aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-01-24 04:43:04 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2011-01-24 04:43:04 +0100
commit6596380f52cd48b8b44443bb5677ec8caf538761 (patch)
tree0628643e7f1230fc4fa7b6448231fe1378673022
parente9a40e3b91f699c08053d7307bf50b0764811b8e (diff)
downloadbusybox-w32-6596380f52cd48b8b44443bb5677ec8caf538761.tar.gz
busybox-w32-6596380f52cd48b8b44443bb5677ec8caf538761.tar.bz2
busybox-w32-6596380f52cd48b8b44443bb5677ec8caf538761.zip
getty: simplify code by going to more straignforward G trick
function old new delta getty_main 1615 1475 -140 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--loginutils/getty.c396
1 files changed, 121 insertions, 275 deletions
diff --git a/loginutils/getty.c b/loginutils/getty.c
index 13b341db5..bf66f2287 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -16,11 +16,9 @@
16 16
17#include "libbb.h" 17#include "libbb.h"
18#include <syslog.h> 18#include <syslog.h>
19
20#if ENABLE_FEATURE_UTMP 19#if ENABLE_FEATURE_UTMP
21# include <utmp.h> /* LOGIN_PROCESS */ 20# include <utmp.h> /* LOGIN_PROCESS */
22#endif 21#endif
23
24#ifndef IUCLC 22#ifndef IUCLC
25# define IUCLC 0 23# define IUCLC 0
26#endif 24#endif
@@ -36,7 +34,7 @@
36# undef ENABLE_FEATURE_WTMP 34# undef ENABLE_FEATURE_WTMP
37# define ENABLE_FEATURE_UTMP 0 35# define ENABLE_FEATURE_UTMP 0
38# define ENABLE_FEATURE_WTMP 0 36# define ENABLE_FEATURE_WTMP 0
39#endif /* LOGIN_PROCESS */ 37#endif
40 38
41 39
42/* The following is used for understandable diagnostics. */ 40/* The following is used for understandable diagnostics. */
@@ -56,18 +54,6 @@ static FILE *dbf;
56 * below. Note, however, that DEL cannot be used for interrupt generation 54 * below. Note, however, that DEL cannot be used for interrupt generation
57 * and for line editing at the same time. 55 * and for line editing at the same time.
58 */ 56 */
59
60/* I doubt there are systems which still... */
61/* ...have only uppercase: */
62#undef HANDLE_ALLCAPS
63/* ...use # and @ for backspace and line erase: */
64#undef ANCIENT_BS_KILL_CHARS
65/* It actually makes sense (tries to guess parity by looking at 7th bit)
66 * but it's broken, and interferes with non-ASCII login names
67 * (yes, I did receive complains from real users):
68 */
69#undef BROKEN_PARITY_DETECTION_CODE
70
71#undef _PATH_LOGIN 57#undef _PATH_LOGIN
72#define _PATH_LOGIN "/bin/login" 58#define _PATH_LOGIN "/bin/login"
73 59
@@ -100,8 +86,7 @@ static FILE *dbf;
100 */ 86 */
101#define MAX_SPEED 10 /* max. nr. of baud rates */ 87#define MAX_SPEED 10 /* max. nr. of baud rates */
102 88
103/* Storage for command-line options. */ 89struct globals {
104struct options {
105 unsigned timeout; /* time-out period */ 90 unsigned timeout; /* time-out period */
106 const char *login; /* login program */ 91 const char *login; /* login program */
107 const char *tty; /* name of tty */ 92 const char *tty; /* name of tty */
@@ -109,46 +94,17 @@ struct options {
109 const char *issue; /* alternative issue file */ 94 const char *issue; /* alternative issue file */
110 int numspeed; /* number of baud rates to try */ 95 int numspeed; /* number of baud rates to try */
111 int speeds[MAX_SPEED]; /* baud rates to be tried */ 96 int speeds[MAX_SPEED]; /* baud rates to be tried */
97 struct termios termios; /* terminal mode bits */
98 /* Storage for things detected while the login name was read. */
99 unsigned char erase; /* erase character */
100 unsigned char eol; /* end-of-line character */
101 char line_buf[128];
112}; 102};
113 103
114/* Storage for things detected while the login name was read. */ 104#define G (*ptr_to_globals)
115struct chardata { 105#define INIT_G() do { \
116 unsigned char erase; /* erase character */ 106 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
117#ifdef ANCIENT_BS_KILL_CHARS 107} while (0)
118 unsigned char kill; /* kill character */
119#endif
120 unsigned char eol; /* end-of-line character */
121#ifdef BROKEN_PARITY_DETECTION_CODE
122 unsigned char parity; /* what parity did we see */
123 /* (parity & 1): saw odd parity char with 7th bit set */
124 /* (parity & 2): saw even parity char with 7th bit set */
125 /* parity == 0: probably 7-bit, space parity? */
126 /* parity == 1: probably 7-bit, odd parity? */
127 /* parity == 2: probably 7-bit, even parity? */
128 /* parity == 3: definitely 8 bit, no parity! */
129 /* Hmm... with any value of parity "8 bit, no parity" is possible */
130#endif
131#ifdef HANDLE_ALLCAPS
132 unsigned char capslock; /* upper case without lower case */
133#endif
134};
135
136/* Initial values for the above. */
137static const struct chardata init_chardata = {
138 DEF_ERASE, /* default erase character */
139#ifdef ANCIENT_BS_KILL_CHARS
140 DEF_KILL, /* default kill character */
141#endif
142 13, /* default eol char */
143#ifdef BROKEN_PARITY_DETECTION_CODE
144 0, /* space parity */
145#endif
146#ifdef HANDLE_ALLCAPS
147 0, /* no capslock */
148#endif
149};
150
151#define line_buf bb_common_bufsiz1
152 108
153//usage:#define getty_trivial_usage 109//usage:#define getty_trivial_usage
154//usage: "[OPTIONS] BAUD_RATE[,BAUD_RATE]... TTY [TERMTYPE]" 110//usage: "[OPTIONS] BAUD_RATE[,BAUD_RATE]... TTY [TERMTYPE]"
@@ -193,52 +149,53 @@ static int bcode(const char *s)
193} 149}
194 150
195/* parse alternate baud rates */ 151/* parse alternate baud rates */
196static void parse_speeds(struct options *op, char *arg) 152static void parse_speeds(char *arg)
197{ 153{
198 char *cp; 154 char *cp;
199 155
200 /* NB: at least one iteration is always done */ 156 /* NB: at least one iteration is always done */
201 debug("entered parse_speeds\n"); 157 debug("entered parse_speeds\n");
202 while ((cp = strsep(&arg, ",")) != NULL) { 158 while ((cp = strsep(&arg, ",")) != NULL) {
203 op->speeds[op->numspeed] = bcode(cp); 159 G.speeds[G.numspeed] = bcode(cp);
204 if (op->speeds[op->numspeed] < 0) 160 if (G.speeds[G.numspeed] < 0)
205 bb_error_msg_and_die("bad speed: %s", cp); 161 bb_error_msg_and_die("bad speed: %s", cp);
206 /* note: arg "0" turns into speed B0 */ 162 /* note: arg "0" turns into speed B0 */
207 op->numspeed++; 163 G.numspeed++;
208 if (op->numspeed > MAX_SPEED) 164 if (G.numspeed > MAX_SPEED)
209 bb_error_msg_and_die("too many alternate speeds"); 165 bb_error_msg_and_die("too many alternate speeds");
210 } 166 }
211 debug("exiting parse_speeds\n"); 167 debug("exiting parse_speeds\n");
212} 168}
213 169
214/* parse command-line arguments */ 170/* parse command-line arguments */
215static void parse_args(char **argv, struct options *op, char **fakehost_p) 171static void parse_args(char **argv, char **fakehost_p)
216{ 172{
217 char *ts; 173 char *ts;
218 int flags; 174 int flags;
219 175
220 opt_complementary = "-2:t+"; /* at least 2 args; -t N */ 176 opt_complementary = "-2:t+"; /* at least 2 args; -t N */
221 flags = getopt32(argv, opt_string, 177 flags = getopt32(argv, opt_string,
222 &(op->initstring), fakehost_p, &(op->issue), 178 &G.initstring, fakehost_p, &G.issue,
223 &(op->login), &op->timeout); 179 &G.login, &G.timeout
180 );
224 if (flags & F_INITSTRING) { 181 if (flags & F_INITSTRING) {
225 op->initstring = xstrdup(op->initstring); 182 G.initstring = xstrdup(G.initstring);
226 /* decode \ddd octal codes into chars */ 183 /* decode \ddd octal codes into chars */
227 strcpy_and_process_escape_sequences((char*)op->initstring, op->initstring); 184 strcpy_and_process_escape_sequences((char*)G.initstring, G.initstring);
228 } 185 }
229 argv += optind; 186 argv += optind;
230 debug("after getopt\n"); 187 debug("after getopt\n");
231 188
232 /* we loosen up a bit and accept both "baudrate tty" and "tty baudrate" */ 189 /* We loosen up a bit and accept both "baudrate tty" and "tty baudrate" */
233 op->tty = argv[0]; /* tty name */ 190 G.tty = argv[0]; /* tty name */
234 ts = argv[1]; /* baud rate(s) */ 191 ts = argv[1]; /* baud rate(s) */
235 if (isdigit(argv[0][0])) { 192 if (isdigit(argv[0][0])) {
236 /* a number first, assume it's a speed (BSD style) */ 193 /* A number first, assume it's a speed (BSD style) */
237 op->tty = ts; /* tty name is in argv[1] */ 194 G.tty = ts; /* tty name is in argv[1] */
238 ts = argv[0]; /* baud rate(s) */ 195 ts = argv[0]; /* baud rate(s) */
239 } 196 }
240 parse_speeds(op, ts); 197 parse_speeds(ts);
241 applet_name = xasprintf("getty: %s", op->tty); 198 applet_name = xasprintf("getty: %s", G.tty);
242 199
243 if (argv[2]) 200 if (argv[2])
244 xsetenv("TERM", argv[2]); 201 xsetenv("TERM", argv[2]);
@@ -247,17 +204,17 @@ static void parse_args(char **argv, struct options *op, char **fakehost_p)
247} 204}
248 205
249/* set up tty as standard input, output, error */ 206/* set up tty as standard input, output, error */
250static void open_tty(const char *tty) 207static void open_tty(void)
251{ 208{
252 /* Set up new standard input, unless we are given an already opened port. */ 209 /* Set up new standard input, unless we are given an already opened port. */
253 if (NOT_LONE_DASH(tty)) { 210 if (NOT_LONE_DASH(G.tty)) {
254 if (tty[0] != '/') 211 if (G.tty[0] != '/')
255 tty = xasprintf("/dev/%s", tty); /* will leak it */ 212 G.tty = xasprintf("/dev/%s", G.tty); /* will leak it */
256 213
257 /* Open the tty as standard input. */ 214 /* Open the tty as standard input. */
258 debug("open(2)\n"); 215 debug("open(2)\n");
259 close(0); 216 close(0);
260 /*fd =*/ xopen(tty, O_RDWR | O_NONBLOCK); /* uses fd 0 */ 217 xopen(G.tty, O_RDWR | O_NONBLOCK); /* uses fd 0 */
261 218
262 /* Set proper protections and ownership. */ 219 /* Set proper protections and ownership. */
263 fchown(0, 0, 0); /* 0:0 */ 220 fchown(0, 0, 0); /* 0:0 */
@@ -273,7 +230,7 @@ static void open_tty(const char *tty)
273} 230}
274 231
275/* initialize termios settings */ 232/* initialize termios settings */
276static void termios_init(struct termios *tp, int speed) 233static void termios_init(int speed)
277{ 234{
278 /* Flush input and output queues, important for modems! 235 /* Flush input and output queues, important for modems!
279 * Users report losing previously queued output chars, and I hesitate 236 * Users report losing previously queued output chars, and I hesitate
@@ -285,7 +242,7 @@ static void termios_init(struct termios *tp, int speed)
285 242
286 /* Set speed if it wasn't specified as "0" on command line. */ 243 /* Set speed if it wasn't specified as "0" on command line. */
287 if (speed != B0) 244 if (speed != B0)
288 cfsetspeed(tp, speed); 245 cfsetspeed(&G.termios, speed);
289 246
290 /* 247 /*
291 * Initial termios settings: 8-bit characters, raw-mode, blocking i/o. 248 * Initial termios settings: 8-bit characters, raw-mode, blocking i/o.
@@ -293,31 +250,29 @@ static void termios_init(struct termios *tp, int speed)
293 * reads will be done in raw mode anyway. Errors will be dealt with 250 * reads will be done in raw mode anyway. Errors will be dealt with
294 * later on. 251 * later on.
295 */ 252 */
296 tp->c_cflag = CS8 | HUPCL | CREAD; 253 G.termios.c_cflag = CS8 | HUPCL | CREAD;
297 if (option_mask32 & F_LOCAL) 254 if (option_mask32 & F_LOCAL)
298 tp->c_cflag |= CLOCAL; 255 G.termios.c_cflag |= CLOCAL;
299 tp->c_iflag = 0; 256 G.termios.c_iflag = 0;
300 tp->c_lflag = 0; 257 G.termios.c_lflag = 0;
301 tp->c_oflag = OPOST | ONLCR; 258 G.termios.c_oflag = OPOST | ONLCR;
302 tp->c_cc[VMIN] = 1; 259 G.termios.c_cc[VMIN] = 1;
303 tp->c_cc[VTIME] = 0; 260 G.termios.c_cc[VTIME] = 0;
304#ifdef __linux__ 261#ifdef __linux__
305 tp->c_line = 0; 262 G.termios.c_line = 0;
306#endif 263#endif
307
308 /* Optionally enable hardware flow control */
309#ifdef CRTSCTS 264#ifdef CRTSCTS
310 if (option_mask32 & F_RTSCTS) 265 if (option_mask32 & F_RTSCTS)
311 tp->c_cflag |= CRTSCTS; 266 G.termios.c_cflag |= CRTSCTS;
312#endif 267#endif
313 268
314 tcsetattr_stdin_TCSANOW(tp); 269 tcsetattr_stdin_TCSANOW(&G.termios);
315 270
316 debug("term_io 2\n"); 271 debug("term_io 2\n");
317} 272}
318 273
319/* extract baud rate from modem status message */ 274/* extract baud rate from modem status message */
320static void auto_baud(char *buf, unsigned size_buf, struct termios *tp) 275static void auto_baud(void)
321{ 276{
322 int speed; 277 int speed;
323 int vmin; 278 int vmin;
@@ -344,83 +299,60 @@ static void auto_baud(char *buf, unsigned size_buf, struct termios *tp)
344 * Use 7-bit characters, don't block if input queue is empty. Errors will 299 * Use 7-bit characters, don't block if input queue is empty. Errors will
345 * be dealt with later on. 300 * be dealt with later on.
346 */ 301 */
347 iflag = tp->c_iflag; 302 iflag = G.termios.c_iflag;
348 tp->c_iflag |= ISTRIP; /* enable 8th-bit stripping */ 303 G.termios.c_iflag |= ISTRIP; /* enable 8th-bit stripping */
349 vmin = tp->c_cc[VMIN]; 304 vmin = G.termios.c_cc[VMIN];
350 tp->c_cc[VMIN] = 0; /* don't block if queue empty */ 305 G.termios.c_cc[VMIN] = 0; /* don't block if queue empty */
351 tcsetattr_stdin_TCSANOW(tp); 306 tcsetattr_stdin_TCSANOW(&G.termios);
352 307
353 /* 308 /*
354 * Wait for a while, then read everything the modem has said so far and 309 * Wait for a while, then read everything the modem has said so far and
355 * try to extract the speed of the dial-in call. 310 * try to extract the speed of the dial-in call.
356 */ 311 */
357 sleep(1); 312 sleep(1);
358 nread = safe_read(STDIN_FILENO, buf, size_buf - 1); 313 nread = safe_read(STDIN_FILENO, G.line_buf, sizeof(G.line_buf) - 1);
359 if (nread > 0) { 314 if (nread > 0) {
360 buf[nread] = '\0'; 315 G.line_buf[nread] = '\0';
361 for (bp = buf; bp < buf + nread; bp++) { 316 for (bp = G.line_buf; bp < G.line_buf + nread; bp++) {
362 if (isdigit(*bp)) { 317 if (isdigit(*bp)) {
363 speed = bcode(bp); 318 speed = bcode(bp);
364 if (speed > 0) 319 if (speed > 0)
365 cfsetspeed(tp, speed); 320 cfsetspeed(&G.termios, speed);
366 break; 321 break;
367 } 322 }
368 } 323 }
369 } 324 }
370 325
371 /* Restore terminal settings. Errors will be dealt with later on. */ 326 /* Restore terminal settings. Errors will be dealt with later on. */
372 tp->c_iflag = iflag; 327 G.termios.c_iflag = iflag;
373 tp->c_cc[VMIN] = vmin; 328 G.termios.c_cc[VMIN] = vmin;
374 tcsetattr_stdin_TCSANOW(tp); 329 tcsetattr_stdin_TCSANOW(&G.termios);
375}
376
377#ifdef HANDLE_ALLCAPS
378/* does string contain upper case without lower case? */
379static int all_is_upcase(const char *s)
380{
381 while (*s)
382 if (islower(*s++))
383 return 0;
384 return 1;
385} 330}
386#endif
387 331
388/* get user name, establish parity, speed, erase, kill, eol; 332/* get user name, establish parity, speed, erase, kill, eol;
389 * return NULL on BREAK, logname on success */ 333 * return NULL on BREAK, logname on success */
390static char *get_logname(char *logname, unsigned size_logname, 334static char *get_logname(void)
391 struct options *op, struct chardata *cp)
392{ 335{
393 char *bp; 336 char *bp;
394 char c; /* input character, full eight bits */ 337 char c;
395 char ascval; /* low 7 bits of input character */
396#ifdef BROKEN_PARITY_DETECTION_CODE
397 static const char erase[][3] = {/* backspace-space-backspace */
398 "\010\040\010", /* space parity */
399 "\010\040\010", /* odd parity */
400 "\210\240\210", /* even parity */
401 "\010\040\010", /* 8 bit no parity */
402 };
403#endif
404
405 /* NB: *cp is pre-initialized with init_chardata */
406 338
407 /* Flush pending input (esp. after parsing or switching the baud rate). */ 339 /* Flush pending input (esp. after parsing or switching the baud rate). */
408 usleep(100*1000); /* 0.1 sec */ 340 usleep(100*1000); /* 0.1 sec */
409 tcflush(STDIN_FILENO, TCIOFLUSH); 341 tcflush(STDIN_FILENO, TCIOFLUSH);
410 342
411 /* Prompt for and read a login name. */ 343 /* Prompt for and read a login name. */
412 logname[0] = '\0'; 344 G.line_buf[0] = '\0';
413 while (!logname[0]) { 345 while (!G.line_buf[0]) {
414 /* Write issue file and prompt. */ 346 /* Write issue file and prompt. */
415#ifdef ISSUE 347#ifdef ISSUE
416 if (!(option_mask32 & F_NOISSUE)) 348 if (!(option_mask32 & F_NOISSUE))
417 print_login_issue(op->issue, op->tty); 349 print_login_issue(G.issue, G.tty);
418#endif 350#endif
419 print_login_prompt(); 351 print_login_prompt();
420 352
421 /* Read name, watch for break, parity, erase, kill, end-of-line. */ 353 /* Read name, watch for break, parity, erase, kill, end-of-line. */
422 bp = logname; 354 bp = G.line_buf;
423 cp->eol = '\0'; 355 G.eol = '\0';
424 while (1) { 356 while (1) {
425 /* Do not report trivial EINTR/EIO errors. */ 357 /* Do not report trivial EINTR/EIO errors. */
426 errno = EINTR; /* make read of 0 bytes be silent too */ 358 errno = EINTR; /* make read of 0 bytes be silent too */
@@ -432,71 +364,39 @@ static char *get_logname(char *logname, unsigned size_logname,
432 364
433 /* BREAK. If we have speeds to try, 365 /* BREAK. If we have speeds to try,
434 * return NULL (will switch speeds and return here) */ 366 * return NULL (will switch speeds and return here) */
435 if (c == '\0' && op->numspeed > 1) 367 if (c == '\0' && G.numspeed > 1)
436 return NULL; 368 return NULL;
437 369
438#ifdef BROKEN_PARITY_DETECTION_CODE
439 /* Do parity bit handling. */
440 if (!(option_mask32 & F_LOCAL) && (c & 0x80)) { /* "parity" bit on? */
441 int bits = 1;
442 int mask = 1;
443 while (mask & 0x7f) {
444 if (mask & c)
445 bits++; /* count "1" bits */
446 mask <<= 1;
447 }
448 /* ... |= 2 - even, 1 - odd */
449 cp->parity |= 2 - (bits & 1);
450 }
451 ascval = c & 0x7f;
452#else
453 ascval = c;
454#endif
455
456 /* Do erase, kill and end-of-line processing. */ 370 /* Do erase, kill and end-of-line processing. */
457 switch (ascval) { 371 switch (c) {
458 case CR: 372 case CR:
459 case NL: 373 case NL:
460 *bp = '\0'; /* terminate logname */ 374 *bp = '\0';
461 cp->eol = ascval; /* set end-of-line char */ 375 G.eol = c;
462 goto got_logname; 376 goto got_logname;
463 case BS: 377 case BS:
464 case DEL: 378 case DEL:
465#ifdef ANCIENT_BS_KILL_CHARS 379 G.erase = c;
466 case '#': 380 if (bp > G.line_buf) {
467#endif
468 cp->erase = ascval; /* set erase character */
469 if (bp > logname) {
470#ifdef BROKEN_PARITY_DETECTION_CODE
471 full_write(STDOUT_FILENO, erase[cp->parity], 3);
472#else
473 full_write(STDOUT_FILENO, "\010 \010", 3); 381 full_write(STDOUT_FILENO, "\010 \010", 3);
474#endif
475 bp--; 382 bp--;
476 } 383 }
477 break; 384 break;
478 case CTL('U'): 385 case CTL('U'):
479#ifdef ANCIENT_BS_KILL_CHARS 386 while (bp > G.line_buf) {
480 case '@':
481 cp->kill = ascval; /* set kill character */
482#endif
483 while (bp > logname) {
484#ifdef BROKEN_PARITY_DETECTION_CODE
485 full_write(STDOUT_FILENO, erase[cp->parity], 3);
486#else
487 full_write(STDOUT_FILENO, "\010 \010", 3); 387 full_write(STDOUT_FILENO, "\010 \010", 3);
488#endif
489 bp--; 388 bp--;
490 } 389 }
491 break; 390 break;
492 case CTL('D'): 391 case CTL('D'):
493 exit(EXIT_SUCCESS); 392 exit(EXIT_SUCCESS);
494 default: 393 default:
495 if (ascval < ' ') { 394 if ((unsigned char)c < ' ') {
496 /* ignore garbage characters */ 395 /* ignore garbage characters */
497 } else if ((int)(bp - logname) < size_logname - 1) { 396 } else if ((int)(bp - G.line_buf) < sizeof(G.line_buf) - 1) {
498 full_write(STDOUT_FILENO, &c, 1); /* echo the character */ 397 /* echo and store the character */
499 *bp++ = ascval; /* and store it */ 398 full_write(STDOUT_FILENO, &c, 1);
399 *bp++ = c;
500 } 400 }
501 break; 401 break;
502 } 402 }
@@ -504,87 +404,42 @@ static char *get_logname(char *logname, unsigned size_logname,
504 got_logname: ; 404 got_logname: ;
505 } /* while logname is empty */ 405 } /* while logname is empty */
506 406
507#ifdef HANDLE_ALLCAPS 407 return G.line_buf;
508 /* Handle names with upper case and no lower case. */
509 cp->capslock = all_is_upcase(logname);
510 if (cp->capslock) {
511 for (bp = logname; *bp; bp++)
512 if (isupper(*bp))
513 *bp = tolower(*bp); /* map name to lower case */
514 }
515#endif
516 return logname;
517} 408}
518 409
519/* set the final tty mode bits */ 410/* set the final tty mode bits */
520static void termios_final(struct termios *tp, struct chardata *cp) 411static void termios_final(void)
521{ 412{
522 /* General terminal-independent stuff. */ 413 /* General terminal-independent stuff. */
523 tp->c_iflag |= IXON | IXOFF; /* 2-way flow control */ 414 G.termios.c_iflag |= IXON | IXOFF; /* 2-way flow control */
524 tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE; 415 G.termios.c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE;
525 /* no longer| ECHOCTL | ECHOPRT */ 416 /* no longer in lflag: | ECHOCTL | ECHOPRT */
526 tp->c_oflag |= OPOST; 417 G.termios.c_oflag |= OPOST;
527 /* tp->c_cflag = 0; */ 418 /* G.termios.c_cflag = 0; */
528 tp->c_cc[VINTR] = DEF_INTR; /* default interrupt */ 419 G.termios.c_cc[VINTR] = DEF_INTR; /* default interrupt */
529 tp->c_cc[VQUIT] = DEF_QUIT; /* default quit */ 420 G.termios.c_cc[VQUIT] = DEF_QUIT; /* default quit */
530 tp->c_cc[VEOF] = DEF_EOF; /* default EOF character */ 421 G.termios.c_cc[VEOF] = DEF_EOF; /* default EOF character */
531 tp->c_cc[VEOL] = DEF_EOL; 422 G.termios.c_cc[VEOL] = DEF_EOL;
532#ifdef VSWTC 423#ifdef VSWTC
533 tp->c_cc[VSWTC] = DEF_SWITCH; /* default switch character */ 424 G.termios.c_cc[VSWTC] = DEF_SWITCH; /* default switch character */
534#endif 425#endif
535 426
536 /* Account for special characters seen in input. */ 427 /* Account for special characters seen in input. */
537 if (cp->eol == CR) { 428 if (G.eol == CR) {
538 tp->c_iflag |= ICRNL; /* map CR in input to NL */ 429 G.termios.c_iflag |= ICRNL; /* map CR in input to NL */
539 tp->c_oflag |= ONLCR; /* map NL in output to CR-NL */ 430 G.termios.c_oflag |= ONLCR; /* map NL in output to CR-NL */
540 }
541 tp->c_cc[VERASE] = cp->erase; /* set erase character */
542#ifdef ANCIENT_BS_KILL_CHARS
543 tp->c_cc[VKILL] = cp->kill; /* set kill character */
544#else
545 tp->c_cc[VKILL] = DEF_KILL; /* set kill character */
546#endif
547
548#ifdef BROKEN_PARITY_DETECTION_CODE
549 /* Account for the presence or absence of parity bits in input. */
550 switch (cp->parity) {
551 case 0: /* space (always 0) parity */
552// I bet most people go here - they use only 7-bit chars in usernames....
553 break;
554 case 1: /* odd parity */
555 tp->c_cflag |= PARODD;
556 /* FALLTHROUGH */
557 case 2: /* even parity */
558 tp->c_cflag |= PARENB;
559 tp->c_iflag |= INPCK | ISTRIP;
560 /* FALLTHROUGH */
561 case (1 | 2): /* no parity bit */
562 tp->c_cflag &= ~CSIZE;
563 tp->c_cflag |= CS7;
564// FIXME: wtf? case 3: we saw both even and odd 8-bit bytes -
565// it's probably some umlauts etc, but definitely NOT 7-bit!!!
566// Entire parity detection madness here just begs for deletion...
567 break;
568 } 431 }
569#endif 432 G.termios.c_cc[VERASE] = G.erase; /* set erase character */
570 433 G.termios.c_cc[VKILL] = DEF_KILL; /* set kill character */
571#ifdef HANDLE_ALLCAPS
572 /* Account for upper case without lower case. */
573 if (cp->capslock) {
574 tp->c_iflag |= IUCLC;
575 tp->c_lflag |= XCASE;
576 tp->c_oflag |= OLCUC;
577 }
578#endif
579 434
580#ifdef CRTSCTS 435#ifdef CRTSCTS
581 /* Optionally enable hardware flow control */ 436 /* Optionally enable hardware flow control */
582 if (option_mask32 & F_RTSCTS) 437 if (option_mask32 & F_RTSCTS)
583 tp->c_cflag |= CRTSCTS; 438 G.termios.c_cflag |= CRTSCTS;
584#endif 439#endif
585 440
586 /* Finally, make the new settings effective */ 441 /* Finally, make the new settings effective */
587 if (tcsetattr_stdin_TCSANOW(tp) < 0) 442 if (tcsetattr_stdin_TCSANOW(&G.termios) < 0)
588 bb_perror_msg_and_die("tcsetattr"); 443 bb_perror_msg_and_die("tcsetattr");
589} 444}
590 445
@@ -593,27 +448,20 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
593{ 448{
594 int n; 449 int n;
595 pid_t pid; 450 pid_t pid;
596 char *fakehost = NULL; /* Fake hostname for ut_host */ 451 char *fakehost = NULL; /* Fake hostname for ut_host */
597 char *logname; /* login name, given to /bin/login */ 452 char *logname;
598 /* Merging these into "struct local" may _seem_ to reduce
599 * parameter passing, but today's gcc will inline
600 * statics which are called once anyway, so don't do that */
601 struct chardata chardata; /* set by get_logname() */
602 struct termios termios; /* terminal mode bits */
603 struct options options;
604
605 chardata = init_chardata;
606 453
607 memset(&options, 0, sizeof(options)); 454 INIT_G();
608 options.login = _PATH_LOGIN; /* default login program */ 455 G.login = _PATH_LOGIN; /* default login program */
609 options.tty = "tty1"; /* default tty line */ 456 G.initstring = ""; /* modem init string */
610 options.initstring = ""; /* modem init string */
611#ifdef ISSUE 457#ifdef ISSUE
612 options.issue = ISSUE; /* default issue file */ 458 G.issue = ISSUE; /* default issue file */
613#endif 459#endif
460 G.erase = DEF_ERASE;
461 G.eol = CR;
614 462
615 /* Parse command-line arguments. */ 463 /* Parse command-line arguments. */
616 parse_args(argv, &options, &fakehost); 464 parse_args(argv, &fakehost);
617 465
618 logmode = LOGMODE_NONE; 466 logmode = LOGMODE_NONE;
619 467
@@ -648,7 +496,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
648 /* Open the tty as standard input, if it is not "-" */ 496 /* Open the tty as standard input, if it is not "-" */
649 /* If it's not "-" and not taken yet, it will become our ctty */ 497 /* If it's not "-" and not taken yet, it will become our ctty */
650 debug("calling open_tty\n"); 498 debug("calling open_tty\n");
651 open_tty(options.tty); 499 open_tty();
652 ndelay_off(0); 500 ndelay_off(0);
653 debug("duping\n"); 501 debug("duping\n");
654 xdup2(0, 1); 502 xdup2(0, 1);
@@ -662,7 +510,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
662 * by patching the SunOS kernel variable "zsadtrlow" to a larger value; 510 * by patching the SunOS kernel variable "zsadtrlow" to a larger value;
663 * 5 seconds seems to be a good value. 511 * 5 seconds seems to be a good value.
664 */ 512 */
665 if (tcgetattr(STDIN_FILENO, &termios) < 0) 513 if (tcgetattr(STDIN_FILENO, &G.termios) < 0)
666 bb_perror_msg_and_die("tcgetattr"); 514 bb_perror_msg_and_die("tcgetattr");
667 515
668 pid = getpid(); 516 pid = getpid();
@@ -676,25 +524,25 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
676#endif 524#endif
677 525
678 /* Update the utmp file. This tty is ours now! */ 526 /* Update the utmp file. This tty is ours now! */
679 update_utmp(pid, LOGIN_PROCESS, options.tty, "LOGIN", fakehost); 527 update_utmp(pid, LOGIN_PROCESS, G.tty, "LOGIN", fakehost);
680 528
681 /* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */ 529 /* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */
682 debug("calling termios_init\n"); 530 debug("calling termios_init\n");
683 termios_init(&termios, options.speeds[0]); 531 termios_init(G.speeds[0]);
684 532
685 /* Write the modem init string and DON'T flush the buffers */ 533 /* Write the modem init string and DON'T flush the buffers */
686 if (option_mask32 & F_INITSTRING) { 534 if (option_mask32 & F_INITSTRING) {
687 debug("writing init string\n"); 535 debug("writing init string\n");
688 full_write1_str(options.initstring); 536 full_write1_str(G.initstring);
689 } 537 }
690 538
691 /* Optionally detect the baud rate from the modem status message */ 539 /* Optionally detect the baud rate from the modem status message */
692 debug("before autobaud\n"); 540 debug("before autobaud\n");
693 if (option_mask32 & F_PARSE) 541 if (option_mask32 & F_PARSE)
694 auto_baud(line_buf, sizeof(line_buf), &termios); 542 auto_baud();
695 543
696 /* Set the optional timer */ 544 /* Set the optional timer */
697 alarm(options.timeout); /* if 0, alarm is not set */ 545 alarm(G.timeout); /* if 0, alarm is not set */
698 546
699 /* Optionally wait for CR or LF before writing /etc/issue */ 547 /* Optionally wait for CR or LF before writing /etc/issue */
700 if (option_mask32 & F_WAITCRLF) { 548 if (option_mask32 & F_WAITCRLF) {
@@ -703,7 +551,6 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
703 debug("waiting for cr-lf\n"); 551 debug("waiting for cr-lf\n");
704 while (safe_read(STDIN_FILENO, &ch, 1) == 1) { 552 while (safe_read(STDIN_FILENO, &ch, 1) == 1) {
705 debug("read %x\n", (unsigned char)ch); 553 debug("read %x\n", (unsigned char)ch);
706 ch &= 0x7f; /* strip "parity bit" */
707 if (ch == '\n' || ch == '\r') 554 if (ch == '\n' || ch == '\r')
708 break; 555 break;
709 } 556 }
@@ -712,20 +559,19 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
712 logname = NULL; 559 logname = NULL;
713 if (!(option_mask32 & F_NOPROMPT)) { 560 if (!(option_mask32 & F_NOPROMPT)) {
714 /* NB: termios_init already set line speed 561 /* NB: termios_init already set line speed
715 * to options.speeds[0] */ 562 * to G.speeds[0] */
716 int baud_index = 0; 563 int baud_index = 0;
717 564
718 while (1) { 565 while (1) {
719 /* Read the login name. */ 566 /* Read the login name. */
720 debug("reading login name\n"); 567 debug("reading login name\n");
721 logname = get_logname(line_buf, sizeof(line_buf), 568 logname = get_logname();
722 &options, &chardata);
723 if (logname) 569 if (logname)
724 break; 570 break;
725 /* we are here only if options.numspeed > 1 */ 571 /* We are here only if G.numspeed > 1. */
726 baud_index = (baud_index + 1) % options.numspeed; 572 baud_index = (baud_index + 1) % G.numspeed;
727 cfsetspeed(&termios, options.speeds[baud_index]); 573 cfsetspeed(&G.termios, G.speeds[baud_index]);
728 tcsetattr_stdin_TCSANOW(&termios); 574 tcsetattr_stdin_TCSANOW(&G.termios);
729 } 575 }
730 } 576 }
731 577
@@ -733,7 +579,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
733 alarm(0); 579 alarm(0);
734 580
735 /* Finalize the termios settings. */ 581 /* Finalize the termios settings. */
736 termios_final(&termios, &chardata); 582 termios_final();
737 583
738 /* Now the newline character should be properly written. */ 584 /* Now the newline character should be properly written. */
739 full_write(STDOUT_FILENO, "\n", 1); 585 full_write(STDOUT_FILENO, "\n", 1);
@@ -742,6 +588,6 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
742 /* We use PATH because we trust that root doesn't set "bad" PATH, 588 /* We use PATH because we trust that root doesn't set "bad" PATH,
743 * and getty is not suid-root applet. */ 589 * and getty is not suid-root applet. */
744 /* With -n, logname == NULL, and login will ask for username instead */ 590 /* With -n, logname == NULL, and login will ask for username instead */
745 BB_EXECLP(options.login, options.login, "--", logname, NULL); 591 BB_EXECLP(G.login, G.login, "--", logname, NULL);
746 bb_error_msg_and_die("can't execute '%s'", options.login); 592 bb_error_msg_and_die("can't execute '%s'", G.login);
747} 593}