diff options
author | Peter Korsgaard <jacmet@sunsite.dk> | 2011-01-26 15:15:19 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-01-26 15:15:19 +0100 |
commit | ddd1ec1c279da19a79238ce9df820d79415fa33a (patch) | |
tree | 7c40426eef48b9986e98f8dc821ac2b0bd207f8c | |
parent | e3d4c03852f17b20eafaedf957afa1b0bf03c66f (diff) | |
download | busybox-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.c | 56 |
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 | ||
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,25 +239,31 @@ 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. 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 | ||