X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=shell%2Fcttyhack.c;h=b9ee59bd0c024f7fb7b42dc3c78b092cc51604ba;hb=24bd350aaa3cd593a9a8304042cea689d716aba2;hp=37ea13723eef838e32015bf54ce904db03b9b96f;hpb=816cd16a4ce81ec8d2989a356256f813fc91475d;p=oweals%2Fbusybox.git diff --git a/shell/cttyhack.c b/shell/cttyhack.c index 37ea13723..b9ee59bd0 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c @@ -4,55 +4,56 @@ * * Licensed under GPLv2, see file LICENSE in this source tree. */ -#include "libbb.h" - -//applet:IF_CTTYHACK(APPLET(cttyhack, BB_DIR_BIN, BB_SUID_DROP)) - -//kbuild:lib-$(CONFIG_CTTYHACK) += cttyhack.o - //config:config CTTYHACK -//config: bool "cttyhack" +//config: bool "cttyhack (2.4 kb)" //config: default y //config: help -//config: One common problem reported on the mailing list is the "can't -//config: access tty; job control turned off" error message, which typically -//config: appears when one tries to use a shell with stdin/stdout on -//config: /dev/console. -//config: This device is special - it cannot be a controlling tty. +//config: One common problem reported on the mailing list is the "can't +//config: access tty; job control turned off" error message, which typically +//config: appears when one tries to use a shell with stdin/stdout on +//config: /dev/console. +//config: This device is special - it cannot be a controlling tty. //config: -//config: The proper solution is to use the correct device instead of -//config: /dev/console. +//config: The proper solution is to use the correct device instead of +//config: /dev/console. //config: -//config: cttyhack provides a "quick and dirty" solution to this problem. -//config: It analyzes stdin with various ioctls, trying to determine whether -//config: it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line). -//config: On Linux it also checks sysfs for a pointer to the active console. -//config: If cttyhack is able to find the real console device, it closes -//config: stdin/out/err and reopens that device. -//config: Then it executes the given program. Opening the device will make -//config: that device a controlling tty. This may require cttyhack -//config: to be a session leader. +//config: cttyhack provides a "quick and dirty" solution to this problem. +//config: It analyzes stdin with various ioctls, trying to determine whether +//config: it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line). +//config: On Linux it also checks sysfs for a pointer to the active console. +//config: If cttyhack is able to find the real console device, it closes +//config: stdin/out/err and reopens that device. +//config: Then it executes the given program. Opening the device will make +//config: that device a controlling tty. This may require cttyhack +//config: to be a session leader. //config: -//config: Example for /etc/inittab (for busybox init): +//config: Example for /etc/inittab (for busybox init): //config: -//config: ::respawn:/bin/cttyhack /bin/sh +//config: ::respawn:/bin/cttyhack /bin/sh //config: -//config: Starting an interactive shell from boot shell script: +//config: Starting an interactive shell from boot shell script: //config: -//config: setsid cttyhack sh +//config: setsid cttyhack sh //config: -//config: Giving controlling tty to shell running with PID 1: +//config: Giving controlling tty to shell running with PID 1: //config: -//config: # exec cttyhack sh +//config: # exec cttyhack sh //config: -//config: Without cttyhack, you need to know exact tty name, -//config: and do something like this: +//config: Without cttyhack, you need to know exact tty name, +//config: and do something like this: //config: -//config: # exec setsid sh -c 'exec sh /dev/tty1 2>&1' +//config: # exec setsid sh -c 'exec sh /dev/tty1 2>&1' //config: +//config: Starting getty on a controlling tty from a shell script: +//config: +//config: # getty 115200 $(cttyhack) + +//applet:IF_CTTYHACK(APPLET_NOEXEC(cttyhack, cttyhack, BB_DIR_BIN, BB_SUID_DROP, cttyhack)) + +//kbuild:lib-$(CONFIG_CTTYHACK) += cttyhack.o //usage:#define cttyhack_trivial_usage -//usage: "PROG ARGS" +//usage: "[PROG ARGS]" //usage:#define cttyhack_full_usage "\n\n" //usage: "Give PROG a controlling tty if possible." //usage: "\nExample for /etc/inittab (for busybox init):" @@ -62,6 +63,8 @@ //usage: "\nStarting interactive shell from boot shell script:" //usage: "\n setsid cttyhack sh" +#include "libbb.h" + #if !defined(__linux__) && !defined(TIOCGSERIAL) && !ENABLE_WERROR # warning cttyhack will not be able to detect a controlling tty on this system #endif @@ -108,61 +111,78 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv) char paranoia[sizeof(struct serial_struct) * 3]; } u; - if (!*++argv) { - bb_show_usage(); - } - strcpy(console, "/dev/tty"); fd = open(console, O_RDWR); - if (fd >= 0) { - /* We already have ctty, nothing to do */ - close(fd); - } else { + if (fd < 0) { /* We don't have ctty (or don't have "/dev/tty" node...) */ do { #ifdef __linux__ + /* Note that this method does not use _stdin_. + * Thus, "cttyhack 0) { - /* found active console via sysfs (Linux 2.6.38+) - * sysfs string looks like "ttyS0\n" so zap the newline: + char *last; + /* Found active console via sysfs (Linux 2.6.38+). + * It looks like "[tty0 ]ttyS0\n" so zap the newline: */ console[4 + s] = '\0'; + /* If there are multiple consoles, + * take the last one: + */ + last = strrchr(console + 5, ' '); + if (last) + overlapping_strcpy(console + 5, last + 1); break; } if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { /* this is linux virtual tty */ - sprintf(console + 8, "S%d" + 1, u.vt.v_active); + sprintf(console + 8, "S%u" + 1, (int)u.vt.v_active); break; } #endif #ifdef TIOCGSERIAL if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { - /* this is a serial console, asuming it is named /dev/ttySn */ - sprintf(console + 8, "S%d", u.sr.line); + /* this is a serial console; assuming it is named /dev/ttySn */ + sprintf(console + 8, "S%u", (int)u.sr.line); break; } #endif /* nope, could not find it */ - goto ret; + console[0] = '\0'; } while (0); + } + + argv++; + if (!argv[0]) { + if (!console[0]) + return EXIT_FAILURE; + puts(console); + return EXIT_SUCCESS; + } + if (fd < 0) { fd = open_or_warn(console, O_RDWR); if (fd < 0) goto ret; - //bb_error_msg("switching to '%s'", console); - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - while (fd > 2) - close(fd--); - /* Some other session may have it as ctty, - * steal it from them: - */ - ioctl(0, TIOCSCTTY, 1); } - -ret: + //bb_error_msg("switching to '%s'", console); + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + while (fd > 2) + close(fd--); + /* Some other session may have it as ctty, + * try to steal it from them: + */ + ioctl(0, TIOCSCTTY, 1); + ret: BB_EXECVP_or_die(argv); }