Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/loginutils/getty.c

    r1765 r2725  
    77 * option added by Eric Rasmussen <ear@usfirst.org> - 12/28/95
    88 *
    9  * 1999-02-22 Arkadiusz Mikiewicz <misiek@misiek.eu.org>
     9 * 1999-02-22 Arkadiusz Mickiewicz <misiek@misiek.eu.org>
    1010 * - added Native Language Support
    11 
     11 *
    1212 * 1999-05-05 Thorsten Kranzkowski <dl8bcu@gmx.net>
    1313 * - enable hardware flow control before displaying /etc/issue
    1414 *
    15  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    16  *
     15 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1716 */
    1817
     
    2120
    2221#if ENABLE_FEATURE_UTMP
    23 #include <utmp.h>
     22# include <utmp.h> /* LOGIN_PROCESS */
     23#endif
     24
     25#ifndef IUCLC
     26# define IUCLC 0
    2427#endif
    2528
     
    2932 */
    3033#ifdef LOGIN_PROCESS                    /* defined in System V utmp.h */
    31 #define SYSV_STYLE                      /* select System V style getty */
    3234#include <sys/utsname.h>
    33 #include <time.h>
    34 #if ENABLE_FEATURE_WTMP
    35 extern void updwtmp(const char *filename, const struct utmp *ut);
    36 static void update_utmp(const char *line);
    37 #endif
     35#else /* if !sysV style, wtmp/utmp code is off */
     36#undef ENABLE_FEATURE_UTMP
     37#undef ENABLE_FEATURE_WTMP
     38#define ENABLE_FEATURE_UTMP 0
     39#define ENABLE_FEATURE_WTMP 0
    3840#endif  /* LOGIN_PROCESS */
    3941
     
    4850/* I doubt there are systems which still need this */
    4951#undef HANDLE_ALLCAPS
     52#undef ANCIENT_BS_KILL_CHARS
    5053
    5154#define _PATH_LOGIN "/bin/login"
     
    5861
    5962/* Some shorthands for control characters. */
    60 #define CTL(x)          (x ^ 0100)      /* Assumes ASCII dialect */
     63#define CTL(x)          ((x) ^ 0100)    /* Assumes ASCII dialect */
    6164#define CR              CTL('M')        /* carriage return */
    6265#define NL              CTL('J')        /* line feed */
     
    7780 * we will try is the first one specified.
    7881 */
    79 #define FIRST_SPEED     0
     82#define MAX_SPEED       10              /* max. nr. of baud rates */
    8083
    8184/* Storage for command-line options. */
    82 
    83 #define MAX_SPEED       10              /* max. nr. of baud rates */
    84 
    8585struct options {
    8686    int flags;                      /* toggle switches, see below */
    8787    unsigned timeout;               /* time-out period */
    88     const char *login;                    /* login program */
    89     const char *tty;                      /* name of tty */
    90     const char *initstring;               /* modem init string */
    91     const char *issue;                    /* alternative issue file */
     88    const char *login;              /* login program */
     89    const char *tty;                /* name of tty */
     90    const char *initstring;         /* modem init string */
     91    const char *issue;              /* alternative issue file */
    9292    int numspeed;                   /* number of baud rates to try */
    9393    int speeds[MAX_SPEED];          /* baud rates to be tried */
    9494};
    95 
    96 static const char opt_string[] ALIGN1 = "I:LH:f:hil:mt:wn";
    97 #define F_INITSTRING    (1<<0)          /* initstring is set */
    98 #define F_LOCAL         (1<<1)          /* force local */
    99 #define F_FAKEHOST      (1<<2)          /* force fakehost */
    100 #define F_CUSTISSUE     (1<<3)          /* give alternative issue file */
    101 #define F_RTSCTS        (1<<4)          /* enable RTS/CTS flow control */
    102 #define F_ISSUE         (1<<5)          /* display /etc/issue */
    103 #define F_LOGIN         (1<<6)          /* non-default login program */
    104 #define F_PARSE         (1<<7)          /* process modem status messages */
    105 #define F_TIMEOUT       (1<<8)          /* time out */
    106 #define F_WAITCRLF      (1<<9)          /* wait for CR or LF */
    107 #define F_NOPROMPT      (1<<10)         /* don't ask for login name! */
    10895
    10996/* Storage for things detected while the login name was read. */
     
    113100    unsigned char eol;      /* end-of-line character */
    114101    unsigned char parity;   /* what parity did we see */
     102    /* (parity & 1): saw odd parity char with 7th bit set */
     103    /* (parity & 2): saw even parity char with 7th bit set */
     104    /* parity == 0: probably 7-bit, space parity? */
     105    /* parity == 1: probably 7-bit, odd parity? */
     106    /* parity == 2: probably 7-bit, even parity? */
     107    /* parity == 3: definitely 8 bit, no parity! */
     108    /* Hmm... with any value of "parity" 8 bit, no parity is possible */
    115109#ifdef HANDLE_ALLCAPS
    116110    unsigned char capslock; /* upper case without lower case */
    117111#endif
    118112};
     113
    119114
    120115/* Initial values for the above. */
     
    129124};
    130125
     126static const char opt_string[] ALIGN1 = "I:LH:f:hil:mt:wn";
     127#define F_INITSTRING    (1 << 0)        /* -I initstring is set */
     128#define F_LOCAL         (1 << 1)        /* -L force local */
     129#define F_FAKEHOST      (1 << 2)        /* -H fake hostname */
     130#define F_CUSTISSUE     (1 << 3)        /* -f give alternative issue file */
     131#define F_RTSCTS        (1 << 4)        /* -h enable RTS/CTS flow control */
     132#define F_ISSUE         (1 << 5)        /* -i display /etc/issue */
     133#define F_LOGIN         (1 << 6)        /* -l non-default login program */
     134#define F_PARSE         (1 << 7)        /* -m process modem status messages */
     135#define F_TIMEOUT       (1 << 8)        /* -t time out */
     136#define F_WAITCRLF      (1 << 9)        /* -w wait for CR or LF */
     137#define F_NOPROMPT      (1 << 10)       /* -n don't ask for login name */
     138
     139
     140#define line_buf bb_common_bufsiz1
     141
    131142/* The following is used for understandable diagnostics. */
    132 
    133 /* Fake hostname for ut_host specified on command line. */
    134 static char *fakehost = NULL;
    135 
    136 /* ... */
    137143#ifdef DEBUGGING
    138 #define debug(s) fprintf(dbf,s); fflush(dbf)
     144static FILE *dbf;
    139145#define DEBUGTERM "/dev/ttyp0"
    140 static FILE *dbf;
     146#define debug(...) do { fprintf(dbf, __VA_ARGS__); fflush(dbf); } while (0)
    141147#else
    142 #define debug(s) /* nothing */
    143 #endif
    144 
    145 
    146 /* bcode - convert speed string to speed code; return 0 on failure */
     148#define debug(...) ((void)0)
     149#endif
     150
     151
     152/* bcode - convert speed string to speed code; return <= 0 on failure */
    147153static int bcode(const char *s)
    148154{
    149     int r;
    150     unsigned value = bb_strtou(s, NULL, 10);
    151     if (errno) {
    152         return -1;
    153     }
    154     r = tty_value_to_baud(value);
    155     if (r > 0) {
    156         return r;
    157     }
    158     return 0;
    159 }
    160 
     155    int value = bb_strtou(s, NULL, 10); /* yes, int is intended! */
     156    if (value < 0) /* bad terminating char, overflow, etc */
     157        return value;
     158    return tty_value_to_baud(value);
     159}
    161160
    162161/* parse_speeds - parse alternate baud rates */
     
    165164    char *cp;
    166165
     166    /* NB: at least one iteration is always done */
    167167    debug("entered parse_speeds\n");
    168     for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) {
    169         if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0)
     168    while ((cp = strsep(&arg, ",")) != NULL) {
     169        op->speeds[op->numspeed] = bcode(cp);
     170        if (op->speeds[op->numspeed] < 0)
    170171            bb_error_msg_and_die("bad speed: %s", cp);
     172        /* note: arg "0" turns into speed B0 */
     173        op->numspeed++;
    171174        if (op->numspeed > MAX_SPEED)
    172175            bb_error_msg_and_die("too many alternate speeds");
    173176    }
    174     debug("exiting parsespeeds\n");
    175 }
    176 
     177    debug("exiting parse_speeds\n");
     178}
    177179
    178180/* parse_args - parse command-line arguments */
    179 static void parse_args(int argc, char **argv, struct options *op)
     181static void parse_args(char **argv, struct options *op, char **fakehost_p)
    180182{
    181183    char *ts;
    182184
     185    opt_complementary = "-2:t+"; /* at least 2 args; -t N */
    183186    op->flags = getopt32(argv, opt_string,
    184         &(op->initstring), &fakehost, &(op->issue),
    185         &(op->login), &ts);
     187        &(op->initstring), fakehost_p, &(op->issue),
     188        &(op->login), &op->timeout);
     189    argv += optind;
    186190    if (op->flags & F_INITSTRING) {
    187         const char *p = op->initstring;
    188         char *q;
    189 
    190         op->initstring = q = xstrdup(op->initstring);
    191         /* copy optarg into op->initstring decoding \ddd
    192            octal codes into chars */
    193         while (*p) {
    194             if (*p == '\\') {
    195                 p++;
    196                 *q++ = bb_process_escape_sequence(&p);
    197             } else {
    198                 *q++ = *p++;
    199             }
    200         }
    201         *q = '\0';
    202     }
    203     op->flags ^= F_ISSUE;           /* revert flag show /etc/issue */
    204     if (op->flags & F_TIMEOUT) {
    205         op->timeout = xatoul_range(ts, 1, INT_MAX);
    206     }
    207     argv += optind;
    208     argc -= optind;
    209     debug("after getopt loop\n");
    210     if (argc < 2)          /* check parameter count */
    211         bb_show_usage();
     191        op->initstring = xstrdup(op->initstring);
     192        /* decode \ddd octal codes into chars */
     193        strcpy_and_process_escape_sequences((char*)op->initstring, op->initstring);
     194    }
     195    op->flags ^= F_ISSUE;           /* invert flag "show /etc/issue" */
     196    debug("after getopt\n");
    212197
    213198    /* we loosen up a bit and accept both "baudrate tty" and "tty baudrate" */
     199    op->tty = argv[0];      /* tty name */
     200    ts = argv[1];           /* baud rate(s) */
    214201    if (isdigit(argv[0][0])) {
    215202        /* a number first, assume it's a speed (BSD style) */
    216         parse_speeds(op, argv[0]);       /* baud rate(s) */
    217         op->tty = argv[1]; /* tty name */
    218     } else {
    219         op->tty = argv[0];       /* tty name */
    220         parse_speeds(op, argv[1]); /* baud rate(s) */
    221     }
     203        op->tty = ts;   /* tty name is in argv[1] */
     204        ts = argv[0];   /* baud rate(s) */
     205    }
     206    parse_speeds(op, ts);
     207    applet_name = xasprintf("getty: %s", op->tty);
    222208
    223209    if (argv[2])
    224         setenv("TERM", argv[2], 1);
    225 
    226     debug("exiting parseargs\n");
     210        xsetenv("TERM", argv[2]);
     211
     212    debug("exiting parse_args\n");
    227213}
    228214
    229215/* open_tty - set up tty as standard { input, output, error } */
    230 static void open_tty(const char *tty, struct termios *tp, int local)
    231 {
    232     int chdir_to_root = 0;
    233 
     216static void open_tty(const char *tty)
     217{
    234218    /* Set up new standard input, unless we are given an already opened port. */
    235219    if (NOT_LONE_DASH(tty)) {
    236         struct stat st;
    237         int fd;
     220//      struct stat st;
     221//      int cur_dir_fd;
     222//      int fd;
    238223
    239224        /* Sanity checks... */
    240         xchdir("/dev");
    241         chdir_to_root = 1;
    242         xstat(tty, &st);
    243         if ((st.st_mode & S_IFMT) != S_IFCHR)
    244             bb_error_msg_and_die("%s: not a character device", tty);
     225//      cur_dir_fd = xopen(".", O_DIRECTORY | O_NONBLOCK);
     226//      xchdir("/dev");
     227//      xstat(tty, &st);
     228//      if (!S_ISCHR(st.st_mode))
     229//          bb_error_msg_and_die("not a character device");
     230
     231        if (tty[0] != '/')
     232            tty = xasprintf("/dev/%s", tty); /* will leak it */
    245233
    246234        /* Open the tty as standard input. */
    247235        debug("open(2)\n");
    248         fd = xopen(tty, O_RDWR | O_NONBLOCK);
    249         xdup2(fd, 0);
    250         while (fd > 2)
    251             close(fd--);
     236        close(0);
     237        /*fd =*/ xopen(tty, O_RDWR | O_NONBLOCK); /* uses fd 0 */
     238
     239//      /* Restore current directory */
     240//      fchdir(cur_dir_fd);
     241
     242        /* Open the tty as standard input, continued */
     243//      xmove_fd(fd, 0);
     244//      /* fd is >= cur_dir_fd, and cur_dir_fd gets closed too here: */
     245//      while (fd > 2)
     246//          close(fd--);
     247
     248        /* Set proper protections and ownership. */
     249        fchown(0, 0, 0);        /* 0:0 */
     250        fchmod(0, 0620);        /* crw--w---- */
    252251    } else {
    253252        /*
     
    258257            bb_error_msg_and_die("stdin is not open for read/write");
    259258    }
    260 
    261     /* Replace current standard output/error fd's with new ones */
    262     debug("duping\n");
    263     xdup2(0, 1);
    264     xdup2(0, 2);
    265 
    266     /*
    267      * The following ioctl will fail if stdin is not a tty, but also when
    268      * there is noise on the modem control lines. In the latter case, the
    269      * common course of action is (1) fix your cables (2) give the modem more
    270      * time to properly reset after hanging up. SunOS users can achieve (2)
    271      * by patching the SunOS kernel variable "zsadtrlow" to a larger value;
    272      * 5 seconds seems to be a good value.
    273      */
    274     ioctl_or_perror_and_die(0, TCGETS, tp, "%s: TCGETS", tty);
    275 
    276     /*
    277      * It seems to be a terminal. Set proper protections and ownership. Mode
    278      * 0622 is suitable for SYSV <4 because /bin/login does not change
    279      * protections. SunOS 4 login will change the protections to 0620 (write
    280      * access for group tty) after the login has succeeded.
    281      */
    282 
    283 #ifdef DEBIAN
    284 #warning Debian /dev/vcs[a]NN hack is deprecated and will be removed
    285     {
    286         /* tty to root.dialout 660 */
    287         struct group *gr;
    288         int id;
    289 
    290         gr = getgrnam("dialout");
    291         id = gr ? gr->gr_gid : 0;
    292         chown(tty, 0, id);
    293         chmod(tty, 0660);
    294 
    295         /* vcs,vcsa to root.sys 600 */
    296         if (!strncmp(tty, "tty", 3) && isdigit(tty[3])) {
    297             char *vcs, *vcsa;
    298 
    299             vcs = xstrdup(tty);
    300             vcsa = xmalloc(strlen(tty) + 2);
    301             strcpy(vcs, "vcs");
    302             strcpy(vcs + 3, tty + 3);
    303             strcpy(vcsa, "vcsa");
    304             strcpy(vcsa + 4, tty + 3);
    305 
    306             gr = getgrnam("sys");
    307             id = gr ? gr->gr_gid : 0;
    308             chown(vcs, 0, id);
    309             chmod(vcs, 0600);
    310             chown(vcsa, 0, id);
    311             chmod(vcs, 0600);
    312 
    313             free(vcs);
    314             free(vcsa);
    315         }
    316     }
    317 #else
    318     if (NOT_LONE_DASH(tty)) {
    319         chown(tty, 0, 0);        /* 0:0 */
    320         chmod(tty, 0622);        /* crw--w--w- */
    321     }
    322 #endif
    323     if (chdir_to_root)
    324         xchdir("/");
    325259}
    326260
     
    328262static void termios_init(struct termios *tp, int speed, struct options *op)
    329263{
     264    speed_t ispeed, ospeed;
    330265    /*
    331266     * Initial termios settings: 8-bit characters, raw-mode, blocking i/o.
     
    334269     * later on.
    335270     */
    336 #ifdef __linux__
    337271    /* flush input and output queues, important for modems! */
    338     ioctl(0, TCFLSH, TCIOFLUSH);
    339 #endif
    340 
    341     tp->c_cflag = CS8 | HUPCL | CREAD | speed;
    342     if (op->flags & F_LOCAL) {
     272    tcflush(0, TCIOFLUSH);
     273    ispeed = ospeed = speed;
     274    if (speed == B0) {
     275        /* Speed was specified as "0" on command line.
     276         * Just leave it unchanged */
     277        ispeed = cfgetispeed(tp);
     278        ospeed = cfgetospeed(tp);
     279    }
     280    tp->c_cflag = CS8 | HUPCL | CREAD;
     281    if (op->flags & F_LOCAL)
    343282        tp->c_cflag |= CLOCAL;
    344     }
    345 
    346     tp->c_iflag = tp->c_lflag = tp->c_line = 0;
     283    cfsetispeed(tp, ispeed);
     284    cfsetospeed(tp, ospeed);
     285
     286    tp->c_iflag = tp->c_lflag = 0;
    347287    tp->c_oflag = OPOST | ONLCR;
    348288    tp->c_cc[VMIN] = 1;
    349289    tp->c_cc[VTIME] = 0;
     290#ifdef __linux__
     291    tp->c_line = 0;
     292#endif
    350293
    351294    /* Optionally enable hardware flow control */
    352 
    353 #ifdef  CRTSCTS
     295#ifdef CRTSCTS
    354296    if (op->flags & F_RTSCTS)
    355297        tp->c_cflag |= CRTSCTS;
    356298#endif
    357299
    358     ioctl(0, TCSETS, tp);
    359 
    360     /* go to blocking input even in local mode */
    361     ndelay_off(0);
     300    tcsetattr_stdin_TCSANOW(tp);
    362301
    363302    debug("term_io 2\n");
     
    392331     * be dealt with later on.
    393332     */
    394 
    395333    iflag = tp->c_iflag;
    396334    tp->c_iflag |= ISTRIP;          /* enable 8th-bit stripping */
    397335    vmin = tp->c_cc[VMIN];
    398     tp->c_cc[VMIN] = 0;                     /* don't block if queue empty */
    399     ioctl(0, TCSETS, tp);
     336    tp->c_cc[VMIN] = 0;             /* don't block if queue empty */
     337    tcsetattr_stdin_TCSANOW(tp);
    400338
    401339    /*
     
    403341     * try to extract the speed of the dial-in call.
    404342     */
    405 
    406343    sleep(1);
    407     nread = read(0, buf, size_buf - 1);
     344    nread = safe_read(STDIN_FILENO, buf, size_buf - 1);
    408345    if (nread > 0) {
    409346        buf[nread] = '\0';
    410347        for (bp = buf; bp < buf + nread; bp++) {
    411             if (isascii(*bp) && isdigit(*bp)) {
     348            if (isdigit(*bp)) {
    412349                speed = bcode(bp);
    413                 if (speed) {
    414                     tp->c_cflag &= ~CBAUD;
    415                     tp->c_cflag |= speed;
    416                 }
     350                if (speed > 0)
     351                    cfsetspeed(tp, speed);
    417352                break;
    418353            }
    419354        }
    420355    }
     356
    421357    /* Restore terminal settings. Errors will be dealt with later on. */
    422 
    423358    tp->c_iflag = iflag;
    424359    tp->c_cc[VMIN] = vmin;
    425     ioctl(0, TCSETS, tp);
    426 }
    427 
    428 /* next_speed - select next baud rate */
    429 static void next_speed(struct termios *tp, struct options *op)
    430 {
    431     static int baud_index = FIRST_SPEED;    /* current speed index */
    432 
    433     baud_index = (baud_index + 1) % op->numspeed;
    434     tp->c_cflag &= ~CBAUD;
    435     tp->c_cflag |= op->speeds[baud_index];
    436     ioctl(0, TCSETS, tp);
    437 }
    438 
     360    tcsetattr_stdin_TCSANOW(tp);
     361}
    439362
    440363/* do_prompt - show login prompt, optionally preceded by /etc/issue contents */
    441 static void do_prompt(struct options *op, struct termios *tp)
     364static void do_prompt(struct options *op)
    442365{
    443366#ifdef ISSUE
     
    448371
    449372#ifdef HANDLE_ALLCAPS
    450 /* caps_lock - string contains upper case without lower case */
     373/* all_is_upcase - string contains upper case without lower case */
    451374/* returns 1 if true, 0 if false */
    452 static int caps_lock(const char *s)
     375static int all_is_upcase(const char *s)
    453376{
    454377    while (*s)
     
    459382#endif
    460383
    461 /* get_logname - get user name, establish parity, speed, erase, kill, eol */
    462 /* return NULL on failure, logname on success */
     384/* get_logname - get user name, establish parity, speed, erase, kill, eol;
     385 * return NULL on BREAK, logname on success */
    463386static char *get_logname(char *logname, unsigned size_logname,
    464         struct options *op, struct chardata *cp, struct termios *tp)
     387        struct options *op, struct chardata *cp)
    465388{
    466389    char *bp;
    467     char c;             /* input character, full eight bits */
     390    char c;                         /* input character, full eight bits */
    468391    char ascval;                    /* low 7 bits of input character */
    469392    int bits;                       /* # of "1" bits per character */
    470393    int mask;                       /* mask with 1 bit up */
    471     static const char erase[][3] = {    /* backspace-space-backspace */
     394    static const char erase[][3] = {/* backspace-space-backspace */
    472395        "\010\040\010",                 /* space parity */
    473396        "\010\040\010",                 /* odd parity */
    474397        "\210\240\210",                 /* even parity */
    475         "\210\240\210",                 /* no parity */
     398        "\010\040\010",                 /* 8 bit no parity */
    476399    };
    477400
    478     /* Initialize kill, erase, parity etc. (also after switching speeds). */
    479 
    480     *cp = init_chardata;
     401    /* NB: *cp is pre-initialized with init_chardata */
    481402
    482403    /* Flush pending input (esp. after parsing or switching the baud rate). */
    483 
    484404    sleep(1);
    485     ioctl(0, TCFLSH, TCIFLUSH);
     405    tcflush(0, TCIOFLUSH);
    486406
    487407    /* Prompt for and read a login name. */
    488 
    489408    logname[0] = '\0';
    490409    while (!logname[0]) {
    491 
    492410        /* Write issue file and prompt, with "parity" bit == 0. */
    493 
    494         do_prompt(op, tp);
     411        do_prompt(op);
    495412
    496413        /* Read name, watch for break, parity, erase, kill, end-of-line. */
    497 
    498414        bp = logname;
    499415        cp->eol = '\0';
     
    501417
    502418            /* Do not report trivial EINTR/EIO errors. */
    503             if (read(0, &c, 1) < 1) {
     419            errno = EINTR; /* make read of 0 bytes be silent too */
     420            if (read(STDIN_FILENO, &c, 1) < 1) {
    504421                if (errno == EINTR || errno == EIO)
    505                     exit(0);
    506                 bb_perror_msg_and_die("%s: read", op->tty);
     422                    exit(EXIT_SUCCESS);
     423                bb_perror_msg_and_die(bb_msg_read_error);
    507424            }
    508425
    509             /* Do BREAK handling elsewhere. */
     426            /* BREAK. If we have speeds to try,
     427             * return NULL (will switch speeds and return here) */
    510428            if (c == '\0' && op->numspeed > 1)
    511429                return NULL;
    512430
    513431            /* Do parity bit handling. */
    514             ascval = c & 0177;
    515             if (c != ascval) {       /* "parity" bit on ? */
     432            if (!(op->flags & F_LOCAL) && (c & 0x80)) {       /* "parity" bit on? */
    516433                bits = 1;
    517434                mask = 1;
    518                 while (mask & 0177) {
    519                     if (mask & ascval)
     435                while (mask & 0x7f) {
     436                    if (mask & c)
    520437                        bits++; /* count "1" bits */
    521438                    mask <<= 1;
     
    526443
    527444            /* Do erase, kill and end-of-line processing. */
     445            ascval = c & 0x7f;
    528446            switch (ascval) {
    529447            case CR:
     
    534452            case BS:
    535453            case DEL:
     454#ifdef ANCIENT_BS_KILL_CHARS
    536455            case '#':
     456#endif
    537457                cp->erase = ascval;     /* set erase character */
    538458                if (bp > logname) {
    539                     write(1, erase[cp->parity], 3);
     459                    full_write(STDOUT_FILENO, erase[cp->parity], 3);
    540460                    bp--;
    541461                }
    542462                break;
    543463            case CTL('U'):
     464#ifdef ANCIENT_BS_KILL_CHARS
    544465            case '@':
     466#endif
    545467                cp->kill = ascval;      /* set kill character */
    546468                while (bp > logname) {
    547                     write(1, erase[cp->parity], 3);
     469                    full_write(STDOUT_FILENO, erase[cp->parity], 3);
    548470                    bp--;
    549471                }
    550472                break;
    551473            case CTL('D'):
    552                 exit(0);
     474                exit(EXIT_SUCCESS);
    553475            default:
    554                 if (!isascii(ascval) || !isprint(ascval)) {
     476                if (ascval < ' ') {
    555477                    /* ignore garbage characters */
    556                 } else if (bp - logname >= size_logname - 1) {
    557                     bb_error_msg_and_die("%s: input overrun", op->tty);
     478                } else if ((int)(bp - logname) >= size_logname - 1) {
     479                    bb_error_msg_and_die("input overrun");
    558480                } else {
    559                     write(1, &c, 1); /* echo the character */
     481                    full_write(STDOUT_FILENO, &c, 1); /* echo the character */
    560482                    *bp++ = ascval; /* and store it */
    561483                }
     
    567489
    568490#ifdef HANDLE_ALLCAPS
    569     cp->capslock = caps_lock(logname);
     491    cp->capslock = all_is_upcase(logname);
    570492    if (cp->capslock) {
    571493        for (bp = logname; *bp; bp++)
     
    581503{
    582504    /* General terminal-independent stuff. */
    583 
    584505    tp->c_iflag |= IXON | IXOFF;    /* 2-way flow control */
    585506    tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE;
     
    591512    tp->c_cc[VEOF] = DEF_EOF;       /* default EOF character */
    592513    tp->c_cc[VEOL] = DEF_EOL;
     514#ifdef VSWTC
    593515    tp->c_cc[VSWTC] = DEF_SWITCH;   /* default switch character */
     516#endif
    594517
    595518    /* Account for special characters seen in input. */
    596 
    597519    if (cp->eol == CR) {
    598520        tp->c_iflag |= ICRNL;   /* map CR in input to NL */
     
    603525
    604526    /* Account for the presence or absence of parity bits in input. */
    605 
    606527    switch (cp->parity) {
    607528    case 0:                                 /* space (always 0) parity */
     529// I bet most people go here - they use only 7-bit chars in usernames....
    608530        break;
    609531    case 1:                                 /* odd parity */
     
    617539        tp->c_cflag &= ~CSIZE;
    618540        tp->c_cflag |= CS7;
     541// FIXME: wtf? case 3: we saw both even and odd 8-bit bytes -
     542// it's probably some umlauts etc, but definitely NOT 7-bit!!!
     543// Entire parity detection madness here just begs for deletion...
    619544        break;
    620545    }
     
    629554#endif
    630555    /* Optionally enable hardware flow control */
    631 
    632 #ifdef  CRTSCTS
     556#ifdef CRTSCTS
    633557    if (op->flags & F_RTSCTS)
    634558        tp->c_cflag |= CRTSCTS;
     
    636560
    637561    /* Finally, make the new settings effective */
    638 
    639     ioctl_or_perror_and_die(0, TCSETS, tp, "%s: TCSETS", op->tty);
    640 }
    641 
    642 
    643 #ifdef SYSV_STYLE
    644 #if ENABLE_FEATURE_UTMP
    645 /* update_utmp - update our utmp entry */
    646 static void update_utmp(const char *line)
    647 {
    648     struct utmp ut;
    649     struct utmp *utp;
    650     time_t t;
    651     int mypid = getpid();
    652 
    653     /*
    654      * The utmp file holds miscellaneous information about things started by
    655      * /sbin/init and other system-related events. Our purpose is to update
    656      * the utmp entry for the current process, in particular the process type
    657      * and the tty line we are listening to. Return successfully only if the
    658      * utmp file can be opened for update, and if we are able to find our
    659      * entry in the utmp file.
    660      */
    661     if (access(_PATH_UTMP, R_OK|W_OK) == -1) {
    662         close(creat(_PATH_UTMP, 0664));
    663     }
    664     utmpname(_PATH_UTMP);
    665     setutent();
    666     while ((utp = getutent())
    667            && !(utp->ut_type == INIT_PROCESS && utp->ut_pid == mypid))
    668         /* nothing */;
    669 
    670     if (utp) {
    671         memcpy(&ut, utp, sizeof(ut));
    672     } else {
    673         /* some inits don't initialize utmp... */
    674         memset(&ut, 0, sizeof(ut));
    675         safe_strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
    676     }
    677     /* endutent(); */
    678 
    679     strcpy(ut.ut_user, "LOGIN");
    680     safe_strncpy(ut.ut_line, line, sizeof(ut.ut_line));
    681     if (fakehost)
    682         safe_strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host));
    683     time(&t);
    684     ut.ut_time = t;
    685     ut.ut_type = LOGIN_PROCESS;
    686     ut.ut_pid = mypid;
    687 
    688     pututline(&ut);
    689     endutent();
    690 
    691 #if ENABLE_FEATURE_WTMP
    692     if (access(bb_path_wtmp_file, R_OK|W_OK) == -1)
    693         close(creat(bb_path_wtmp_file, 0664));
    694     updwtmp(bb_path_wtmp_file, &ut);
    695 #endif
    696 }
    697 
    698 #endif /* CONFIG_FEATURE_UTMP */
    699 #endif /* SYSV_STYLE */
    700 
    701 
    702 int getty_main(int argc, char **argv);
    703 int getty_main(int argc, char **argv)
    704 {
    705     int nullfd;
    706     char *logname = NULL;           /* login name, given to /bin/login */
     562    if (tcsetattr_stdin_TCSANOW(tp) < 0)
     563        bb_perror_msg_and_die("tcsetattr");
     564}
     565
     566int getty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     567int getty_main(int argc UNUSED_PARAM, char **argv)
     568{
     569    int n;
     570    pid_t pid;
     571    char *fakehost = NULL;          /* Fake hostname for ut_host */
     572    char *logname;                  /* login name, given to /bin/login */
    707573    /* Merging these into "struct local" may _seem_ to reduce
    708574     * parameter passing, but today's gcc will inline
    709575     * statics which are called once anyway, so don't do that */
    710576    struct chardata chardata;       /* set by get_logname() */
    711     struct termios termios;           /* terminal mode bits */
    712     struct options options = {
    713         0,                      /* show /etc/issue (SYSV_STYLE) */
    714         0,                      /* no timeout */
    715         _PATH_LOGIN,            /* default login program */
    716         "tty1",                 /* default tty line */
    717         "",                     /* modem init string */
     577    struct termios termios;         /* terminal mode bits */
     578    struct options options;
     579
     580    chardata = init_chardata;
     581
     582    memset(&options, 0, sizeof(options));
     583    options.login = _PATH_LOGIN;    /* default login program */
     584    options.tty = "tty1";           /* default tty line */
     585    options.initstring = "";        /* modem init string */
    718586#ifdef ISSUE
    719         ISSUE,                  /* default issue file */
    720 #else
    721         NULL,
    722 #endif
    723         0,                      /* no baud rates known yet */
    724     };
    725 
    726     /* Already too late because of theoretical
    727      * possibility of getty --help somehow triggered
    728      * inadvertently before we reach this. Oh well. */
     587    options.issue = ISSUE;          /* default issue file */
     588#endif
     589
     590    /* Parse command-line arguments. */
     591    parse_args(argv, &options, &fakehost);
     592
    729593    logmode = LOGMODE_NONE;
     594
     595    /* Create new session, lose controlling tty, if any */
     596    /* docs/ctty.htm says:
     597     * "This is allowed only when the current process
     598     *  is not a process group leader" - is this a problem? */
    730599    setsid();
    731     nullfd = xopen(bb_dev_null, O_RDWR);
    732     /* dup2(nullfd, 0); - no, because of possible "getty - 9600" */
    733     /* open_tty() will take care of fd# 0 anyway */
    734     dup2(nullfd, 1);
    735     dup2(nullfd, 2);
    736     while (nullfd > 2) close(nullfd--);
    737     /* We want special flavor of error_msg_and_die */
     600    /* close stdio, and stray descriptors, just in case */
     601    n = xopen(bb_dev_null, O_RDWR);
     602    /* dup2(n, 0); - no, we need to handle "getty - 9600" too */
     603    xdup2(n, 1);
     604    xdup2(n, 2);
     605    while (n > 2)
     606        close(n--);
     607
     608    /* Logging. We want special flavor of error_msg_and_die */
    738609    die_sleep = 10;
    739610    msg_eol = "\r\n";
     611    /* most likely will internally use fd #3 in CLOEXEC mode: */
    740612    openlog(applet_name, LOG_PID, LOG_AUTH);
    741613    logmode = LOGMODE_BOTH;
    742614
    743615#ifdef DEBUGGING
    744     dbf = xfopen(DEBUGTERM, "w");
    745 
    746     {
    747         int i;
    748 
    749         for (i = 1; i < argc; i++) {
    750             debug(argv[i]);
    751             debug("\n");
    752         }
    753     }
    754 #endif
    755 
    756     /* Parse command-line arguments. */
    757     parse_args(argc, argv, &options);
    758 
    759 #ifdef SYSV_STYLE
    760 #if ENABLE_FEATURE_UTMP
    761     /* Update the utmp file. */
    762     update_utmp(options.tty);
    763 #endif
    764 #endif
    765 
     616    dbf = xfopen_for_write(DEBUGTERM);
     617    for (n = 1; argv[n]; n++) {
     618        debug(argv[n]);
     619        debug("\n");
     620    }
     621#endif
     622
     623    /* Open the tty as standard input, if it is not "-" */
     624    /* If it's not "-" and not taken yet, it will become our ctty */
    766625    debug("calling open_tty\n");
    767     /* Open the tty as standard { input, output, error }. */
    768     open_tty(options.tty, &termios, options.flags & F_LOCAL);
    769 
     626    open_tty(options.tty);
     627    ndelay_off(0);
     628    debug("duping\n");
     629    xdup2(0, 1);
     630    xdup2(0, 2);
     631
     632    /*
     633     * The following ioctl will fail if stdin is not a tty, but also when
     634     * there is noise on the modem control lines. In the latter case, the
     635     * common course of action is (1) fix your cables (2) give the modem more
     636     * time to properly reset after hanging up. SunOS users can achieve (2)
     637     * by patching the SunOS kernel variable "zsadtrlow" to a larger value;
     638     * 5 seconds seems to be a good value.
     639     */
     640    if (tcgetattr(0, &termios) < 0)
     641        bb_perror_msg_and_die("tcgetattr");
     642
     643    pid = getpid();
    770644#ifdef __linux__
    771     {
    772         int iv;
    773 
    774         iv = getpid();
    775         ioctl(0, TIOCSPGRP, &iv);
    776     }
    777 #endif
     645// FIXME: do we need this? Otherwise "-" case seems to be broken...
     646    // /* Forcibly make fd 0 our controlling tty, even if another session
     647    //  * has it as a ctty. (Another session loses ctty). */
     648    // ioctl(0, TIOCSCTTY, (void*)1);
     649    /* Make ourself a foreground process group within our session */
     650    tcsetpgrp(0, pid);
     651#endif
     652
     653    /* Update the utmp file. This tty is ours now! */
     654    update_utmp(pid, LOGIN_PROCESS, options.tty, "LOGIN", fakehost);
     655
    778656    /* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */
    779657    debug("calling termios_init\n");
    780     termios_init(&termios, options.speeds[FIRST_SPEED], &options);
    781 
    782     /* write the modem init string and DON'T flush the buffers */
     658    termios_init(&termios, options.speeds[0], &options);
     659
     660    /* Write the modem init string and DON'T flush the buffers */
    783661    if (options.flags & F_INITSTRING) {
    784662        debug("writing init string\n");
    785         write(1, options.initstring, strlen(options.initstring));
    786     }
    787 
    788     if (!(options.flags & F_LOCAL)) {
    789         /* go to blocking write mode unless -L is specified */
    790         ndelay_off(1);
    791     }
    792 
    793     /* Optionally detect the baud rate from the modem status message. */
     663        full_write1_str(options.initstring);
     664    }
     665
     666    /* Optionally detect the baud rate from the modem status message */
    794667    debug("before autobaud\n");
    795668    if (options.flags & F_PARSE)
    796         auto_baud(bb_common_bufsiz1, sizeof(bb_common_bufsiz1), &termios);
    797 
    798     /* Set the optional timer. */
    799     if (options.timeout)
    800         alarm(options.timeout);
    801 
    802     /* optionally wait for CR or LF before writing /etc/issue */
     669        auto_baud(line_buf, sizeof(line_buf), &termios);
     670
     671    /* Set the optional timer */
     672    alarm(options.timeout); /* if 0, alarm is not set */
     673
     674    /* Optionally wait for CR or LF before writing /etc/issue */
    803675    if (options.flags & F_WAITCRLF) {
    804676        char ch;
    805677
    806678        debug("waiting for cr-lf\n");
    807         while (read(0, &ch, 1) == 1) {
     679        while (safe_read(STDIN_FILENO, &ch, 1) == 1) {
     680            debug("read %x\n", (unsigned char)ch);
    808681            ch &= 0x7f;                     /* strip "parity bit" */
    809 #ifdef DEBUGGING
    810             fprintf(dbf, "read %c\n", ch);
    811 #endif
    812682            if (ch == '\n' || ch == '\r')
    813683                break;
     
    815685    }
    816686
    817     chardata = init_chardata;
     687    logname = NULL;
    818688    if (!(options.flags & F_NOPROMPT)) {
    819         /* Read the login name. */
    820         debug("reading login name\n");
    821         logname = get_logname(bb_common_bufsiz1, sizeof(bb_common_bufsiz1),
    822                 &options, &chardata, &termios);
    823         while (logname == NULL)
    824             next_speed(&termios, &options);
     689        /* NB:termios_init already set line speed
     690         * to options.speeds[0] */
     691        int baud_index = 0;
     692
     693        while (1) {
     694            /* Read the login name. */
     695            debug("reading login name\n");
     696            logname = get_logname(line_buf, sizeof(line_buf),
     697                    &options, &chardata);
     698            if (logname)
     699                break;
     700            /* we are here only if options.numspeed > 1 */
     701            baud_index = (baud_index + 1) % options.numspeed;
     702            cfsetispeed(&termios, options.speeds[baud_index]);
     703            cfsetospeed(&termios, options.speeds[baud_index]);
     704            tcsetattr_stdin_TCSANOW(&termios);
     705        }
    825706    }
    826707
    827708    /* Disable timer. */
    828 
    829     if (options.timeout)
    830         alarm(0);
     709    alarm(0);
    831710
    832711    /* Finalize the termios settings. */
    833 
    834712    termios_final(&options, &termios, &chardata);
    835713
    836714    /* Now the newline character should be properly written. */
    837 
    838     write(1, "\n", 1);
     715    full_write(STDOUT_FILENO, "\n", 1);
    839716
    840717    /* Let the login program take care of password validation. */
    841 
    842     execl(options.login, options.login, "--", logname, (char *) 0);
    843     bb_error_msg_and_die("%s: can't exec %s", options.tty, options.login);
    844 }
     718    /* We use PATH because we trust that root doesn't set "bad" PATH,
     719     * and getty is not suid-root applet. */
     720    /* With -n, logname == NULL, and login will ask for username instead */
     721    BB_EXECLP(options.login, options.login, "--", logname, NULL);
     722    bb_error_msg_and_die("can't execute '%s'", options.login);
     723}
Note: See TracChangeset for help on using the changeset viewer.