X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=shell%2Fcttyhack.c;h=f9b59c26321906d9b7039fc977ebf80cbe8ca6b4;hb=ee0d4cd8cb64a4ef7f10a89c7d51145d44cc6d49;hp=3a78bae29fde072c8d1ed3d1bab6f2a696e9f0b8;hpb=430ba79c39eeed4725c36e9c2ad61c438c8a5d3e;p=oweals%2Fbusybox.git diff --git a/shell/cttyhack.c b/shell/cttyhack.c index 3a78bae29..f9b59c263 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c @@ -1,12 +1,12 @@ /* vi: set sw=4 ts=4: */ /* - * Licensed under GPLv2 - * * Copyright (c) 2007 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. */ #include "libbb.h" -//applet:IF_CTTYHACK(APPLET(cttyhack, _BB_DIR_BIN, _BB_SUID_DROP)) +//applet:IF_CTTYHACK(APPLET(cttyhack, BB_DIR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_CTTYHACK) += cttyhack.o @@ -14,18 +14,22 @@ //config: bool "cttyhack" //config: default y //config: help -//config: One common problem reported on the mailing list is "can't access tty; -//config: job control turned off" error message which typically appears when -//config: one tries to use shell with stdin/stdout opened to /dev/console. +//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: Proper solution is to use correct device instead of /dev/console. +//config: The proper solution is to use the correct device instead of +//config: /dev/console. //config: -//config: cttyhack provides "quick and dirty" solution to this problem. +//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: If it detects one, it closes stdin/out/err and reopens that device. -//config: Then it executes given program. Opening the device will make +//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: @@ -46,9 +50,12 @@ //config: //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) //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):" @@ -58,7 +65,7 @@ //usage: "\nStarting interactive shell from boot shell script:" //usage: "\n setsid cttyhack sh" -#if !defined(__linux__) && !defined(TIOCGSERIAL) +#if !defined(__linux__) && !defined(TIOCGSERIAL) && !ENABLE_WERROR # warning cttyhack will not be able to detect a controlling tty on this system #endif @@ -104,44 +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...) */ - if (0) {} -#ifdef TIOCGSERIAL - else if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { - /* this is a serial console */ - sprintf(console + 8, "S%d", u.sr.line); - } -#endif + do { #ifdef __linux__ - else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { - /* this is linux virtual tty */ - sprintf(console + 8, "S%d" + 1, u.vt.v_active); - } -#endif - if (console[8]) { - fd = xopen(console, O_RDWR); - //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: + /* Note that this method does not use _stdin_. + * Thus, "cttyhack 0) { + 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%u" + 1, (int)u.vt.v_active); + break; + } +#endif +#ifdef TIOCGSERIAL + if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { + /* 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 */ + 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, + * try to steal it from them: + */ + ioctl(0, TIOCSCTTY, 1); + ret: BB_EXECVP_or_die(argv); }