getty: fix a minor problem of Ctrl-D not printing '\n'
No binary (build failed)
—
(log yok)
| @@ -0,0 +1,70 @@ | |
| + | Getty |
| + | |
| + | ??? Should getty open tty with or without O_NONBLOCK? |
| + | For serial lines, it means "should getty wait for Carrier Detect pin?" |
| + | I checked other getties: |
| + | |
| + | - agetty always uses O_NONBLOCK |
| + | - mgetty uses O_NONBLOCK unless run with -b, or as "getty" |
| + | |
| + | ??? If we decided to use O_NONBLOCK (perhaps optionally with -b), |
| + | when getty should send -I INITSTR data to tty? After open succeeds? |
| + | What if we also want to initialize *modem* with some AT commands? |
| + | |
| + | ??? Should we check/create /var/lock/LCK..ttyPFX lockfiles? |
| + | |
| + | ??? mgetty opens tty but does NOT lock it, then waits for input via |
| + | select/poll, and when input is available, it checks lock file. |
| + | If it exists, mgetty exits (it assumes someone else uses the line). |
| + | If no, it creates the file (lock the tty). Sounds like a good algorithm |
| + | to use if we are called with -w... |
| + | |
| + | Getty should establish a new session and process group, and ensure |
| + | that tty is a ctty. |
| + | |
| + | ??? Should getty ensure that other processes which might have opened |
| + | fds to this tty be dusconnected? agetty has a -R option which makes |
| + | agetty call vhangup() after tty is opened. (Then agetty opens it again, |
| + | since it probably vhangup'ed its own fd too). |
| + | |
| + | Getty should leave the tty in approximately the same state as "stty sane" |
| + | before it execs login program. Minor things we do conditionally are: |
| + | c_iflag |= ICRNL; // if '\r' was used to end username |
| + | |
| + | ??? mgetty uses per-tty file to ignore connects, /etc/nologin.ttyxx - |
| + | is it useful? |
| + | |
| + | It should be possible to run "getty 0 -" from a shell prompt. |
| + | [This currently doesn't work from interactive shell since setsid() |
| + | fails in process group leader. The workaround is to run it as a child |
| + | of something. sh -c 'getty - 0; true' usually works. Should we fix this?] |
| + | It should leave tty in a sane state when it exits (Ctrl-D, -t SEC timeout): |
| + | echo should be on, speed, control chars properly set, etc. |
| + | (However, it can't restore ctty. The symptom is that "</dev/tty" |
| + | fails in the parent shell after getty exits: /dev/tty can't be opened). |
| + | |
| + | Getty should write LOGIN_PROCESS utmp record before it starts waiting |
| + | for username to be entered. |
| + | |
| + | Login |
| + | |
| + | Login should not try to set up tty parameters - apart from switching echo |
| + | off while entering password, and switching it back on after. |
| + | |
| + | Login should not leave "echo off" state when it times out reading password |
| + | or otherwise terminates (Ctrl-C, Ctrl-D etc). |
| + | |
| + | ??? Should login establish a new session and/or process group, and ensure |
| + | that tty is a ctty? Without this, running login directly (not via getty) |
| + | from e.g. initscript will usually result with a login session without |
| + | ctty and without session/pgrp properly created... |
| + | |
| + | It should be possible to run "login [USER]" from a shell prompt, |
| + | and it should work (not block/die/error out). |
| + | Similarly to getty, it should leave tty in the sane state when it exits. |
| + | |
| + | ??? Should login write LOGIN_PROCESS utmp record before it starts waiting |
| + | for username/password to be entered? |
| + | |
| + | Login should write USER_PROCESS utmp record just before it is about |
| + | to exec user's shell. |
| @@ -63,18 +63,8 @@ static FILE *dbf; | |
| */ | |
| #define ISSUE "/etc/issue" | |
| - | /* Some shorthands for control characters */ |
| - | #define CTL(x) ((x) ^ 0100) /* Assumes ASCII dialect */ |
| - | #define BS CTL('H') /* back space */ |
| - | #define DEL CTL('?') /* delete */ |
| - | |
| - | /* Defaults for line-editing etc. characters; you may want to change this */ |
| - | #define DEF_INTR CTL('C') /* default interrupt character */ |
| - | #define DEF_QUIT CTL('\\') /* default quit char */ |
| - | #define DEF_KILL CTL('U') /* default kill char */ |
| - | #define DEF_EOF CTL('D') /* default EOF char */ |
| - | #define DEF_EOL '\n' |
| - | #define DEF_SWITCH 0 /* default switch char (none) */ |
| + | /* Macro to build Ctrl-LETTER. Assumes ASCII dialect */ |
| + | #define CTL(x) ((x) ^ 0100) |
| /* | |
| * When multiple baud rates are specified on the command line, | |
| @@ -365,17 +355,17 @@ static void finalize_tty_attrs(void) | |
| * (why "stty sane" unsets this bit?) | |
| */ | |
| - | G.tty_attrs.c_cc[VINTR] = DEF_INTR; |
| - | G.tty_attrs.c_cc[VQUIT] = DEF_QUIT; |
| - | G.tty_attrs.c_cc[VEOF] = DEF_EOF; |
| - | G.tty_attrs.c_cc[VEOL] = DEF_EOL; |
| + | G.tty_attrs.c_cc[VINTR] = CTL('C'); |
| + | G.tty_attrs.c_cc[VQUIT] = CTL('\\'); |
| + | G.tty_attrs.c_cc[VEOF] = CTL('D'); |
| + | G.tty_attrs.c_cc[VEOL] = '\n'; |
| #ifdef VSWTC | |
| - | G.tty_attrs.c_cc[VSWTC] = DEF_SWITCH; |
| + | G.tty_attrs.c_cc[VSWTC] = 0; |
| #endif | |
| #ifdef VSWTCH | |
| - | G.tty_attrs.c_cc[VSWTCH] = DEF_SWITCH; |
| + | G.tty_attrs.c_cc[VSWTCH] = 0; |
| #endif | |
| - | G.tty_attrs.c_cc[VKILL] = DEF_KILL; |
| + | G.tty_attrs.c_cc[VKILL] = CTL('U'); |
| /* Other control chars: | |
| * VEOL2 | |
| * VERASE, VWERASE - (word) erase. we may set VERASE in get_logname | |
| @@ -386,6 +376,9 @@ static void finalize_tty_attrs(void) | |
| */ | |
| set_tty_attrs(); | |
| + | |
| + | /* Now the newline character should be properly written */ |
| + | full_write(STDOUT_FILENO, "\n", 1); |
| } | |
| /* extract baud rate from modem status message */ | |
| @@ -449,8 +442,7 @@ static char *get_logname(void) | |
| tcflush(STDIN_FILENO, TCIFLUSH); | |
| /* Prompt for and read a login name */ | |
| - | G.line_buf[0] = '\0'; |
| - | while (!G.line_buf[0]) { |
| + | do { |
| /* Write issue file and prompt */ | |
| #ifdef ISSUE | |
| if (!(option_mask32 & F_NOISSUE)) | |
| @@ -458,9 +450,8 @@ static char *get_logname(void) | |
| #endif | |
| print_login_prompt(); | |
| - | /* Read name, watch for break, parity, erase, kill, end-of-line */ |
| + | /* Read name, watch for break, erase, kill, end-of-line */ |
| bp = G.line_buf; | |
| - | G.eol = '\0'; |
| while (1) { | |
| /* Do not report trivial EINTR/EIO errors */ | |
| errno = EINTR; /* make read of 0 bytes be silent too */ | |
| @@ -471,20 +462,14 @@ static char *get_logname(void) | |
| bb_perror_msg_and_die(bb_msg_read_error); | |
| } | |
| - | /* BREAK. If we have speeds to try, |
| - | * return NULL (will switch speeds and return here) */ |
| - | if (c == '\0' && G.numspeed > 1) |
| - | return NULL; |
| - | |
| - | /* Do erase, kill and end-of-line processing */ |
| switch (c) { | |
| case '\r': | |
| case '\n': | |
| *bp = '\0'; | |
| G.eol = c; | |
| goto got_logname; | |
| - | case BS: |
| - | case DEL: |
| + | case CTL('H'): |
| + | case 0x7f: |
| G.tty_attrs.c_cc[VERASE] = c; | |
| if (bp > G.line_buf) { | |
| full_write(STDOUT_FILENO, "\010 \010", 3); | |
| @@ -497,9 +482,16 @@ static char *get_logname(void) | |
| bp--; | |
| } | |
| break; | |
| + | case CTL('C'): |
| case CTL('D'): | |
| finalize_tty_attrs(); | |
| exit(EXIT_SUCCESS); | |
| + | case '\0': |
| + | /* BREAK. If we have speeds to try, |
| + | * return NULL (will switch speeds and return here) */ |
| + | if (G.numspeed > 1) |
| + | return NULL; |
| + | /* fall through and ignore it */ |
| default: | |
| if ((unsigned char)c < ' ') { | |
| /* ignore garbage characters */ | |
| @@ -512,7 +504,7 @@ static char *get_logname(void) | |
| } | |
| } /* end of get char loop */ | |
| got_logname: ; | |
| - | } /* while logname is empty */ |
| + | } while (G.line_buf[0] == '\0'); /* while logname is empty */ |
| return G.line_buf; | |
| } | |
| @@ -682,9 +674,6 @@ int getty_main(int argc UNUSED_PARAM, char **argv) | |
| finalize_tty_attrs(); | |
| - | /* Now the newline character should be properly written */ |
| - | full_write(STDOUT_FILENO, "\n", 1); |
| - | |
| /* Let the login program take care of password validation */ | |
| /* We use PATH because we trust that root doesn't set "bad" PATH, | |
| * and getty is not suid-root applet */ | |
| @@ -443,7 +443,6 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |
| if (pw->pw_uid != 0) | |
| die_if_nologin(); | |
| - | |
| #if ENABLE_LOGIN_SESSION_AS_CHILD | |
| child_pid = vfork(); | |
| if (child_pid != 0) { | |