aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Korsgaard <jacmet@sunsite.dk>2011-01-26 15:15:19 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2011-01-26 15:15:19 +0100
commitddd1ec1c279da19a79238ce9df820d79415fa33a (patch)
tree7c40426eef48b9986e98f8dc821ac2b0bd207f8c
parente3d4c03852f17b20eafaedf957afa1b0bf03c66f (diff)
downloadbusybox-w32-ddd1ec1c279da19a79238ce9df820d79415fa33a.tar.gz
busybox-w32-ddd1ec1c279da19a79238ce9df820d79415fa33a.tar.bz2
busybox-w32-ddd1ec1c279da19a79238ce9df820d79415fa33a.zip
getty: wait up to 5 seconds for the output buffer to drain
Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--loginutils/getty.c56
1 files changed, 33 insertions, 23 deletions
diff --git a/loginutils/getty.c b/loginutils/getty.c
index 2d2184a76..035534157 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -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,25 +239,31 @@ 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. Errors will be dealt with
252 * later on. 264 * later on.
253 */ 265 */
254 /* 8 bits; hangup (drop DTR) on last close; enable receive */ 266 /* 8 bits; hang up (drop DTR) on last close; enable receive */
255 G.termios.c_cflag = CS8 | HUPCL | CREAD; 267 G.termios.c_cflag = CS8 | HUPCL | CREAD;
256 if (option_mask32 & F_LOCAL) { 268 if (option_mask32 & F_LOCAL) {
257 /* ignore Carrier Detect pin: 269 /* ignore Carrier Detect pin:
@@ -266,9 +278,8 @@ static void termios_init(int speed)
266#endif 278#endif
267 /* Other bits in c_cflag: 279 /* Other bits in c_cflag:
268 * CSTOPB 2 stop bits (1 otherwise) 280 * CSTOPB 2 stop bits (1 otherwise)
269 * PARENB Enable parity bit 281 * PARENB Enable parity bit (both on input and output)
270 * PARODD Use odd parity (else even) 282 * PARODD Odd parity (else even)
271 * LOBLK Block job control output (??)
272 */ 283 */
273 G.termios.c_iflag = 0; 284 G.termios.c_iflag = 0;
274 G.termios.c_lflag = 0; 285 G.termios.c_lflag = 0;
@@ -281,7 +292,7 @@ static void termios_init(int speed)
281 G.termios.c_line = 0; 292 G.termios.c_line = 0;
282#endif 293#endif
283 294
284 tcsetattr_stdin_TCSANOW(&G.termios); 295 set_termios();
285 296
286 debug("term_io 2\n"); 297 debug("term_io 2\n");
287} 298}
@@ -309,8 +320,8 @@ static void termios_final(void)
309 * ICRNL Map CR to NL 320 * ICRNL Map CR to NL
310 * IUCLC Map uppercase to lowercase 321 * IUCLC Map uppercase to lowercase
311 * IMAXBEL Echo BEL on input line too long 322 * IMAXBEL Echo BEL on input line too long
312 * IUTF8 [Appears to affect tty's idea of char widths, 323 * IUTF8 Appears to affect tty's idea of char widths,
313 * observed to improve backspacing through Unicode chars] 324 * observed to improve backspacing through Unicode chars
314 */ 325 */
315 326
316 /* line buffered input (NL or EOL or EOF chars end a line); 327 /* line buffered input (NL or EOL or EOF chars end a line);
@@ -324,16 +335,16 @@ static void termios_final(void)
324 /* Other bits in c_lflag: 335 /* Other bits in c_lflag:
325 * XCASE Map uppercase to \lowercase [tried, doesn't work] 336 * XCASE Map uppercase to \lowercase [tried, doesn't work]
326 * ECHONL Echo NL even if ECHO is not set 337 * ECHONL Echo NL even if ECHO is not set
338 * ECHOCTL Echo ctrl chars as ^c (else don't echo) - maybe set this?
339 * ECHOPRT On erase, echo erased chars
340 * [qwe<BS><BS><BS> input looks like "qwe\ewq/" on screen]
327 * NOFLSH Don't flush input buffer after interrupt or quit chars 341 * NOFLSH Don't flush input buffer after interrupt or quit chars
328 * IEXTEN Enable extended functions (??) 342 * IEXTEN Enable extended functions (??)
329 * [glibc says it enables c_cc[LNEXT] "enter literal char" 343 * [glibc says it enables c_cc[LNEXT] "enter literal char"
330 * and c_cc[VDISCARD] "toggle discard buffered output" chars] 344 * and c_cc[VDISCARD] "toggle discard buffered output" chars]
331 * ECHOCTL Echo ctrl chars as ^c (else don't echo) - maybe set this?
332 * ECHOPRT On erase, echo erased chars
333 * [qwe<BS><BS><BS> input looks like "qwe\ewq/" on screen]
334 * FLUSHO Output being flushed (c_cc[VDISCARD] is in effect) 345 * FLUSHO Output being flushed (c_cc[VDISCARD] is in effect)
335 * PENDIN Retype pending input at next read or input char 346 * PENDIN Retype pending input at next read or input char
336 * (c_cc[VREPRINT] is being processes) 347 * (c_cc[VREPRINT] is being processed)
337 * TOSTOP Send SIGTTOU for background output 348 * TOSTOP Send SIGTTOU for background output
338 * (why "stty sane" unsets this bit?) 349 * (why "stty sane" unsets this bit?)
339 */ 350 */
@@ -358,8 +369,7 @@ static void termios_final(void)
358 * VSTART, VSTOP - chars used for IXON/IXOFF 369 * VSTART, VSTOP - chars used for IXON/IXOFF
359 */ 370 */
360 371
361 if (tcsetattr_stdin_TCSANOW(&G.termios) < 0) 372 set_termios();
362 bb_perror_msg_and_die("tcsetattr");
363} 373}
364 374
365/* extract baud rate from modem status message */ 375/* extract baud rate from modem status message */
@@ -383,7 +393,7 @@ static void auto_baud(void)
383 */ 393 */
384 394
385 G.termios.c_cc[VMIN] = 0; /* don't block reads (min read is 0 chars) */ 395 G.termios.c_cc[VMIN] = 0; /* don't block reads (min read is 0 chars) */
386 tcsetattr_stdin_TCSANOW(&G.termios); 396 set_termios();
387 397
388 /* 398 /*
389 * Wait for a while, then read everything the modem has said so far and 399 * Wait for a while, then read everything the modem has said so far and
@@ -407,7 +417,7 @@ static void auto_baud(void)
407 417
408 /* Restore terminal settings. Errors will be dealt with later on */ 418 /* Restore terminal settings. Errors will be dealt with later on */
409 G.termios.c_cc[VMIN] = 1; /* restore to value set by termios_init */ 419 G.termios.c_cc[VMIN] = 1; /* restore to value set by termios_init */
410 tcsetattr_stdin_TCSANOW(&G.termios); 420 set_termios();
411} 421}
412 422
413/* get user name, establish parity, speed, erase, kill, eol; 423/* get user name, establish parity, speed, erase, kill, eol;
@@ -614,7 +624,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
614 /* We are here only if G.numspeed > 1 */ 624 /* We are here only if G.numspeed > 1 */
615 baud_index = (baud_index + 1) % G.numspeed; 625 baud_index = (baud_index + 1) % G.numspeed;
616 cfsetspeed(&G.termios, G.speeds[baud_index]); 626 cfsetspeed(&G.termios, G.speeds[baud_index]);
617 tcsetattr_stdin_TCSANOW(&G.termios); 627 set_termios();
618 } 628 }
619 } 629 }
620 630