diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-10-23 23:58:59 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-10-23 23:58:59 +0200 |
commit | e9dc354df86e9a3026de406520f6cd03a3519495 (patch) | |
tree | be701340f824afa52536888ae116f96e02047967 | |
parent | ee320c6d9cd0781233ed599d743b4da94b4424a7 (diff) | |
download | busybox-w32-e9dc354df86e9a3026de406520f6cd03a3519495.tar.gz busybox-w32-e9dc354df86e9a3026de406520f6cd03a3519495.tar.bz2 busybox-w32-e9dc354df86e9a3026de406520f6cd03a3519495.zip |
getty: fix a minor problem of Ctrl-D not printing '\n'
Also removed defines for control chars which are never changed,
and added login/getty README.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | loginutils/README | 70 | ||||
-rw-r--r-- | loginutils/getty.c | 59 | ||||
-rw-r--r-- | loginutils/login.c | 1 |
3 files changed, 94 insertions, 36 deletions
diff --git a/loginutils/README b/loginutils/README new file mode 100644 index 000000000..ce8851097 --- /dev/null +++ b/loginutils/README | |||
@@ -0,0 +1,70 @@ | |||
1 | Getty | ||
2 | |||
3 | ??? Should getty open tty with or without O_NONBLOCK? | ||
4 | For serial lines, it means "should getty wait for Carrier Detect pin?" | ||
5 | I checked other getties: | ||
6 | |||
7 | - agetty always uses O_NONBLOCK | ||
8 | - mgetty uses O_NONBLOCK unless run with -b, or as "getty" | ||
9 | |||
10 | ??? If we decided to use O_NONBLOCK (perhaps optionally with -b), | ||
11 | when getty should send -I INITSTR data to tty? After open succeeds? | ||
12 | What if we also want to initialize *modem* with some AT commands? | ||
13 | |||
14 | ??? Should we check/create /var/lock/LCK..ttyPFX lockfiles? | ||
15 | |||
16 | ??? mgetty opens tty but does NOT lock it, then waits for input via | ||
17 | select/poll, and when input is available, it checks lock file. | ||
18 | If it exists, mgetty exits (it assumes someone else uses the line). | ||
19 | If no, it creates the file (lock the tty). Sounds like a good algorithm | ||
20 | to use if we are called with -w... | ||
21 | |||
22 | Getty should establish a new session and process group, and ensure | ||
23 | that tty is a ctty. | ||
24 | |||
25 | ??? Should getty ensure that other processes which might have opened | ||
26 | fds to this tty be dusconnected? agetty has a -R option which makes | ||
27 | agetty call vhangup() after tty is opened. (Then agetty opens it again, | ||
28 | since it probably vhangup'ed its own fd too). | ||
29 | |||
30 | Getty should leave the tty in approximately the same state as "stty sane" | ||
31 | before it execs login program. Minor things we do conditionally are: | ||
32 | c_iflag |= ICRNL; // if '\r' was used to end username | ||
33 | |||
34 | ??? mgetty uses per-tty file to ignore connects, /etc/nologin.ttyxx - | ||
35 | is it useful? | ||
36 | |||
37 | It should be possible to run "getty 0 -" from a shell prompt. | ||
38 | [This currently doesn't work from interactive shell since setsid() | ||
39 | fails in process group leader. The workaround is to run it as a child | ||
40 | of something. sh -c 'getty - 0; true' usually works. Should we fix this?] | ||
41 | It should leave tty in a sane state when it exits (Ctrl-D, -t SEC timeout): | ||
42 | echo should be on, speed, control chars properly set, etc. | ||
43 | (However, it can't restore ctty. The symptom is that "</dev/tty" | ||
44 | fails in the parent shell after getty exits: /dev/tty can't be opened). | ||
45 | |||
46 | Getty should write LOGIN_PROCESS utmp record before it starts waiting | ||
47 | for username to be entered. | ||
48 | |||
49 | Login | ||
50 | |||
51 | Login should not try to set up tty parameters - apart from switching echo | ||
52 | off while entering password, and switching it back on after. | ||
53 | |||
54 | Login should not leave "echo off" state when it times out reading password | ||
55 | or otherwise terminates (Ctrl-C, Ctrl-D etc). | ||
56 | |||
57 | ??? Should login establish a new session and/or process group, and ensure | ||
58 | that tty is a ctty? Without this, running login directly (not via getty) | ||
59 | from e.g. initscript will usually result with a login session without | ||
60 | ctty and without session/pgrp properly created... | ||
61 | |||
62 | It should be possible to run "login [USER]" from a shell prompt, | ||
63 | and it should work (not block/die/error out). | ||
64 | Similarly to getty, it should leave tty in the sane state when it exits. | ||
65 | |||
66 | ??? Should login write LOGIN_PROCESS utmp record before it starts waiting | ||
67 | for username/password to be entered? | ||
68 | |||
69 | Login should write USER_PROCESS utmp record just before it is about | ||
70 | to exec user's shell. | ||
diff --git a/loginutils/getty.c b/loginutils/getty.c index 32735642b..4d5219725 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c | |||
@@ -63,18 +63,8 @@ static FILE *dbf; | |||
63 | */ | 63 | */ |
64 | #define ISSUE "/etc/issue" | 64 | #define ISSUE "/etc/issue" |
65 | 65 | ||
66 | /* Some shorthands for control characters */ | 66 | /* Macro to build Ctrl-LETTER. Assumes ASCII dialect */ |
67 | #define CTL(x) ((x) ^ 0100) /* Assumes ASCII dialect */ | 67 | #define CTL(x) ((x) ^ 0100) |
68 | #define BS CTL('H') /* back space */ | ||
69 | #define DEL CTL('?') /* delete */ | ||
70 | |||
71 | /* Defaults for line-editing etc. characters; you may want to change this */ | ||
72 | #define DEF_INTR CTL('C') /* default interrupt character */ | ||
73 | #define DEF_QUIT CTL('\\') /* default quit char */ | ||
74 | #define DEF_KILL CTL('U') /* default kill char */ | ||
75 | #define DEF_EOF CTL('D') /* default EOF char */ | ||
76 | #define DEF_EOL '\n' | ||
77 | #define DEF_SWITCH 0 /* default switch char (none) */ | ||
78 | 68 | ||
79 | /* | 69 | /* |
80 | * When multiple baud rates are specified on the command line, | 70 | * When multiple baud rates are specified on the command line, |
@@ -365,17 +355,17 @@ static void finalize_tty_attrs(void) | |||
365 | * (why "stty sane" unsets this bit?) | 355 | * (why "stty sane" unsets this bit?) |
366 | */ | 356 | */ |
367 | 357 | ||
368 | G.tty_attrs.c_cc[VINTR] = DEF_INTR; | 358 | G.tty_attrs.c_cc[VINTR] = CTL('C'); |
369 | G.tty_attrs.c_cc[VQUIT] = DEF_QUIT; | 359 | G.tty_attrs.c_cc[VQUIT] = CTL('\\'); |
370 | G.tty_attrs.c_cc[VEOF] = DEF_EOF; | 360 | G.tty_attrs.c_cc[VEOF] = CTL('D'); |
371 | G.tty_attrs.c_cc[VEOL] = DEF_EOL; | 361 | G.tty_attrs.c_cc[VEOL] = '\n'; |
372 | #ifdef VSWTC | 362 | #ifdef VSWTC |
373 | G.tty_attrs.c_cc[VSWTC] = DEF_SWITCH; | 363 | G.tty_attrs.c_cc[VSWTC] = 0; |
374 | #endif | 364 | #endif |
375 | #ifdef VSWTCH | 365 | #ifdef VSWTCH |
376 | G.tty_attrs.c_cc[VSWTCH] = DEF_SWITCH; | 366 | G.tty_attrs.c_cc[VSWTCH] = 0; |
377 | #endif | 367 | #endif |
378 | G.tty_attrs.c_cc[VKILL] = DEF_KILL; | 368 | G.tty_attrs.c_cc[VKILL] = CTL('U'); |
379 | /* Other control chars: | 369 | /* Other control chars: |
380 | * VEOL2 | 370 | * VEOL2 |
381 | * VERASE, VWERASE - (word) erase. we may set VERASE in get_logname | 371 | * VERASE, VWERASE - (word) erase. we may set VERASE in get_logname |
@@ -386,6 +376,9 @@ static void finalize_tty_attrs(void) | |||
386 | */ | 376 | */ |
387 | 377 | ||
388 | set_tty_attrs(); | 378 | set_tty_attrs(); |
379 | |||
380 | /* Now the newline character should be properly written */ | ||
381 | full_write(STDOUT_FILENO, "\n", 1); | ||
389 | } | 382 | } |
390 | 383 | ||
391 | /* extract baud rate from modem status message */ | 384 | /* extract baud rate from modem status message */ |
@@ -449,8 +442,7 @@ static char *get_logname(void) | |||
449 | tcflush(STDIN_FILENO, TCIFLUSH); | 442 | tcflush(STDIN_FILENO, TCIFLUSH); |
450 | 443 | ||
451 | /* Prompt for and read a login name */ | 444 | /* Prompt for and read a login name */ |
452 | G.line_buf[0] = '\0'; | 445 | do { |
453 | while (!G.line_buf[0]) { | ||
454 | /* Write issue file and prompt */ | 446 | /* Write issue file and prompt */ |
455 | #ifdef ISSUE | 447 | #ifdef ISSUE |
456 | if (!(option_mask32 & F_NOISSUE)) | 448 | if (!(option_mask32 & F_NOISSUE)) |
@@ -458,9 +450,8 @@ static char *get_logname(void) | |||
458 | #endif | 450 | #endif |
459 | print_login_prompt(); | 451 | print_login_prompt(); |
460 | 452 | ||
461 | /* Read name, watch for break, parity, erase, kill, end-of-line */ | 453 | /* Read name, watch for break, erase, kill, end-of-line */ |
462 | bp = G.line_buf; | 454 | bp = G.line_buf; |
463 | G.eol = '\0'; | ||
464 | while (1) { | 455 | while (1) { |
465 | /* Do not report trivial EINTR/EIO errors */ | 456 | /* Do not report trivial EINTR/EIO errors */ |
466 | errno = EINTR; /* make read of 0 bytes be silent too */ | 457 | errno = EINTR; /* make read of 0 bytes be silent too */ |
@@ -471,20 +462,14 @@ static char *get_logname(void) | |||
471 | bb_perror_msg_and_die(bb_msg_read_error); | 462 | bb_perror_msg_and_die(bb_msg_read_error); |
472 | } | 463 | } |
473 | 464 | ||
474 | /* BREAK. If we have speeds to try, | ||
475 | * return NULL (will switch speeds and return here) */ | ||
476 | if (c == '\0' && G.numspeed > 1) | ||
477 | return NULL; | ||
478 | |||
479 | /* Do erase, kill and end-of-line processing */ | ||
480 | switch (c) { | 465 | switch (c) { |
481 | case '\r': | 466 | case '\r': |
482 | case '\n': | 467 | case '\n': |
483 | *bp = '\0'; | 468 | *bp = '\0'; |
484 | G.eol = c; | 469 | G.eol = c; |
485 | goto got_logname; | 470 | goto got_logname; |
486 | case BS: | 471 | case CTL('H'): |
487 | case DEL: | 472 | case 0x7f: |
488 | G.tty_attrs.c_cc[VERASE] = c; | 473 | G.tty_attrs.c_cc[VERASE] = c; |
489 | if (bp > G.line_buf) { | 474 | if (bp > G.line_buf) { |
490 | full_write(STDOUT_FILENO, "\010 \010", 3); | 475 | full_write(STDOUT_FILENO, "\010 \010", 3); |
@@ -497,9 +482,16 @@ static char *get_logname(void) | |||
497 | bp--; | 482 | bp--; |
498 | } | 483 | } |
499 | break; | 484 | break; |
485 | case CTL('C'): | ||
500 | case CTL('D'): | 486 | case CTL('D'): |
501 | finalize_tty_attrs(); | 487 | finalize_tty_attrs(); |
502 | exit(EXIT_SUCCESS); | 488 | exit(EXIT_SUCCESS); |
489 | case '\0': | ||
490 | /* BREAK. If we have speeds to try, | ||
491 | * return NULL (will switch speeds and return here) */ | ||
492 | if (G.numspeed > 1) | ||
493 | return NULL; | ||
494 | /* fall through and ignore it */ | ||
503 | default: | 495 | default: |
504 | if ((unsigned char)c < ' ') { | 496 | if ((unsigned char)c < ' ') { |
505 | /* ignore garbage characters */ | 497 | /* ignore garbage characters */ |
@@ -512,7 +504,7 @@ static char *get_logname(void) | |||
512 | } | 504 | } |
513 | } /* end of get char loop */ | 505 | } /* end of get char loop */ |
514 | got_logname: ; | 506 | got_logname: ; |
515 | } /* while logname is empty */ | 507 | } while (G.line_buf[0] == '\0'); /* while logname is empty */ |
516 | 508 | ||
517 | return G.line_buf; | 509 | return G.line_buf; |
518 | } | 510 | } |
@@ -682,9 +674,6 @@ int getty_main(int argc UNUSED_PARAM, char **argv) | |||
682 | 674 | ||
683 | finalize_tty_attrs(); | 675 | finalize_tty_attrs(); |
684 | 676 | ||
685 | /* Now the newline character should be properly written */ | ||
686 | full_write(STDOUT_FILENO, "\n", 1); | ||
687 | |||
688 | /* Let the login program take care of password validation */ | 677 | /* Let the login program take care of password validation */ |
689 | /* We use PATH because we trust that root doesn't set "bad" PATH, | 678 | /* We use PATH because we trust that root doesn't set "bad" PATH, |
690 | * and getty is not suid-root applet */ | 679 | * and getty is not suid-root applet */ |
diff --git a/loginutils/login.c b/loginutils/login.c index b54beef6e..73db8fa63 100644 --- a/loginutils/login.c +++ b/loginutils/login.c | |||
@@ -443,7 +443,6 @@ int login_main(int argc UNUSED_PARAM, char **argv) | |||
443 | if (pw->pw_uid != 0) | 443 | if (pw->pw_uid != 0) |
444 | die_if_nologin(); | 444 | die_if_nologin(); |
445 | 445 | ||
446 | |||
447 | #if ENABLE_LOGIN_SESSION_AS_CHILD | 446 | #if ENABLE_LOGIN_SESSION_AS_CHILD |
448 | child_pid = vfork(); | 447 | child_pid = vfork(); |
449 | if (child_pid != 0) { | 448 | if (child_pid != 0) { |