aboutsummaryrefslogtreecommitdiff
path: root/loginutils
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-22 13:15:08 +0000
committerRon Yorston <rmy@pobox.com>2012-03-22 13:15:08 +0000
commitc0d4367d6b581eb5989c02815880cf0fa2851ae8 (patch)
tree868c266e627e2d7f65ba5a4d5f98a1c421453181 /loginutils
parentf6bad5ef766b0447158e3de2f55c35f1f6cecb58 (diff)
parentda4441c44f6efccb6f7b7588404d9c6bfb7b6af8 (diff)
downloadbusybox-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.src14
-rw-r--r--loginutils/getty.c177
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
186config LOGIN 198config 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
227static 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 */
234static void termios_init(int speed) 240static 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
275static void termios_final(void) 312static 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