Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/loginutils/getty.c
- Timestamp:
- Nov 4, 2007, 3:16:40 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.5/mindi-busybox/loginutils/getty.c
r902 r1765 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* agetty.c - another getty program for Linux. By W. Z. Venema 1989 3 Ported to Linux by Peter Orbaek <poe@daimi.aau.dk> 4 This program is freely distributable. The entire man-page used to 5 be here. Now read the real man-page agetty.8 instead. 6 7 -f option added by Eric Rasmussen <ear@usfirst.org> - 12/28/95 8 9 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> 10 - added Native Language Support 11 12 1999-05-05 Thorsten Kranzkowski <dl8bcu@gmx.net> 13 - enable hardware flow control before displaying /etc/issue 14 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <unistd.h> 20 #include <string.h> 21 #include <sys/ioctl.h> 22 #include <errno.h> 23 #include <sys/stat.h> 24 #include <signal.h> 25 #include <fcntl.h> 26 #include <stdarg.h> 27 #include <ctype.h> 28 #include <getopt.h> 29 #include <termios.h> 30 #include "busybox.h" 31 32 #ifdef CONFIG_FEATURE_UTMP 3 * Ported to Linux by Peter Orbaek <poe@daimi.aau.dk> 4 * This program is freely distributable. The entire man-page used to 5 * be here. Now read the real man-page agetty.8 instead. 6 * 7 * option added by Eric Rasmussen <ear@usfirst.org> - 12/28/95 8 * 9 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> 10 * - added Native Language Support 11 12 * 1999-05-05 Thorsten Kranzkowski <dl8bcu@gmx.net> 13 * - enable hardware flow control before displaying /etc/issue 14 * 15 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 16 * 17 */ 18 19 #include "libbb.h" 20 #include <syslog.h> 21 22 #if ENABLE_FEATURE_UTMP 33 23 #include <utmp.h> 34 24 #endif 35 25 36 #define _PATH_LOGIN "/bin/login" 37 38 /* If USE_SYSLOG is undefined all diagnostics go directly to /dev/console. */ 39 #ifdef CONFIG_SYSLOGD 40 #include <sys/param.h> 41 #include <syslog.h> 42 #endif 43 44 45 /* 46 * Some heuristics to find out what environment we are in: if it is not 47 * System V, assume it is SunOS 4. 48 */ 49 26 /* 27 * Some heuristics to find out what environment we are in: if it is not 28 * System V, assume it is SunOS 4. 29 */ 50 30 #ifdef LOGIN_PROCESS /* defined in System V utmp.h */ 51 31 #define SYSV_STYLE /* select System V style getty */ 52 #ifdef CONFIG_FEATURE_WTMP53 extern void updwtmp(const char *filename, const struct utmp *ut);54 #endif55 #endif /* LOGIN_PROCESS */56 57 /*58 * Things you may want to modify.59 *60 * You may disagree with the default line-editing etc. characters defined61 * below. Note, however, that DEL cannot be used for interrupt generation62 * and for line editing at the same time.63 */64 65 #ifdef SYSV_STYLE66 32 #include <sys/utsname.h> 67 33 #include <time.h> 68 #endif 69 70 /* If ISSUE is not defined, agetty will never display the contents of the 71 * /etc/issue file. You will not want to spit out large "issue" files at the 72 * wrong baud rate. 73 */ 34 #if ENABLE_FEATURE_WTMP 35 extern void updwtmp(const char *filename, const struct utmp *ut); 36 static void update_utmp(const char *line); 37 #endif 38 #endif /* LOGIN_PROCESS */ 39 40 /* 41 * Things you may want to modify. 42 * 43 * You may disagree with the default line-editing etc. characters defined 44 * below. Note, however, that DEL cannot be used for interrupt generation 45 * and for line editing at the same time. 46 */ 47 48 /* I doubt there are systems which still need this */ 49 #undef HANDLE_ALLCAPS 50 51 #define _PATH_LOGIN "/bin/login" 52 53 /* If ISSUE is not defined, getty will never display the contents of the 54 * /etc/issue file. You will not want to spit out large "issue" files at the 55 * wrong baud rate. 56 */ 74 57 #define ISSUE "/etc/issue" /* displayed before the login prompt */ 75 58 76 59 /* Some shorthands for control characters. */ 77 78 60 #define CTL(x) (x ^ 0100) /* Assumes ASCII dialect */ 79 61 #define CR CTL('M') /* carriage return */ … … 83 65 84 66 /* Defaults for line-editing etc. characters; you may want to change this. */ 85 86 67 #define DEF_ERASE DEL /* default erase character */ 87 68 #define DEF_INTR CTL('C') /* default interrupt character */ … … 92 73 #define DEF_SWITCH 0 /* default switch char */ 93 74 94 /* 95 * SunOS 4.1.1 termio is broken. We must use the termios stuff instead, 96 * because the termio -> termios translation does not clear the termios 97 * CIBAUD bits. Therefore, the tty driver would sometimes report that input 98 * baud rate != output baud rate. I did not notice that problem with SunOS 99 * 4.1. We will use termios where available, and termio otherwise. 100 */ 101 102 /* linux 0.12 termio is broken too, if we use it c_cc[VERASE] isn't set 103 properly, but all is well if we use termios?! */ 104 105 #ifdef TCGETS 106 #undef TCGETA 107 #undef TCSETA 108 #undef TCSETAW 109 #define termio termios 110 #define TCGETA TCGETS 111 #define TCSETA TCSETS 112 #define TCSETAW TCSETSW 113 #endif 114 115 /* 116 * When multiple baud rates are specified on the command line, the first one 117 * we will try is the first one specified. 118 */ 119 75 /* 76 * When multiple baud rates are specified on the command line, the first one 77 * we will try is the first one specified. 78 */ 120 79 #define FIRST_SPEED 0 121 80 … … 126 85 struct options { 127 86 int flags; /* toggle switches, see below */ 128 int timeout;/* time-out period */129 c har *login; /* login program */130 c har *tty; /* name of tty */131 c har *initstring; /* modem init string */132 c har *issue; /* alternative issue file */87 unsigned timeout; /* time-out period */ 88 const char *login; /* login program */ 89 const char *tty; /* name of tty */ 90 const char *initstring; /* modem init string */ 91 const char *issue; /* alternative issue file */ 133 92 int numspeed; /* number of baud rates to try */ 134 93 int speeds[MAX_SPEED]; /* baud rates to be tried */ 135 94 }; 136 95 137 static const char opt_string[] = "I:LH:f:hil:mt:wn";96 static const char opt_string[] ALIGN1 = "I:LH:f:hil:mt:wn"; 138 97 #define F_INITSTRING (1<<0) /* initstring is set */ 139 98 #define F_LOCAL (1<<1) /* force local */ … … 149 108 150 109 /* Storage for things detected while the login name was read. */ 151 152 110 struct chardata { 153 int erase; /* erase character */ 154 int kill; /* kill character */ 155 int eol; /* end-of-line character */ 156 int parity; /* what parity did we see */ 157 int capslock; /* upper case without lower case */ 111 unsigned char erase; /* erase character */ 112 unsigned char kill; /* kill character */ 113 unsigned char eol; /* end-of-line character */ 114 unsigned char parity; /* what parity did we see */ 115 #ifdef HANDLE_ALLCAPS 116 unsigned char capslock; /* upper case without lower case */ 117 #endif 158 118 }; 159 119 160 120 /* Initial values for the above. */ 161 162 static struct chardata init_chardata = { 121 static const struct chardata init_chardata = { 163 122 DEF_ERASE, /* default erase character */ 164 123 DEF_KILL, /* default kill character */ 165 124 13, /* default eol char */ 166 125 0, /* space parity */ 126 #ifdef HANDLE_ALLCAPS 167 127 0, /* no capslock */ 128 #endif 168 129 }; 169 170 #if 0171 struct Speedtab {172 long speed;173 int code;174 };175 176 static struct Speedtab speedtab[] = {177 {50, B50},178 {75, B75},179 {110, B110},180 {134, B134},181 {150, B150},182 {200, B200},183 {300, B300},184 {600, B600},185 {1200, B1200},186 {1800, B1800},187 {2400, B2400},188 {4800, B4800},189 {9600, B9600},190 #ifdef B19200191 {19200, B19200},192 #endif193 #ifdef B38400194 {38400, B38400},195 #endif196 #ifdef EXTA197 {19200, EXTA},198 #endif199 #ifdef EXTB200 {38400, EXTB},201 #endif202 #ifdef B57600203 {57600, B57600},204 #endif205 #ifdef B115200206 {115200, B115200},207 #endif208 #ifdef B230400209 {230400, B230400},210 #endif211 {0, 0},212 };213 #endif214 215 216 #ifdef SYSV_STYLE217 #ifdef CONFIG_FEATURE_UTMP218 static void update_utmp(char *line);219 #endif220 #endif221 130 222 131 /* The following is used for understandable diagnostics. */ … … 229 138 #define debug(s) fprintf(dbf,s); fflush(dbf) 230 139 #define DEBUGTERM "/dev/ttyp0" 231 FILE *dbf;140 static FILE *dbf; 232 141 #else 233 #define debug(s) /* nothing */ 234 #endif 235 236 237 /* 238 * output error messages 239 */ 240 static void error(const char *fmt, ...) ATTRIBUTE_NORETURN; 241 static void error(const char *fmt, ...) 242 { 243 va_list va_alist; 244 char buf[256]; 245 246 #ifdef CONFIG_SYSLOGD 247 va_start(va_alist, fmt); 248 vsnprintf(buf, sizeof(buf), fmt, va_alist); 249 openlog(bb_applet_name, 0, LOG_AUTH); 250 syslog(LOG_ERR, "%s", buf); 251 closelog(); 252 #else 253 int fd; 254 size_t l; 255 256 snprintf(buf, sizeof(buf), "%s: ", bb_applet_name); 257 l = strlen(buf); 258 va_start(va_alist, fmt); 259 vsnprintf(buf + l, sizeof(buf) - l, fmt, va_alist); 260 l = strlen(buf); 261 /* truncate if need */ 262 if((l + 3) > sizeof(buf)) 263 l = sizeof(buf) - 3; 264 /* add \r\n always */ 265 buf[l++] = '\r'; 266 buf[l++] = '\n'; 267 buf[l] = 0; 268 if ((fd = open("/dev/console", 1)) >= 0) { 269 write(fd, buf, l); 270 close(fd); 271 } 272 #endif 273 274 va_end(va_alist); 275 276 (void) sleep((unsigned) 10); /* be kind to init(8) */ 277 exit(1); 278 } 279 142 #define debug(s) /* nothing */ 143 #endif 280 144 281 145 … … 284 148 { 285 149 int r; 286 unsigned long value;287 if ( safe_strtoul((char *)s, &value)) {150 unsigned value = bb_strtou(s, NULL, 10); 151 if (errno) { 288 152 return -1; 289 153 } 290 if ((r = tty_value_to_baud(value)) > 0) { 154 r = tty_value_to_baud(value); 155 if (r > 0) { 291 156 return r; 292 157 } … … 303 168 for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) { 304 169 if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0) 305 error("bad speed: %s", cp);170 bb_error_msg_and_die("bad speed: %s", cp); 306 171 if (op->numspeed > MAX_SPEED) 307 error("too many alternate speeds");172 bb_error_msg_and_die("too many alternate speeds"); 308 173 } 309 174 debug("exiting parsespeeds\n"); … … 311 176 312 177 313 /* parse -args - parse command-line arguments */178 /* parse_args - parse command-line arguments */ 314 179 static void parse_args(int argc, char **argv, struct options *op) 315 180 { 316 181 char *ts; 317 182 318 op->flags = bb_getopt_ulflags(argc,argv, opt_string,183 op->flags = getopt32(argv, opt_string, 319 184 &(op->initstring), &fakehost, &(op->issue), 320 185 &(op->login), &ts); 321 if (op->flags & F_INITSTRING) {186 if (op->flags & F_INITSTRING) { 322 187 const char *p = op->initstring; 323 188 char *q; 324 189 325 q = op->initstring = bb_xstrdup(op->initstring);190 op->initstring = q = xstrdup(op->initstring); 326 191 /* copy optarg into op->initstring decoding \ddd 327 192 octal codes into chars */ … … 337 202 } 338 203 op->flags ^= F_ISSUE; /* revert flag show /etc/issue */ 339 if(op->flags & F_TIMEOUT) { 340 if ((op->timeout = atoi(ts)) <= 0) 341 error("bad timeout value: %s", ts); 342 } 204 if (op->flags & F_TIMEOUT) { 205 op->timeout = xatoul_range(ts, 1, INT_MAX); 206 } 207 argv += optind; 208 argc -= optind; 343 209 debug("after getopt loop\n"); 344 if (argc < optind +2) /* check parameter count */210 if (argc < 2) /* check parameter count */ 345 211 bb_show_usage(); 346 212 347 213 /* we loosen up a bit and accept both "baudrate tty" and "tty baudrate" */ 348 if ( '0' <= argv[optind][0] && argv[optind][0] <= '9') {214 if (isdigit(argv[0][0])) { 349 215 /* a number first, assume it's a speed (BSD style) */ 350 parse_speeds(op, argv[ optind++]); /* baud rate(s) */351 op->tty = argv[ optind]; /* tty name */216 parse_speeds(op, argv[0]); /* baud rate(s) */ 217 op->tty = argv[1]; /* tty name */ 352 218 } else { 353 op->tty = argv[optind++]; /* tty name */ 354 parse_speeds(op, argv[optind]); /* baud rate(s) */ 355 } 356 357 optind++; 358 if (argc > optind && argv[optind]) 359 setenv("TERM", argv[optind], 1); 219 op->tty = argv[0]; /* tty name */ 220 parse_speeds(op, argv[1]); /* baud rate(s) */ 221 } 222 223 if (argv[2]) 224 setenv("TERM", argv[2], 1); 360 225 361 226 debug("exiting parseargs\n"); … … 363 228 364 229 /* open_tty - set up tty as standard { input, output, error } */ 365 static void open_tty(c har *tty, struct termio*tp, int local)230 static void open_tty(const char *tty, struct termios *tp, int local) 366 231 { 367 232 int chdir_to_root = 0; 368 233 369 234 /* Set up new standard input, unless we are given an already opened port. */ 370 371 if (strcmp(tty, "-")) { 235 if (NOT_LONE_DASH(tty)) { 372 236 struct stat st; 373 237 int fd; 374 238 375 239 /* Sanity checks... */ 376 377 if (chdir("/dev")) 378 error("/dev: chdir() failed: %m"); 240 xchdir("/dev"); 379 241 chdir_to_root = 1; 380 if (stat(tty, &st) < 0) 381 error("/dev/%s: %m", tty); 242 xstat(tty, &st); 382 243 if ((st.st_mode & S_IFMT) != S_IFCHR) 383 error("/dev/%s: not a character device", tty);244 bb_error_msg_and_die("%s: not a character device", tty); 384 245 385 246 /* Open the tty as standard input. */ 386 387 close(0);388 247 debug("open(2)\n"); 389 fd = open(tty, O_RDWR | O_NONBLOCK, 0); 390 if (fd != 0) 391 error("/dev/%s: cannot open as standard input: %m", tty); 248 fd = xopen(tty, O_RDWR | O_NONBLOCK); 249 xdup2(fd, 0); 250 while (fd > 2) 251 close(fd--); 392 252 } else { 393 394 253 /* 395 254 * Standard input should already be connected to an open port. Make 396 255 * sure it is open for read/write. 397 256 */ 398 399 if ((fcntl(0, F_GETFL, 0) & O_RDWR) != O_RDWR) 400 error("%s: not open for read/write", tty); 257 if ((fcntl(0, F_GETFL) & O_RDWR) != O_RDWR) 258 bb_error_msg_and_die("stdin is not open for read/write"); 401 259 } 402 260 403 261 /* Replace current standard output/error fd's with new ones */ 404 262 debug("duping\n"); 405 if (dup2(STDIN_FILENO, STDOUT_FILENO) == -1 || 406 dup2(STDIN_FILENO, STDERR_FILENO) == -1) 407 error("%s: dup problem: %m", tty); /* we have a problem */ 263 xdup2(0, 1); 264 xdup2(0, 2); 408 265 409 266 /* … … 415 272 * 5 seconds seems to be a good value. 416 273 */ 417 418 if (ioctl(0, TCGETA, tp) < 0) 419 error("%s: ioctl: %m", tty); 274 ioctl_or_perror_and_die(0, TCGETS, tp, "%s: TCGETS", tty); 420 275 421 276 /* … … 427 282 428 283 #ifdef DEBIAN 284 #warning Debian /dev/vcs[a]NN hack is deprecated and will be removed 429 285 { 430 286 /* tty to root.dialout 660 */ … … 432 288 int id; 433 289 434 id = (gr = getgrnam("dialout")) ? gr->gr_gid : 0; 290 gr = getgrnam("dialout"); 291 id = gr ? gr->gr_gid : 0; 435 292 chown(tty, 0, id); 436 293 chmod(tty, 0660); … … 440 297 char *vcs, *vcsa; 441 298 442 if (!(vcs = strdup(tty))) 443 error("Can't malloc for vcs"); 444 if (!(vcsa = malloc(strlen(tty) + 2))) 445 error("Can't malloc for vcsa"); 299 vcs = xstrdup(tty); 300 vcsa = xmalloc(strlen(tty) + 2); 446 301 strcpy(vcs, "vcs"); 447 302 strcpy(vcs + 3, tty + 3); … … 449 304 strcpy(vcsa + 4, tty + 3); 450 305 451 id = (gr = getgrnam("sys")) ? gr->gr_gid : 0; 306 gr = getgrnam("sys"); 307 id = gr ? gr->gr_gid : 0; 452 308 chown(vcs, 0, id); 453 309 chmod(vcs, 0600); … … 460 316 } 461 317 #else 462 (void) chown(tty, 0, 0); /* root, sys */ 463 (void) chmod(tty, 0622); /* crw--w--w- */ 464 #endif 465 if(chdir_to_root && chdir("/")) 466 error("chdir to / failed: %m"); 467 } 468 469 /* termio_init - initialize termio settings */ 470 static void termio_init(struct termio *tp, int speed, struct options *op) 318 if (NOT_LONE_DASH(tty)) { 319 chown(tty, 0, 0); /* 0:0 */ 320 chmod(tty, 0622); /* crw--w--w- */ 321 } 322 #endif 323 if (chdir_to_root) 324 xchdir("/"); 325 } 326 327 /* termios_init - initialize termios settings */ 328 static void termios_init(struct termios *tp, int speed, struct options *op) 471 329 { 472 330 /* 473 * Initial termio settings: 8-bit characters, raw-mode, blocking i/o.331 * Initial termios settings: 8-bit characters, raw-mode, blocking i/o. 474 332 * Special characters are set after we have read the login name; all 475 333 * reads will be done in raw mode anyway. Errors will be dealt with 476 * later on.334 * later on. 477 335 */ 478 336 #ifdef __linux__ 479 337 /* flush input and output queues, important for modems! */ 480 (void)ioctl(0, TCFLSH, TCIOFLUSH);338 ioctl(0, TCFLSH, TCIOFLUSH); 481 339 #endif 482 340 … … 498 356 #endif 499 357 500 (void) ioctl(0, TCSETA, tp);358 ioctl(0, TCSETS, tp); 501 359 502 360 /* go to blocking input even in local mode */ 503 fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NONBLOCK);361 ndelay_off(0); 504 362 505 363 debug("term_io 2\n"); … … 507 365 508 366 /* auto_baud - extract baud rate from modem status message */ 509 static void auto_baud( struct termio*tp)367 static void auto_baud(char *buf, unsigned size_buf, struct termios *tp) 510 368 { 511 369 int speed; 512 370 int vmin; 513 371 unsigned iflag; 514 char buf[BUFSIZ];515 372 char *bp; 516 373 int nread; … … 533 390 /* 534 391 * Use 7-bit characters, don't block if input queue is empty. Errors will 535 * be dealt with later on.392 * be dealt with later on. 536 393 */ 537 394 … … 540 397 vmin = tp->c_cc[VMIN]; 541 398 tp->c_cc[VMIN] = 0; /* don't block if queue empty */ 542 (void) ioctl(0, TCSETA, tp);399 ioctl(0, TCSETS, tp); 543 400 544 401 /* … … 547 404 */ 548 405 549 (void) sleep(1); 550 if ((nread = read(0, buf, sizeof(buf) - 1)) > 0) { 406 sleep(1); 407 nread = read(0, buf, size_buf - 1); 408 if (nread > 0) { 551 409 buf[nread] = '\0'; 552 410 for (bp = buf; bp < buf + nread; bp++) { 553 411 if (isascii(*bp) && isdigit(*bp)) { 554 if ((speed = bcode(bp))) { 412 speed = bcode(bp); 413 if (speed) { 555 414 tp->c_cflag &= ~CBAUD; 556 415 tp->c_cflag |= speed; … … 560 419 } 561 420 } 562 /* Restore terminal settings. Errors will be dealt with later on. */421 /* Restore terminal settings. Errors will be dealt with later on. */ 563 422 564 423 tp->c_iflag = iflag; 565 424 tp->c_cc[VMIN] = vmin; 566 (void) ioctl(0, TCSETA, tp);425 ioctl(0, TCSETS, tp); 567 426 } 568 427 569 428 /* next_speed - select next baud rate */ 570 static void next_speed(struct termio *tp, struct options *op)429 static void next_speed(struct termios *tp, struct options *op) 571 430 { 572 431 static int baud_index = FIRST_SPEED; /* current speed index */ … … 575 434 tp->c_cflag &= ~CBAUD; 576 435 tp->c_cflag |= op->speeds[baud_index]; 577 (void) ioctl(0, TCSETA, tp);436 ioctl(0, TCSETS, tp); 578 437 } 579 438 580 439 581 440 /* do_prompt - show login prompt, optionally preceded by /etc/issue contents */ 582 static void do_prompt(struct options *op, struct termio *tp)583 { 584 #ifdef ISSUE /* optional: show /etc/issue */441 static void do_prompt(struct options *op, struct termios *tp) 442 { 443 #ifdef ISSUE 585 444 print_login_issue(op->issue, op->tty); 586 445 #endif … … 588 447 } 589 448 449 #ifdef HANDLE_ALLCAPS 590 450 /* caps_lock - string contains upper case without lower case */ 591 451 /* returns 1 if true, 0 if false */ 592 452 static int caps_lock(const char *s) 593 453 { 594 int capslock; 595 596 for (capslock = 0; *s; s++) { 597 if (islower(*s)) 598 return (0); 599 if (capslock == 0) 600 capslock = isupper(*s); 601 } 602 return (capslock); 603 } 604 605 #define logname bb_common_bufsiz1 454 while (*s) 455 if (islower(*s++)) 456 return 0; 457 return 1; 458 } 459 #endif 460 606 461 /* get_logname - get user name, establish parity, speed, erase, kill, eol */ 607 462 /* return NULL on failure, logname on success */ 608 static char *get_logname(struct options *op, struct chardata *cp, struct termio *tp) 463 static char *get_logname(char *logname, unsigned size_logname, 464 struct options *op, struct chardata *cp, struct termios *tp) 609 465 { 610 466 char *bp; … … 613 469 int bits; /* # of "1" bits per character */ 614 470 int mask; /* mask with 1 bit up */ 615 static c har *erase[] = {/* backspace-space-backspace */471 static const char erase[][3] = { /* backspace-space-backspace */ 616 472 "\010\040\010", /* space parity */ 617 473 "\010\040\010", /* odd parity */ … … 626 482 /* Flush pending input (esp. after parsing or switching the baud rate). */ 627 483 628 (void)sleep(1);629 (void)ioctl(0, TCFLSH, TCIFLUSH);484 sleep(1); 485 ioctl(0, TCFLSH, TCIFLUSH); 630 486 631 487 /* Prompt for and read a login name. */ 632 488 633 for (*logname = 0; *logname == 0; /* void */ ) { 489 logname[0] = '\0'; 490 while (!logname[0]) { 634 491 635 492 /* Write issue file and prompt, with "parity" bit == 0. */ … … 639 496 /* Read name, watch for break, parity, erase, kill, end-of-line. */ 640 497 641 for (bp = logname, cp->eol = 0; cp->eol == 0; /* void */ ) { 498 bp = logname; 499 cp->eol = '\0'; 500 while (cp->eol == '\0') { 642 501 643 502 /* Do not report trivial EINTR/EIO errors. */ 644 645 503 if (read(0, &c, 1) < 1) { 646 504 if (errno == EINTR || errno == EIO) 647 505 exit(0); 648 error("%s: read: %m", op->tty);506 bb_perror_msg_and_die("%s: read", op->tty); 649 507 } 508 650 509 /* Do BREAK handling elsewhere. */ 651 652 if ((c == 0) && op->numspeed > 1) 653 /* return (0); */ 510 if (c == '\0' && op->numspeed > 1) 654 511 return NULL; 655 512 656 513 /* Do parity bit handling. */ 657 658 if (c != (ascval = (c & 0177))) { /* "parity" bit on ? */ 659 for (bits = 1, mask = 1; mask & 0177; mask <<= 1) 514 ascval = c & 0177; 515 if (c != ascval) { /* "parity" bit on ? */ 516 bits = 1; 517 mask = 1; 518 while (mask & 0177) { 660 519 if (mask & ascval) 661 520 bits++; /* count "1" bits */ 662 cp->parity |= ((bits & 1) ? 1 : 2); 521 mask <<= 1; 522 } 523 /* ... |= 2 - even, 1 - odd */ 524 cp->parity |= 2 - (bits & 1); 663 525 } 526 664 527 /* Do erase, kill and end-of-line processing. */ 665 666 528 switch (ascval) { 667 529 case CR: 668 530 case NL: 669 *bp = 0;/* terminate logname */531 *bp = '\0'; /* terminate logname */ 670 532 cp->eol = ascval; /* set end-of-line char */ 671 533 break; … … 675 537 cp->erase = ascval; /* set erase character */ 676 538 if (bp > logname) { 677 (void)write(1, erase[cp->parity], 3);539 write(1, erase[cp->parity], 3); 678 540 bp--; 679 541 } … … 683 545 cp->kill = ascval; /* set kill character */ 684 546 while (bp > logname) { 685 (void)write(1, erase[cp->parity], 3);547 write(1, erase[cp->parity], 3); 686 548 bp--; 687 549 } … … 691 553 default: 692 554 if (!isascii(ascval) || !isprint(ascval)) { 693 /* ignore garbage characters */ ;694 } else if (bp - logname >= size of(logname)- 1) {695 error("%s: input overrun", op->tty);555 /* ignore garbage characters */ 556 } else if (bp - logname >= size_logname - 1) { 557 bb_error_msg_and_die("%s: input overrun", op->tty); 696 558 } else { 697 (void)write(1, &c, 1); /* echo the character */559 write(1, &c, 1); /* echo the character */ 698 560 *bp++ = ascval; /* and store it */ 699 561 } … … 704 566 /* Handle names with upper case and no lower case. */ 705 567 706 if ((cp->capslock = caps_lock(logname))) { 568 #ifdef HANDLE_ALLCAPS 569 cp->capslock = caps_lock(logname); 570 if (cp->capslock) { 707 571 for (bp = logname; *bp; bp++) 708 572 if (isupper(*bp)) 709 573 *bp = tolower(*bp); /* map name to lower case */ 710 574 } 711 return (logname); 712 } 713 714 /* termio_final - set the final tty mode bits */ 715 static void termio_final(struct options *op, struct termio *tp, struct chardata *cp) 575 #endif 576 return logname; 577 } 578 579 /* termios_final - set the final tty mode bits */ 580 static void termios_final(struct options *op, struct termios *tp, struct chardata *cp) 716 581 { 717 582 /* General terminal-independent stuff. */ … … 754 619 break; 755 620 } 621 756 622 /* Account for upper case without lower case. */ 757 623 #ifdef HANDLE_ALLCAPS 758 624 if (cp->capslock) { 759 625 tp->c_iflag |= IUCLC; … … 761 627 tp->c_oflag |= OLCUC; 762 628 } 629 #endif 763 630 /* Optionally enable hardware flow control */ 764 631 … … 770 637 /* Finally, make the new settings effective */ 771 638 772 if (ioctl(0, TCSETA, tp) < 0) 773 error("%s: ioctl: TCSETA: %m", op->tty); 774 } 775 776 777 #ifdef SYSV_STYLE 778 #ifdef CONFIG_FEATURE_UTMP 639 ioctl_or_perror_and_die(0, TCSETS, tp, "%s: TCSETS", op->tty); 640 } 641 642 643 #ifdef SYSV_STYLE 644 #if ENABLE_FEATURE_UTMP 779 645 /* update_utmp - update our utmp entry */ 780 static void update_utmp(c har *line)646 static void update_utmp(const char *line) 781 647 { 782 648 struct utmp ut; … … 784 650 time_t t; 785 651 int mypid = getpid(); 786 #if ! (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1))787 struct flock lock;788 #endif789 652 790 653 /* … … 802 665 setutent(); 803 666 while ((utp = getutent()) 804 && !(utp->ut_type == INIT_PROCESS && utp->ut_pid == mypid)) /* nothing */805 ;667 && !(utp->ut_type == INIT_PROCESS && utp->ut_pid == mypid)) 668 /* nothing */; 806 669 807 670 if (utp) { … … 812 675 safe_strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id)); 813 676 } 814 /* endutent(); */677 /* endutent(); */ 815 678 816 679 strcpy(ut.ut_user, "LOGIN"); … … 826 689 endutent(); 827 690 828 #if def CONFIG_FEATURE_WTMP691 #if ENABLE_FEATURE_WTMP 829 692 if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) 830 693 close(creat(bb_path_wtmp_file, 0664)); … … 837 700 838 701 839 #undef logname 702 int getty_main(int argc, char **argv); 840 703 int getty_main(int argc, char **argv) 841 704 { 705 int nullfd; 842 706 char *logname = NULL; /* login name, given to /bin/login */ 707 /* Merging these into "struct local" may _seem_ to reduce 708 * parameter passing, but today's gcc will inline 709 * statics which are called once anyway, so don't do that */ 843 710 struct chardata chardata; /* set by get_logname() */ 844 struct termio termio; /* terminal mode bits */845 st atic struct options options = {711 struct termios termios; /* terminal mode bits */ 712 struct options options = { 846 713 0, /* show /etc/issue (SYSV_STYLE) */ 847 714 0, /* no timeout */ … … 857 724 }; 858 725 726 /* Already too late because of theoretical 727 * possibility of getty --help somehow triggered 728 * inadvertently before we reach this. Oh well. */ 729 logmode = LOGMODE_NONE; 730 setsid(); 731 nullfd = xopen(bb_dev_null, O_RDWR); 732 /* dup2(nullfd, 0); - no, because of possible "getty - 9600" */ 733 /* open_tty() will take care of fd# 0 anyway */ 734 dup2(nullfd, 1); 735 dup2(nullfd, 2); 736 while (nullfd > 2) close(nullfd--); 737 /* We want special flavor of error_msg_and_die */ 738 die_sleep = 10; 739 msg_eol = "\r\n"; 740 openlog(applet_name, LOG_PID, LOG_AUTH); 741 logmode = LOGMODE_BOTH; 742 859 743 #ifdef DEBUGGING 860 dbf = bb_xfopen(DEBUGTERM, "w");744 dbf = xfopen(DEBUGTERM, "w"); 861 745 862 746 { … … 871 755 872 756 /* Parse command-line arguments. */ 873 874 757 parse_args(argc, argv, &options); 875 758 876 #ifdef __linux__ 877 setsid(); 878 #endif 879 759 #ifdef SYSV_STYLE 760 #if ENABLE_FEATURE_UTMP 880 761 /* Update the utmp file. */ 881 882 883 #ifdef SYSV_STYLE884 #ifdef CONFIG_FEATURE_UTMP885 762 update_utmp(options.tty); 886 763 #endif … … 889 766 debug("calling open_tty\n"); 890 767 /* Open the tty as standard { input, output, error }. */ 891 open_tty(options.tty, &termio , options.flags & F_LOCAL);768 open_tty(options.tty, &termios, options.flags & F_LOCAL); 892 769 893 770 #ifdef __linux__ … … 899 776 } 900 777 #endif 901 /* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */902 debug("calling termio _init\n");903 termio _init(&termio, options.speeds[FIRST_SPEED], &options);778 /* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */ 779 debug("calling termios_init\n"); 780 termios_init(&termios, options.speeds[FIRST_SPEED], &options); 904 781 905 782 /* write the modem init string and DON'T flush the buffers */ … … 911 788 if (!(options.flags & F_LOCAL)) { 912 789 /* go to blocking write mode unless -L is specified */ 913 fcntl(1, F_SETFL, fcntl(1, F_GETFL, 0) & ~O_NONBLOCK);790 ndelay_off(1); 914 791 } 915 792 … … 917 794 debug("before autobaud\n"); 918 795 if (options.flags & F_PARSE) 919 auto_baud( &termio);796 auto_baud(bb_common_bufsiz1, sizeof(bb_common_bufsiz1), &termios); 920 797 921 798 /* Set the optional timer. */ 922 799 if (options.timeout) 923 (void) alarm((unsigned)options.timeout);800 alarm(options.timeout); 924 801 925 802 /* optionally wait for CR or LF before writing /etc/issue */ … … 942 819 /* Read the login name. */ 943 820 debug("reading login name\n"); 944 /* while ((logname = get_logname(&options, &chardata, &termio)) == 0) */ 945 while ((logname = get_logname(&options, &chardata, &termio)) == 946 NULL) next_speed(&termio, &options); 821 logname = get_logname(bb_common_bufsiz1, sizeof(bb_common_bufsiz1), 822 &options, &chardata, &termios); 823 while (logname == NULL) 824 next_speed(&termios, &options); 947 825 } 948 826 … … 950 828 951 829 if (options.timeout) 952 (void)alarm(0);953 954 /* Finalize the termio settings. */955 956 termio _final(&options, &termio, &chardata);830 alarm(0); 831 832 /* Finalize the termios settings. */ 833 834 termios_final(&options, &termios, &chardata); 957 835 958 836 /* Now the newline character should be properly written. */ 959 837 960 (void)write(1, "\n", 1);838 write(1, "\n", 1); 961 839 962 840 /* Let the login program take care of password validation. */ 963 841 964 (void) execl(options.login, options.login, "--", logname, (char *) 0); 965 error("%s: can't exec %s: %m", options.tty, options.login); 966 } 967 842 execl(options.login, options.login, "--", logname, (char *) 0); 843 bb_error_msg_and_die("%s: can't exec %s", options.tty, options.login); 844 }
Note:
See TracChangeset
for help on using the changeset viewer.