diff options
| author | Ron Yorston <rmy@pobox.com> | 2012-03-22 13:15:08 +0000 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2012-03-22 13:15:08 +0000 |
| commit | c0d4367d6b581eb5989c02815880cf0fa2851ae8 (patch) | |
| tree | 868c266e627e2d7f65ba5a4d5f98a1c421453181 /loginutils | |
| parent | f6bad5ef766b0447158e3de2f55c35f1f6cecb58 (diff) | |
| parent | da4441c44f6efccb6f7b7588404d9c6bfb7b6af8 (diff) | |
| download | busybox-w32-c0d4367d6b581eb5989c02815880cf0fa2851ae8.tar.gz busybox-w32-c0d4367d6b581eb5989c02815880cf0fa2851ae8.tar.bz2 busybox-w32-c0d4367d6b581eb5989c02815880cf0fa2851ae8.zip | |
Merge commit 'da4441c44f6efccb6f7b7588404d9c6bfb7b6af8' into merge
Conflicts:
libbb/vfork_daemon_rexec.c
networking/wget.c
procps/ps.c
Diffstat (limited to 'loginutils')
| -rw-r--r-- | loginutils/Config.src | 14 | ||||
| -rw-r--r-- | loginutils/getty.c | 177 |
2 files changed, 137 insertions, 54 deletions
diff --git a/loginutils/Config.src b/loginutils/Config.src index 4c771bbc4..0d7f50cf1 100644 --- a/loginutils/Config.src +++ b/loginutils/Config.src | |||
| @@ -181,7 +181,19 @@ config GETTY | |||
| 181 | default y | 181 | default y |
| 182 | select FEATURE_SYSLOG | 182 | select FEATURE_SYSLOG |
| 183 | help | 183 | help |
| 184 | getty lets you log in on a tty, it is normally invoked by init. | 184 | getty lets you log in on a tty. It is normally invoked by init. |
| 185 | |||
| 186 | Note that you can save a few bytes by disabling it and | ||
| 187 | using login applet directly. | ||
| 188 | If you need to reset tty attributes before calling login, | ||
| 189 | this script approximates getty: | ||
| 190 | |||
| 191 | exec </dev/$1 >/dev/$1 2>&1 || exit 1 | ||
| 192 | reset | ||
| 193 | stty sane; stty ispeed 38400; stty ospeed 38400 | ||
| 194 | printf "%s login: " "`hostname`" | ||
| 195 | read -r login | ||
| 196 | exec /bin/login "$login" | ||
| 185 | 197 | ||
| 186 | config LOGIN | 198 | config LOGIN |
| 187 | bool "login" | 199 | bool "login" |
diff --git a/loginutils/getty.c b/loginutils/getty.c index b71d68a1f..3f20c8e81 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c | |||
| @@ -106,15 +106,15 @@ struct globals { | |||
| 106 | //usage:#define getty_full_usage "\n\n" | 106 | //usage:#define getty_full_usage "\n\n" |
| 107 | //usage: "Open a tty, prompt for a login name, then invoke /bin/login\n" | 107 | //usage: "Open a tty, prompt for a login name, then invoke /bin/login\n" |
| 108 | //usage: "\nOptions:" | 108 | //usage: "\nOptions:" |
| 109 | //usage: "\n -h Enable hardware (RTS/CTS) flow control" | 109 | //usage: "\n -h Enable hardware RTS/CTS flow control" |
| 110 | //usage: "\n -i Don't display /etc/issue" | 110 | //usage: "\n -L Set CLOCAL (ignore Carrier Detect state)" |
| 111 | //usage: "\n -L Local line, set CLOCAL on it" | ||
| 112 | //usage: "\n -m Get baud rate from modem's CONNECT status message" | 111 | //usage: "\n -m Get baud rate from modem's CONNECT status message" |
| 112 | //usage: "\n -n Don't prompt for login name" | ||
| 113 | //usage: "\n -w Wait for CR or LF before sending /etc/issue" | 113 | //usage: "\n -w Wait for CR or LF before sending /etc/issue" |
| 114 | //usage: "\n -n Don't prompt for a login name" | 114 | //usage: "\n -i Don't display /etc/issue" |
| 115 | //usage: "\n -f ISSUE_FILE Display ISSUE_FILE instead of /etc/issue" | 115 | //usage: "\n -f ISSUE_FILE Display ISSUE_FILE instead of /etc/issue" |
| 116 | //usage: "\n -l LOGIN Invoke LOGIN instead of /bin/login" | 116 | //usage: "\n -l LOGIN Invoke LOGIN instead of /bin/login" |
| 117 | //usage: "\n -t SEC Terminate after SEC if no username is read" | 117 | //usage: "\n -t SEC Terminate after SEC if no login name is read" |
| 118 | //usage: "\n -I INITSTR Send INITSTR before anything else" | 118 | //usage: "\n -I INITSTR Send INITSTR before anything else" |
| 119 | //usage: "\n -H HOST Log HOST into the utmp file as the hostname" | 119 | //usage: "\n -H HOST Log HOST into the utmp file as the hostname" |
| 120 | //usage: "\n" | 120 | //usage: "\n" |
| @@ -224,6 +224,12 @@ static void open_tty(void) | |||
| 224 | } | 224 | } |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | static void set_termios(void) | ||
| 228 | { | ||
| 229 | if (tcsetattr_stdin_TCSANOW(&G.termios) < 0) | ||
| 230 | bb_perror_msg_and_die("tcsetattr"); | ||
| 231 | } | ||
| 232 | |||
| 227 | /* We manipulate termios this way: | 233 | /* We manipulate termios this way: |
| 228 | * - first, we read existing termios settings | 234 | * - first, we read existing termios settings |
| 229 | * - termios_init modifies some parts and sets it | 235 | * - termios_init modifies some parts and sets it |
| @@ -233,53 +239,128 @@ static void open_tty(void) | |||
| 233 | */ | 239 | */ |
| 234 | static void termios_init(int speed) | 240 | static void termios_init(int speed) |
| 235 | { | 241 | { |
| 236 | /* Flush input and output queues, important for modems! | 242 | /* Try to drain output buffer, with 5 sec timeout. |
| 237 | * Users report losing previously queued output chars, and I hesitate | 243 | * Added on request from users of ~600 baud serial interface |
| 238 | * to use tcdrain here instead of tcflush - I imagine it can block. | 244 | * with biggish buffer on a 90MHz CPU. |
| 239 | * Using small sleep instead. | 245 | * They were losing hundreds of bytes of buffered output |
| 246 | * on tcflush. | ||
| 240 | */ | 247 | */ |
| 241 | usleep(100*1000); /* 0.1 sec */ | 248 | signal_no_SA_RESTART_empty_mask(SIGALRM, record_signo); |
| 249 | alarm(5); | ||
| 250 | tcdrain(STDIN_FILENO); | ||
| 251 | alarm(0); | ||
| 252 | signal(SIGALRM, SIG_DFL); /* do not break -t TIMEOUT! */ | ||
| 253 | |||
| 254 | /* Flush input and output queues, important for modems! */ | ||
| 242 | tcflush(STDIN_FILENO, TCIOFLUSH); | 255 | tcflush(STDIN_FILENO, TCIOFLUSH); |
| 243 | 256 | ||
| 244 | /* Set speed if it wasn't specified as "0" on command line */ | 257 | /* Set speed if it wasn't specified as "0" on command line */ |
| 245 | if (speed != B0) | 258 | if (speed != B0) |
| 246 | cfsetspeed(&G.termios, speed); | 259 | cfsetspeed(&G.termios, speed); |
| 247 | 260 | ||
| 248 | /* | 261 | /* Initial termios settings: 8-bit characters, raw mode, blocking i/o. |
| 249 | * Initial termios settings: 8-bit characters, raw-mode, blocking i/o. | ||
| 250 | * Special characters are set after we have read the login name; all | 262 | * Special characters are set after we have read the login name; all |
| 251 | * reads will be done in raw mode anyway. Errors will be dealt with | 263 | * reads will be done in raw mode anyway. |
| 252 | * later on. | ||
| 253 | */ | 264 | */ |
| 254 | G.termios.c_cflag = CS8 | HUPCL | CREAD; | 265 | /* Clear all bits except: */ |
| 255 | if (option_mask32 & F_LOCAL) | 266 | G.termios.c_cflag &= (0 |
| 267 | /* 2 stop bits (1 otherwise) | ||
| 268 | * Enable parity bit (both on input and output) | ||
| 269 | * Odd parity (else even) | ||
| 270 | */ | ||
| 271 | | CSTOPB | PARENB | PARODD | ||
| 272 | #ifdef CMSPAR | ||
| 273 | | CMSPAR /* mark or space parity */ | ||
| 274 | #endif | ||
| 275 | | CBAUD /* (output) baud rate */ | ||
| 276 | #ifdef CBAUDEX | ||
| 277 | | CBAUDEX /* (output) baud rate */ | ||
| 278 | #endif | ||
| 279 | #ifdef CIBAUD | ||
| 280 | | CIBAUD /* input baud rate */ | ||
| 281 | #endif | ||
| 282 | ); | ||
| 283 | /* Set: 8 bits; hang up (drop DTR) on last close; enable receive */ | ||
| 284 | G.termios.c_cflag |= CS8 | HUPCL | CREAD; | ||
| 285 | if (option_mask32 & F_LOCAL) { | ||
| 286 | /* ignore Carrier Detect pin: | ||
| 287 | * opens don't block when CD is low, | ||
| 288 | * losing CD doesn't hang up processes whose ctty is this tty | ||
| 289 | */ | ||
| 256 | G.termios.c_cflag |= CLOCAL; | 290 | G.termios.c_cflag |= CLOCAL; |
| 291 | } | ||
| 292 | #ifdef CRTSCTS | ||
| 293 | if (option_mask32 & F_RTSCTS) | ||
| 294 | G.termios.c_cflag |= CRTSCTS; /* flow control using RTS/CTS pins */ | ||
| 295 | #endif | ||
| 257 | G.termios.c_iflag = 0; | 296 | G.termios.c_iflag = 0; |
| 258 | G.termios.c_lflag = 0; | 297 | G.termios.c_lflag = 0; |
| 298 | /* non-raw output; add CR to each NL */ | ||
| 259 | G.termios.c_oflag = OPOST | ONLCR; | 299 | G.termios.c_oflag = OPOST | ONLCR; |
| 260 | G.termios.c_cc[VMIN] = 1; | 300 | |
| 261 | G.termios.c_cc[VTIME] = 0; | 301 | G.termios.c_cc[VMIN] = 1; /* block reads if < 1 char is available */ |
| 302 | G.termios.c_cc[VTIME] = 0; /* no timeout (reads block forever) */ | ||
| 262 | #ifdef __linux__ | 303 | #ifdef __linux__ |
| 263 | G.termios.c_line = 0; | 304 | G.termios.c_line = 0; |
| 264 | #endif | 305 | #endif |
| 265 | #ifdef CRTSCTS | ||
| 266 | if (option_mask32 & F_RTSCTS) | ||
| 267 | G.termios.c_cflag |= CRTSCTS; | ||
| 268 | #endif | ||
| 269 | 306 | ||
| 270 | tcsetattr_stdin_TCSANOW(&G.termios); | 307 | set_termios(); |
| 271 | 308 | ||
| 272 | debug("term_io 2\n"); | 309 | debug("term_io 2\n"); |
| 273 | } | 310 | } |
| 274 | 311 | ||
| 275 | static void termios_final(void) | 312 | static void termios_final(void) |
| 276 | { | 313 | { |
| 277 | /* General terminal-independent stuff */ | 314 | /* software flow control on output (stop sending if XOFF is recvd); |
| 278 | G.termios.c_iflag |= IXON | IXOFF; /* 2-way flow control */ | 315 | * and on input (send XOFF when buffer is full) |
| 316 | */ | ||
| 317 | G.termios.c_iflag |= IXON | IXOFF; | ||
| 318 | if (G.eol == '\r') { | ||
| 319 | G.termios.c_iflag |= ICRNL; /* map CR on input to NL */ | ||
| 320 | } | ||
| 321 | /* Other bits in c_iflag: | ||
| 322 | * IXANY Any recvd char enables output (any char is also a XON) | ||
| 323 | * INPCK Enable parity check | ||
| 324 | * IGNPAR Ignore parity errors (drop bad bytes) | ||
| 325 | * PARMRK Mark parity errors with 0xff, 0x00 prefix | ||
| 326 | * (else bad byte is received as 0x00) | ||
| 327 | * ISTRIP Strip parity bit | ||
| 328 | * IGNBRK Ignore break condition | ||
| 329 | * BRKINT Send SIGINT on break - maybe set this? | ||
| 330 | * INLCR Map NL to CR | ||
| 331 | * IGNCR Ignore CR | ||
| 332 | * ICRNL Map CR to NL | ||
| 333 | * IUCLC Map uppercase to lowercase | ||
| 334 | * IMAXBEL Echo BEL on input line too long | ||
| 335 | * IUTF8 Appears to affect tty's idea of char widths, | ||
| 336 | * observed to improve backspacing through Unicode chars | ||
| 337 | */ | ||
| 338 | |||
| 339 | /* line buffered input (NL or EOL or EOF chars end a line); | ||
| 340 | * recognize INT/QUIT/SUSP chars; | ||
| 341 | * echo input chars; | ||
| 342 | * echo BS-SP-BS on erase character; | ||
| 343 | * echo kill char specially, not as ^c (ECHOKE controls how exactly); | ||
| 344 | * erase all input via BS-SP-BS on kill char (else go to next line) | ||
| 345 | */ | ||
| 279 | G.termios.c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE; | 346 | G.termios.c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE; |
| 280 | /* no longer in lflag: | ECHOCTL | ECHOPRT */ | 347 | /* Other bits in c_lflag: |
| 281 | G.termios.c_oflag |= OPOST; | 348 | * XCASE Map uppercase to \lowercase [tried, doesn't work] |
| 282 | /* G.termios.c_cflag = 0; */ | 349 | * ECHONL Echo NL even if ECHO is not set |
| 350 | * ECHOCTL Echo ctrl chars as ^c (else don't echo) - maybe set this? | ||
| 351 | * ECHOPRT On erase, echo erased chars | ||
| 352 | * [qwe<BS><BS><BS> input looks like "qwe\ewq/" on screen] | ||
| 353 | * NOFLSH Don't flush input buffer after interrupt or quit chars | ||
| 354 | * IEXTEN Enable extended functions (??) | ||
| 355 | * [glibc says it enables c_cc[LNEXT] "enter literal char" | ||
| 356 | * and c_cc[VDISCARD] "toggle discard buffered output" chars] | ||
| 357 | * FLUSHO Output being flushed (c_cc[VDISCARD] is in effect) | ||
| 358 | * PENDIN Retype pending input at next read or input char | ||
| 359 | * (c_cc[VREPRINT] is being processed) | ||
| 360 | * TOSTOP Send SIGTTOU for background output | ||
| 361 | * (why "stty sane" unsets this bit?) | ||
| 362 | */ | ||
| 363 | |||
| 283 | G.termios.c_cc[VINTR] = DEF_INTR; | 364 | G.termios.c_cc[VINTR] = DEF_INTR; |
| 284 | G.termios.c_cc[VQUIT] = DEF_QUIT; | 365 | G.termios.c_cc[VQUIT] = DEF_QUIT; |
| 285 | G.termios.c_cc[VEOF] = DEF_EOF; | 366 | G.termios.c_cc[VEOF] = DEF_EOF; |
| @@ -290,24 +371,17 @@ static void termios_final(void) | |||
| 290 | #ifdef VSWTCH | 371 | #ifdef VSWTCH |
| 291 | G.termios.c_cc[VSWTCH] = DEF_SWITCH; | 372 | G.termios.c_cc[VSWTCH] = DEF_SWITCH; |
| 292 | #endif | 373 | #endif |
| 293 | |||
| 294 | /* Account for special characters seen in input */ | ||
| 295 | if (G.eol == '\r') { | ||
| 296 | G.termios.c_iflag |= ICRNL; /* map CR in input to NL */ | ||
| 297 | /* already done by termios_init */ | ||
| 298 | /* G.termios.c_oflag |= ONLCR; map NL in output to CR-NL */ | ||
| 299 | } | ||
| 300 | G.termios.c_cc[VKILL] = DEF_KILL; | 374 | G.termios.c_cc[VKILL] = DEF_KILL; |
| 375 | /* Other control chars: | ||
| 376 | * VEOL2 | ||
| 377 | * VERASE, VWERASE - (word) erase. we may set VERASE in get_logname | ||
| 378 | * VREPRINT - reprint current input buffer | ||
| 379 | * VLNEXT, VDISCARD, VSTATUS | ||
| 380 | * VSUSP, VDSUSP - send (delayed) SIGTSTP | ||
| 381 | * VSTART, VSTOP - chars used for IXON/IXOFF | ||
| 382 | */ | ||
| 301 | 383 | ||
| 302 | #ifdef CRTSCTS | 384 | set_termios(); |
| 303 | /* Optionally enable hardware flow control */ | ||
| 304 | if (option_mask32 & F_RTSCTS) | ||
| 305 | G.termios.c_cflag |= CRTSCTS; | ||
| 306 | #endif | ||
| 307 | |||
| 308 | /* Finally, make the new settings effective */ | ||
| 309 | if (tcsetattr_stdin_TCSANOW(&G.termios) < 0) | ||
| 310 | bb_perror_msg_and_die("tcsetattr"); | ||
| 311 | } | 385 | } |
| 312 | 386 | ||
| 313 | /* extract baud rate from modem status message */ | 387 | /* extract baud rate from modem status message */ |
| @@ -330,12 +404,8 @@ static void auto_baud(void) | |||
| 330 | * modem status messages is enabled. | 404 | * modem status messages is enabled. |
| 331 | */ | 405 | */ |
| 332 | 406 | ||
| 333 | /* | 407 | G.termios.c_cc[VMIN] = 0; /* don't block reads (min read is 0 chars) */ |
| 334 | * Don't block if input queue is empty. | 408 | set_termios(); |
| 335 | * Errors will be dealt with later on. | ||
| 336 | */ | ||
| 337 | G.termios.c_cc[VMIN] = 0; /* don't block if queue empty */ | ||
| 338 | tcsetattr_stdin_TCSANOW(&G.termios); | ||
| 339 | 409 | ||
| 340 | /* | 410 | /* |
| 341 | * Wait for a while, then read everything the modem has said so far and | 411 | * Wait for a while, then read everything the modem has said so far and |
| @@ -357,9 +427,9 @@ static void auto_baud(void) | |||
| 357 | } | 427 | } |
| 358 | } | 428 | } |
| 359 | 429 | ||
| 360 | /* Restore terminal settings. Errors will be dealt with later on */ | 430 | /* Restore terminal settings */ |
| 361 | G.termios.c_cc[VMIN] = 1; /* restore to value set by termios_init */ | 431 | G.termios.c_cc[VMIN] = 1; /* restore to value set by termios_init */ |
| 362 | tcsetattr_stdin_TCSANOW(&G.termios); | 432 | set_termios(); |
| 363 | } | 433 | } |
| 364 | 434 | ||
| 365 | /* get user name, establish parity, speed, erase, kill, eol; | 435 | /* get user name, establish parity, speed, erase, kill, eol; |
| @@ -538,6 +608,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv) | |||
| 538 | 608 | ||
| 539 | /* Set the optional timer */ | 609 | /* Set the optional timer */ |
| 540 | alarm(G.timeout); /* if 0, alarm is not set */ | 610 | alarm(G.timeout); /* if 0, alarm is not set */ |
| 611 | //BUG: death by signal won't restore termios | ||
| 541 | 612 | ||
| 542 | /* Optionally wait for CR or LF before writing /etc/issue */ | 613 | /* Optionally wait for CR or LF before writing /etc/issue */ |
| 543 | if (option_mask32 & F_WAITCRLF) { | 614 | if (option_mask32 & F_WAITCRLF) { |
| @@ -565,7 +636,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv) | |||
| 565 | /* We are here only if G.numspeed > 1 */ | 636 | /* We are here only if G.numspeed > 1 */ |
| 566 | baud_index = (baud_index + 1) % G.numspeed; | 637 | baud_index = (baud_index + 1) % G.numspeed; |
| 567 | cfsetspeed(&G.termios, G.speeds[baud_index]); | 638 | cfsetspeed(&G.termios, G.speeds[baud_index]); |
| 568 | tcsetattr_stdin_TCSANOW(&G.termios); | 639 | set_termios(); |
| 569 | } | 640 | } |
| 570 | } | 641 | } |
| 571 | 642 | ||
