diff options
-rw-r--r-- | loginutils/getty.c | 527 |
1 files changed, 260 insertions, 267 deletions
diff --git a/loginutils/getty.c b/loginutils/getty.c index 43a82df66..11eb5a050 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c @@ -212,20 +212,6 @@ static struct Speedtab speedtab[] = { }; #endif -static void parse_args(int argc, char **argv, struct options *op); -static void parse_speeds(struct options *op, char *arg); -static void open_tty(char *tty, struct termio *tp, int local); -static void termio_init(struct termio *tp, int speed, struct options *op); -static void auto_baud(struct termio *tp); -static void do_prompt(struct options *op, struct termio *tp); -static void next_speed(struct termio *tp, struct options *op); -static char *get_logname(struct options *op, struct chardata *cp, - struct termio *tp); -static void termio_final(struct options *op, struct termio *tp, - struct chardata *cp); -static int caps_lock(const char *s); -static int bcode(const char *s); -static void error(const char *fmt, ...) ATTRIBUTE_NORETURN; #ifdef SYSV_STYLE #ifdef CONFIG_FEATURE_UTMP @@ -247,136 +233,84 @@ FILE *dbf; #define debug(s) /* nothing */ #endif -int getty_main(int argc, char **argv) -{ - char *logname = NULL; /* login name, given to /bin/login */ - struct chardata chardata; /* set by get_logname() */ - struct termio termio; /* terminal mode bits */ - static struct options options = { - 0, /* show /etc/issue (SYSV_STYLE) */ - 0, /* no timeout */ - _PATH_LOGIN, /* default login program */ - "tty1", /* default tty line */ - "", /* modem init string */ -#ifdef ISSUE - ISSUE, /* default issue file */ -#else - NULL, -#endif - 0, /* no baud rates known yet */ - }; -#ifdef DEBUGGING - dbf = bb_xfopen(DEBUGTERM, "w"); +/* + * output error messages + */ +static void error(const char *fmt, ...) ATTRIBUTE_NORETURN; +static void error(const char *fmt, ...) +{ + va_list va_alist; + char buf[256]; - { - int i; +#ifdef CONFIG_SYSLOGD + va_start(va_alist, fmt); + vsnprintf(buf, sizeof(buf), fmt, va_alist); + openlog(bb_applet_name, 0, LOG_AUTH); + syslog(LOG_ERR, "%s", buf); + closelog(); +#else + int fd; + size_t l; - for (i = 1; i < argc; i++) { - debug(argv[i]); - debug("\n"); - } + snprintf(buf, sizeof(buf), "%s: ", bb_applet_name); + l = strlen(buf); + va_start(va_alist, fmt); + vsnprintf(buf + l, sizeof(buf) - l, fmt, va_alist); + l = strlen(buf); + /* truncate if need */ + if((l + 3) > sizeof(buf)) + l = sizeof(buf) - 3; + /* add \r\n always */ + buf[l++] = '\r'; + buf[l++] = '\n'; + buf[l] = 0; + if ((fd = open("/dev/console", 1)) >= 0) { + write(fd, buf, l); + close(fd); } #endif - /* Parse command-line arguments. */ - - parse_args(argc, argv, &options); - -#ifdef __linux__ - setsid(); -#endif - - /* Update the utmp file. */ - - -#ifdef SYSV_STYLE -#ifdef CONFIG_FEATURE_UTMP - update_utmp(options.tty); -#endif -#endif + va_end(va_alist); - debug("calling open_tty\n"); - /* Open the tty as standard { input, output, error }. */ - open_tty(options.tty, &termio, options.flags & F_LOCAL); + (void) sleep((unsigned) 10); /* be kind to init(8) */ + exit(1); +} -#ifdef __linux__ - { - int iv; - iv = getpid(); - ioctl(0, TIOCSPGRP, &iv); - } -#endif - /* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */ - debug("calling termio_init\n"); - termio_init(&termio, options.speeds[FIRST_SPEED], &options); - /* write the modem init string and DON'T flush the buffers */ - if (options.flags & F_INITSTRING) { - debug("writing init string\n"); - write(1, options.initstring, strlen(options.initstring)); +/* bcode - convert speed string to speed code; return 0 on failure */ +static int bcode(const char *s) +{ + int r; + unsigned long value; + if (safe_strtoul((char *)s, &value)) { + return -1; } - - if (!(options.flags & F_LOCAL)) { - /* go to blocking write mode unless -L is specified */ - fcntl(1, F_SETFL, fcntl(1, F_GETFL, 0) & ~O_NONBLOCK); + if ((r = bb_value_to_baud(value)) > 0) { + return r; } + return 0; +} - /* Optionally detect the baud rate from the modem status message. */ - debug("before autobaud\n"); - if (options.flags & F_PARSE) - auto_baud(&termio); - - /* Set the optional timer. */ - if (options.timeout) - (void) alarm((unsigned) options.timeout); - - /* optionally wait for CR or LF before writing /etc/issue */ - if (options.flags & F_WAITCRLF) { - char ch; - debug("waiting for cr-lf\n"); - while (read(0, &ch, 1) == 1) { - ch &= 0x7f; /* strip "parity bit" */ -#ifdef DEBUGGING - fprintf(dbf, "read %c\n", ch); -#endif - if (ch == '\n' || ch == '\r') - break; - } - } +/* parse_speeds - parse alternate baud rates */ +static void parse_speeds(struct options *op, char *arg) +{ + char *cp; - chardata = init_chardata; - if (!(options.flags & F_NOPROMPT)) { - /* Read the login name. */ - debug("reading login name\n"); - /* while ((logname = get_logname(&options, &chardata, &termio)) == 0) */ - while ((logname = get_logname(&options, &chardata, &termio)) == - NULL) next_speed(&termio, &options); + debug("entered parse_speeds\n"); + for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) { + if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0) + error("bad speed: %s", cp); + if (op->numspeed > MAX_SPEED) + error("too many alternate speeds"); } - - /* Disable timer. */ - - if (options.timeout) - (void) alarm(0); - - /* Finalize the termio settings. */ - - termio_final(&options, &termio, &chardata); - - /* Now the newline character should be properly written. */ - - (void) write(1, "\n", 1); - - /* Let the login program take care of password validation. */ - - (void) execl(options.login, options.login, "--", logname, (char *) 0); - error("%s: can't exec %s: %m", options.tty, options.login); + debug("exiting parsespeeds\n"); } -/* parse-args - parse command-line arguments */ +/* parse-args - parse command-line arguments */ static void parse_args(int argc, char **argv, struct options *op) { char *ts; @@ -427,84 +361,6 @@ static void parse_args(int argc, char **argv, struct options *op) debug("exiting parseargs\n"); } -/* parse_speeds - parse alternate baud rates */ - -static void parse_speeds(struct options *op, char *arg) -{ - char *cp; - - debug("entered parse_speeds\n"); - for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) { - if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0) - error("bad speed: %s", cp); - if (op->numspeed > MAX_SPEED) - error("too many alternate speeds"); - } - debug("exiting parsespeeds\n"); -} - -#ifdef SYSV_STYLE -#ifdef CONFIG_FEATURE_UTMP - -/* update_utmp - update our utmp entry */ -static void update_utmp(char *line) -{ - struct utmp ut; - struct utmp *utp; - time_t t; - int mypid = getpid(); -#if ! (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)) - struct flock lock; -#endif - - /* - * The utmp file holds miscellaneous information about things started by - * /sbin/init and other system-related events. Our purpose is to update - * the utmp entry for the current process, in particular the process type - * and the tty line we are listening to. Return successfully only if the - * utmp file can be opened for update, and if we are able to find our - * entry in the utmp file. - */ - if (access(_PATH_UTMP, R_OK|W_OK) == -1) { - close(creat(_PATH_UTMP, 0664)); - } - utmpname(_PATH_UTMP); - setutent(); - while ((utp = getutent()) - && !(utp->ut_type == INIT_PROCESS && utp->ut_pid == mypid)) /* nothing */ - ; - - if (utp) { - memcpy(&ut, utp, sizeof(ut)); - } else { - /* some inits don't initialize utmp... */ - memset(&ut, 0, sizeof(ut)); - strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id)); - } - /*endutent(); */ - - strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user)); - strncpy(ut.ut_line, line, sizeof(ut.ut_line)); - if (fakehost) - strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host)); - time(&t); - ut.ut_time = t; - ut.ut_type = LOGIN_PROCESS; - ut.ut_pid = mypid; - - pututline(&ut); - endutent(); - -#ifdef CONFIG_FEATURE_WTMP - if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) - close(creat(bb_path_wtmp_file, 0664)); - updwtmp(bb_path_wtmp_file, &ut); -#endif -} - -#endif /* CONFIG_FEATURE_UTMP */ -#endif /* SYSV_STYLE */ - /* open_tty - set up tty as standard { input, output, error } */ static void open_tty(char *tty, struct termio *tp, int local) { @@ -611,7 +467,6 @@ static void open_tty(char *tty, struct termio *tp, int local) } /* termio_init - initialize termio settings */ - static void termio_init(struct termio *tp, int speed, struct options *op) { /* @@ -710,6 +565,18 @@ static void auto_baud(struct termio *tp) (void) ioctl(0, TCSETA, tp); } +/* next_speed - select next baud rate */ +static void next_speed(struct termio *tp, struct options *op) +{ + static int baud_index = FIRST_SPEED; /* current speed index */ + + baud_index = (baud_index + 1) % op->numspeed; + tp->c_cflag &= ~CBAUD; + tp->c_cflag |= op->speeds[baud_index]; + (void) ioctl(0, TCSETA, tp); +} + + /* do_prompt - show login prompt, optionally preceded by /etc/issue contents */ static void do_prompt(struct options *op, struct termio *tp) { @@ -719,22 +586,26 @@ static void do_prompt(struct options *op, struct termio *tp) print_login_prompt(); } -/* next_speed - select next baud rate */ -static void next_speed(struct termio *tp, struct options *op) +/* caps_lock - string contains upper case without lower case */ +/* returns 1 if true, 0 if false */ +static int caps_lock(const char *s) { - static int baud_index = FIRST_SPEED; /* current speed index */ + int capslock; - baud_index = (baud_index + 1) % op->numspeed; - tp->c_cflag &= ~CBAUD; - tp->c_cflag |= op->speeds[baud_index]; - (void) ioctl(0, TCSETA, tp); + for (capslock = 0; *s; s++) { + if (islower(*s)) + return (0); + if (capslock == 0) + capslock = isupper(*s); + } + return (capslock); } +#define logname bb_common_bufsiz1 /* get_logname - get user name, establish parity, speed, erase, kill, eol */ /* return NULL on failure, logname on success */ static char *get_logname(struct options *op, struct chardata *cp, struct termio *tp) { -#define logname bb_common_bufsiz1 char *bp; char c; /* input character, full eight bits */ char ascval; /* low 7 bits of input character */ @@ -901,73 +772,195 @@ static void termio_final(struct options *op, struct termio *tp, struct chardata error("%s: ioctl: TCSETA: %m", op->tty); } -/* caps_lock - string contains upper case without lower case */ -/* returns 1 if true, 0 if false */ -static int caps_lock(const char *s) + +#ifdef SYSV_STYLE +#ifdef CONFIG_FEATURE_UTMP +/* update_utmp - update our utmp entry */ +static void update_utmp(char *line) { - int capslock; + struct utmp ut; + struct utmp *utp; + time_t t; + int mypid = getpid(); +#if ! (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)) + struct flock lock; +#endif - for (capslock = 0; *s; s++) { - if (islower(*s)) - return (0); - if (capslock == 0) - capslock = isupper(*s); + /* + * The utmp file holds miscellaneous information about things started by + * /sbin/init and other system-related events. Our purpose is to update + * the utmp entry for the current process, in particular the process type + * and the tty line we are listening to. Return successfully only if the + * utmp file can be opened for update, and if we are able to find our + * entry in the utmp file. + */ + if (access(_PATH_UTMP, R_OK|W_OK) == -1) { + close(creat(_PATH_UTMP, 0664)); } - return (capslock); -} + utmpname(_PATH_UTMP); + setutent(); + while ((utp = getutent()) + && !(utp->ut_type == INIT_PROCESS && utp->ut_pid == mypid)) /* nothing */ + ; -/* bcode - convert speed string to speed code; return 0 on failure */ -static int bcode(const char *s) -{ - int r; - unsigned long value; - if (safe_strtoul((char *)s, &value)) { - return -1; - } - if ((r = bb_value_to_baud(value)) > 0) { - return r; + if (utp) { + memcpy(&ut, utp, sizeof(ut)); + } else { + /* some inits don't initialize utmp... */ + memset(&ut, 0, sizeof(ut)); + strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id)); } - return 0; + /*endutent(); */ + + strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user)); + strncpy(ut.ut_line, line, sizeof(ut.ut_line)); + if (fakehost) + strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host)); + time(&t); + ut.ut_time = t; + ut.ut_type = LOGIN_PROCESS; + ut.ut_pid = mypid; + + pututline(&ut); + endutent(); + +#ifdef CONFIG_FEATURE_WTMP + if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) + close(creat(bb_path_wtmp_file, 0664)); + updwtmp(bb_path_wtmp_file, &ut); +#endif } -/* - * output error messages - */ -static void error(const char *fmt, ...) -{ - va_list va_alist; - char buf[256]; +#endif /* CONFIG_FEATURE_UTMP */ +#endif /* SYSV_STYLE */ -#ifdef CONFIG_SYSLOGD - va_start(va_alist, fmt); - vsnprintf(buf, sizeof(buf), fmt, va_alist); - openlog(bb_applet_name, 0, LOG_AUTH); - syslog(LOG_ERR, "%s", buf); - closelog(); + +#undef logname +int getty_main(int argc, char **argv) +{ + char *logname = NULL; /* login name, given to /bin/login */ + struct chardata chardata; /* set by get_logname() */ + struct termio termio; /* terminal mode bits */ + static struct options options = { + 0, /* show /etc/issue (SYSV_STYLE) */ + 0, /* no timeout */ + _PATH_LOGIN, /* default login program */ + "tty1", /* default tty line */ + "", /* modem init string */ +#ifdef ISSUE + ISSUE, /* default issue file */ #else - int fd; - size_t l; + NULL, +#endif + 0, /* no baud rates known yet */ + }; - snprintf(buf, sizeof(buf), "%s: ", bb_applet_name); - l = strlen(buf); - va_start(va_alist, fmt); - vsnprintf(buf + l, sizeof(buf) - l, fmt, va_alist); - l = strlen(buf); - /* truncate if need */ - if((l + 3) > sizeof(buf)) - l = sizeof(buf) - 3; - /* add \r\n always */ - buf[l++] = '\r'; - buf[l++] = '\n'; - buf[l] = 0; - if ((fd = open("/dev/console", 1)) >= 0) { - write(fd, buf, l); - close(fd); +#ifdef DEBUGGING + dbf = bb_xfopen(DEBUGTERM, "w"); + + { + int i; + + for (i = 1; i < argc; i++) { + debug(argv[i]); + debug("\n"); + } } #endif - va_end(va_alist); + /* Parse command-line arguments. */ - (void) sleep((unsigned) 10); /* be kind to init(8) */ - exit(1); + parse_args(argc, argv, &options); + +#ifdef __linux__ + setsid(); +#endif + + /* Update the utmp file. */ + + +#ifdef SYSV_STYLE +#ifdef CONFIG_FEATURE_UTMP + update_utmp(options.tty); +#endif +#endif + + debug("calling open_tty\n"); + /* Open the tty as standard { input, output, error }. */ + open_tty(options.tty, &termio, options.flags & F_LOCAL); + +#ifdef __linux__ + { + int iv; + + iv = getpid(); + ioctl(0, TIOCSPGRP, &iv); + } +#endif + /* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */ + debug("calling termio_init\n"); + termio_init(&termio, options.speeds[FIRST_SPEED], &options); + + /* write the modem init string and DON'T flush the buffers */ + if (options.flags & F_INITSTRING) { + debug("writing init string\n"); + write(1, options.initstring, strlen(options.initstring)); + } + + if (!(options.flags & F_LOCAL)) { + /* go to blocking write mode unless -L is specified */ + fcntl(1, F_SETFL, fcntl(1, F_GETFL, 0) & ~O_NONBLOCK); + } + + /* Optionally detect the baud rate from the modem status message. */ + debug("before autobaud\n"); + if (options.flags & F_PARSE) + auto_baud(&termio); + + /* Set the optional timer. */ + if (options.timeout) + (void) alarm((unsigned) options.timeout); + + /* optionally wait for CR or LF before writing /etc/issue */ + if (options.flags & F_WAITCRLF) { + char ch; + + debug("waiting for cr-lf\n"); + while (read(0, &ch, 1) == 1) { + ch &= 0x7f; /* strip "parity bit" */ +#ifdef DEBUGGING + fprintf(dbf, "read %c\n", ch); +#endif + if (ch == '\n' || ch == '\r') + break; + } + } + + chardata = init_chardata; + if (!(options.flags & F_NOPROMPT)) { + /* Read the login name. */ + debug("reading login name\n"); + /* while ((logname = get_logname(&options, &chardata, &termio)) == 0) */ + while ((logname = get_logname(&options, &chardata, &termio)) == + NULL) next_speed(&termio, &options); + } + + /* Disable timer. */ + + if (options.timeout) + (void) alarm(0); + + /* Finalize the termio settings. */ + + termio_final(&options, &termio, &chardata); + + /* Now the newline character should be properly written. */ + + (void) write(1, "\n", 1); + + /* Let the login program take care of password validation. */ + + (void) execl(options.login, options.login, "--", logname, (char *) 0); + error("%s: can't exec %s: %m", options.tty, options.login); } + |