Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/shell/cttyhack.c


Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mindi-busybox/shell/cttyhack.c

    r2725 r3232  
    77#include "libbb.h"
    88
    9 //applet:IF_CTTYHACK(APPLET(cttyhack, _BB_DIR_BIN, _BB_SUID_DROP))
     9//applet:IF_CTTYHACK(APPLET(cttyhack, BB_DIR_BIN, BB_SUID_DROP))
    1010
    1111//kbuild:lib-$(CONFIG_CTTYHACK) += cttyhack.o
     
    1515//config:   default y
    1616//config:   help
    17 //config:     One common problem reported on the mailing list is "can't access tty;
    18 //config:     job control turned off" error message which typically appears when
    19 //config:     one tries to use shell with stdin/stdout opened to /dev/console.
     17//config:     One common problem reported on the mailing list is the "can't
     18//config:     access tty; job control turned off" error message, which typically
     19//config:     appears when one tries to use a shell with stdin/stdout on
     20//config:     /dev/console.
    2021//config:     This device is special - it cannot be a controlling tty.
    2122//config:
    22 //config:     Proper solution is to use correct device instead of /dev/console.
     23//config:     The proper solution is to use the correct device instead of
     24//config:     /dev/console.
    2325//config:
    24 //config:     cttyhack provides "quick and dirty" solution to this problem.
     26//config:     cttyhack provides a "quick and dirty" solution to this problem.
    2527//config:     It analyzes stdin with various ioctls, trying to determine whether
    2628//config:     it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line).
    27 //config:     If it detects one, it closes stdin/out/err and reopens that device.
    28 //config:     Then it executes given program. Opening the device will make
     29//config:     On Linux it also checks sysfs for a pointer to the active console.
     30//config:     If cttyhack is able to find the real console device, it closes
     31//config:     stdin/out/err and reopens that device.
     32//config:     Then it executes the given program. Opening the device will make
    2933//config:     that device a controlling tty. This may require cttyhack
    3034//config:     to be a session leader.
     
    4751//config:     # exec setsid sh -c 'exec sh </dev/tty1 >/dev/tty1 2>&1'
    4852//config:
     53//config:     Starting getty on a controlling tty from a shell script:
     54//config:
     55//config:     # getty 115200 $(cttyhack)
    4956
    5057//usage:#define cttyhack_trivial_usage
    51 //usage:       "PROG ARGS"
     58//usage:       "[PROG ARGS]"
    5259//usage:#define cttyhack_full_usage "\n\n"
    5360//usage:       "Give PROG a controlling tty if possible."
     
    105112    } u;
    106113
    107     if (!*++argv) {
    108         bb_show_usage();
     114    strcpy(console, "/dev/tty");
     115    fd = open(console, O_RDWR);
     116    if (fd < 0) {
     117        /* We don't have ctty (or don't have "/dev/tty" node...) */
     118        do {
     119#ifdef __linux__
     120            /* Note that this method does not use _stdin_.
     121             * Thus, "cttyhack </dev/something" can't be used.
     122             * However, this method is more reliable than
     123             * TIOCGSERIAL check, which assumes that all
     124             * serial lines follow /dev/ttySn convention -
     125             * which is not always the case.
     126             * Therefore, we use this method first:
     127             */
     128            int s = open_read_close("/sys/class/tty/console/active",
     129                console + 5, sizeof(console) - 5);
     130            if (s > 0) {
     131                char *last;
     132                /* Found active console via sysfs (Linux 2.6.38+).
     133                 * It looks like "[tty0 ]ttyS0\n" so zap the newline:
     134                 */
     135                console[4 + s] = '\0';
     136                /* If there are multiple consoles,
     137                 * take the last one:
     138                 */
     139                last = strrchr(console + 5, ' ');
     140                if (last)
     141                    overlapping_strcpy(console + 5, last + 1);
     142                break;
     143            }
     144
     145            if (ioctl(0, VT_GETSTATE, &u.vt) == 0) {
     146                /* this is linux virtual tty */
     147                sprintf(console + 8, "S%u" + 1, (int)u.vt.v_active);
     148                break;
     149            }
     150#endif
     151#ifdef TIOCGSERIAL
     152            if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) {
     153                /* this is a serial console; assuming it is named /dev/ttySn */
     154                sprintf(console + 8, "S%u", (int)u.sr.line);
     155                break;
     156            }
     157#endif
     158            /* nope, could not find it */
     159            console[0] = '\0';
     160        } while (0);
    109161    }
    110162
    111     strcpy(console, "/dev/tty");
    112     fd = open(console, O_RDWR);
    113     if (fd >= 0) {
    114         /* We already have ctty, nothing to do */
    115         close(fd);
    116     } else {
    117         /* We don't have ctty (or don't have "/dev/tty" node...) */
    118         if (0) {}
    119 #ifdef TIOCGSERIAL
    120         else if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) {
    121             /* this is a serial console */
    122             sprintf(console + 8, "S%d", u.sr.line);
    123         }
    124 #endif
    125 #ifdef __linux__
    126         else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) {
    127             /* this is linux virtual tty */
    128             sprintf(console + 8, "S%d" + 1, u.vt.v_active);
    129         }
    130 #endif
    131         if (console[8]) {
    132             fd = xopen(console, O_RDWR);
    133             //bb_error_msg("switching to '%s'", console);
    134             dup2(fd, 0);
    135             dup2(fd, 1);
    136             dup2(fd, 2);
    137             while (fd > 2)
    138                 close(fd--);
    139             /* Some other session may have it as ctty,
    140              * steal it from them:
    141              */
    142             ioctl(0, TIOCSCTTY, 1);
    143         }
     163    argv++;
     164    if (!argv[0]) {
     165        if (!console[0])
     166            return EXIT_FAILURE;
     167        puts(console);
     168        return EXIT_SUCCESS;
    144169    }
    145170
     171    if (fd < 0) {
     172        fd = open_or_warn(console, O_RDWR);
     173        if (fd < 0)
     174            goto ret;
     175    }
     176    //bb_error_msg("switching to '%s'", console);
     177    dup2(fd, 0);
     178    dup2(fd, 1);
     179    dup2(fd, 2);
     180    while (fd > 2)
     181        close(fd--);
     182    /* Some other session may have it as ctty,
     183     * try to steal it from them:
     184     */
     185    ioctl(0, TIOCSCTTY, 1);
     186 ret:
    146187    BB_EXECVP_or_die(argv);
    147188}
Note: See TracChangeset for help on using the changeset viewer.