summaryrefslogtreecommitdiff
path: root/loginutils
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-03-17 08:55:44 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-03-17 08:55:44 +0000
commit397de617f38a58ca4659ee348faf1df574b3ec8d (patch)
tree8d629ddebd9ce35cff7fb97b1e8e436142dade41 /loginutils
parenta4522c5a66fab931328e2423f41716fba3a6fbfd (diff)
downloadbusybox-w32-397de617f38a58ca4659ee348faf1df574b3ec8d.tar.gz
busybox-w32-397de617f38a58ca4659ee348faf1df574b3ec8d.tar.bz2
busybox-w32-397de617f38a58ca4659ee348faf1df574b3ec8d.zip
help text: regularize format, and shrink
getty: shrink, and improve comments mount: OPT_ALL is superfluous, we already have OPT_a function old new delta bcode 47 25 -22 getty_main 2503 2349 -154 packed_usage 23928 23698 -230 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-406) Total: -406 bytes text data bss dec hex filename 798031 658 7428 806117 c4ce5 busybox_old 797604 658 7428 805690 c4b3a busybox_unstripped
Diffstat (limited to 'loginutils')
-rw-r--r--loginutils/getty.c172
1 files changed, 84 insertions, 88 deletions
diff --git a/loginutils/getty.c b/loginutils/getty.c
index f033b5afd..246bb4711 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -61,7 +61,7 @@ extern void updwtmp(const char *filename, const struct utmp *ut);
61#define ISSUE "/etc/issue" /* displayed before the login prompt */ 61#define ISSUE "/etc/issue" /* displayed before the login prompt */
62 62
63/* Some shorthands for control characters. */ 63/* Some shorthands for control characters. */
64#define CTL(x) (x ^ 0100) /* Assumes ASCII dialect */ 64#define CTL(x) ((x) ^ 0100) /* Assumes ASCII dialect */
65#define CR CTL('M') /* carriage return */ 65#define CR CTL('M') /* carriage return */
66#define NL CTL('J') /* line feed */ 66#define NL CTL('J') /* line feed */
67#define BS CTL('H') /* back space */ 67#define BS CTL('H') /* back space */
@@ -100,6 +100,13 @@ struct chardata {
100 unsigned char kill; /* kill character */ 100 unsigned char kill; /* kill character */
101 unsigned char eol; /* end-of-line character */ 101 unsigned char eol; /* end-of-line character */
102 unsigned char parity; /* what parity did we see */ 102 unsigned char parity; /* what parity did we see */
103 /* (parity & 1): saw odd parity char with 7th bit set */
104 /* (parity & 2): saw even parity char with 7th bit set */
105 /* parity == 0: probably 7-bit, space parity? */
106 /* parity == 1: probably 7-bit, odd parity? */
107 /* parity == 2: probably 7-bit, even parity? */
108 /* parity == 3: definitely 8 bit, no parity! */
109 /* Hmm... with any value of "parity" 8 bit, no parity is possible */
103#ifdef HANDLE_ALLCAPS 110#ifdef HANDLE_ALLCAPS
104 unsigned char capslock; /* upper case without lower case */ 111 unsigned char capslock; /* upper case without lower case */
105#endif 112#endif
@@ -135,27 +142,21 @@ static const char opt_string[] ALIGN1 = "I:LH:f:hil:mt:wn";
135 142
136/* The following is used for understandable diagnostics. */ 143/* The following is used for understandable diagnostics. */
137#ifdef DEBUGGING 144#ifdef DEBUGGING
138#define debug(s) fprintf(dbf,s); fflush(dbf)
139#define DEBUGTERM "/dev/ttyp0"
140static FILE *dbf; 145static FILE *dbf;
146#define DEBUGTERM "/dev/ttyp0"
147#define debug(...) do { fprintf(dbf, __VA_ARGS__); fflush(dbf); } while (0)
141#else 148#else
142#define debug(s) /* nothing */ 149#define debug(...) ((void)0)
143#endif 150#endif
144 151
145 152
146/* bcode - convert speed string to speed code; return 0 on failure */ 153/* bcode - convert speed string to speed code; return <= 0 on failure */
147static int bcode(const char *s) 154static int bcode(const char *s)
148{ 155{
149 int r; 156 int value = bb_strtou(s, NULL, 10); /* yes, int is intended! */
150 unsigned value = bb_strtou(s, NULL, 10); 157 if (value < 0) /* bad terminating char, overflow, etc */
151 if (errno) { 158 return value;
152 return -1; 159 return tty_value_to_baud(value);
153 }
154 r = tty_value_to_baud(value);
155 if (r > 0) {
156 return r;
157 }
158 return 0;
159} 160}
160 161
161/* parse_speeds - parse alternate baud rates */ 162/* parse_speeds - parse alternate baud rates */
@@ -181,10 +182,10 @@ static void parse_args(char **argv, struct options *op, char **fakehost_p)
181{ 182{
182 char *ts; 183 char *ts;
183 184
184 opt_complementary = "-2"; /* at least 2 args */ 185 opt_complementary = "-2:t+"; /* at least 2 args; -t N */
185 op->flags = getopt32(argv, opt_string, 186 op->flags = getopt32(argv, opt_string,
186 &(op->initstring), fakehost_p, &(op->issue), 187 &(op->initstring), fakehost_p, &(op->issue),
187 &(op->login), &ts); 188 &(op->login), &op->timeout);
188 argv += optind; 189 argv += optind;
189 if (op->flags & F_INITSTRING) { 190 if (op->flags & F_INITSTRING) {
190 const char *p = op->initstring; 191 const char *p = op->initstring;
@@ -203,10 +204,7 @@ static void parse_args(char **argv, struct options *op, char **fakehost_p)
203 } 204 }
204 *q = '\0'; 205 *q = '\0';
205 } 206 }
206 op->flags ^= F_ISSUE; /* invert flag show /etc/issue */ 207 op->flags ^= F_ISSUE; /* invert flag "show /etc/issue" */
207 if (op->flags & F_TIMEOUT) {
208 op->timeout = xatoi_u(ts);
209 }
210 debug("after getopt\n"); 208 debug("after getopt\n");
211 209
212 /* we loosen up a bit and accept both "baudrate tty" and "tty baudrate" */ 210 /* we loosen up a bit and accept both "baudrate tty" and "tty baudrate" */
@@ -219,8 +217,11 @@ static void parse_args(char **argv, struct options *op, char **fakehost_p)
219 } 217 }
220 parse_speeds(op, ts); 218 parse_speeds(op, ts);
221 219
220// TODO: if applet_name is set to "getty: TTY", bb_error_msg's get simpler!
221// grep for "%s:"
222
222 if (argv[2]) 223 if (argv[2])
223 setenv("TERM", argv[2], 1); 224 xsetenv("TERM", argv[2]);
224 225
225 debug("exiting parse_args\n"); 226 debug("exiting parse_args\n");
226} 227}
@@ -230,37 +231,37 @@ static void open_tty(const char *tty)
230{ 231{
231 /* Set up new standard input, unless we are given an already opened port. */ 232 /* Set up new standard input, unless we are given an already opened port. */
232 if (NOT_LONE_DASH(tty)) { 233 if (NOT_LONE_DASH(tty)) {
233 struct stat st; 234// struct stat st;
234 int cur_dir_fd; 235// int cur_dir_fd;
235 int fd; 236// int fd;
236 237
237 /* Sanity checks... */ 238 /* Sanity checks... */
238 cur_dir_fd = xopen(".", O_DIRECTORY | O_NONBLOCK); 239// cur_dir_fd = xopen(".", O_DIRECTORY | O_NONBLOCK);
239 xchdir("/dev"); 240// xchdir("/dev");
240 xstat(tty, &st); 241// xstat(tty, &st);
241 if ((st.st_mode & S_IFMT) != S_IFCHR) 242// if ((st.st_mode & S_IFMT) != S_IFCHR)
242 bb_error_msg_and_die("%s: not a character device", tty); 243// bb_error_msg_and_die("%s: not a character device", tty);
244
245 if (tty[0] != '/')
246 tty = xasprintf("/dev/%s", tty); /* will leak it */
243 247
244 /* Open the tty as standard input. */ 248 /* Open the tty as standard input. */
245 debug("open(2)\n"); 249 debug("open(2)\n");
246 fd = xopen(tty, O_RDWR | O_NONBLOCK); 250 close(0);
251 /*fd =*/ xopen(tty, O_RDWR | O_NONBLOCK); /* uses fd 0 */
247 252
248 /* Restore current directory */ 253// /* Restore current directory */
249 fchdir(cur_dir_fd); 254// fchdir(cur_dir_fd);
250 255
251 /* Open the tty as standard input, continued */ 256 /* Open the tty as standard input, continued */
252 xdup2(fd, 0); 257// xmove_fd(fd, 0);
253 /* fd is >= cur_dir_fd, and cur_dir_fd gets closed too here: */ 258// /* fd is >= cur_dir_fd, and cur_dir_fd gets closed too here: */
254 while (fd > 2) 259// while (fd > 2)
255 close(fd--); 260// close(fd--);
256 261
257 /* Set proper protections and ownership. Mode 0622 262 /* Set proper protections and ownership. */
258 * is suitable for SYSV < 4 because /bin/login does not change
259 * protections. SunOS 4 login will change the protections to 0620
260 * (write access for group tty) after the login has succeeded.
261 */
262 fchown(0, 0, 0); /* 0:0 */ 263 fchown(0, 0, 0); /* 0:0 */
263 fchmod(0, 0622); /* crw--w--w- */ 264 fchmod(0, 0620); /* crw--w---- */
264 } else { 265 } else {
265 /* 266 /*
266 * Standard input should already be connected to an open port. Make 267 * Standard input should already be connected to an open port. Make
@@ -286,9 +287,8 @@ static void termios_init(struct termios *tp, int speed, struct options *op)
286#endif 287#endif
287 288
288 tp->c_cflag = CS8 | HUPCL | CREAD | speed; 289 tp->c_cflag = CS8 | HUPCL | CREAD | speed;
289 if (op->flags & F_LOCAL) { 290 if (op->flags & F_LOCAL)
290 tp->c_cflag |= CLOCAL; 291 tp->c_cflag |= CLOCAL;
291 }
292 292
293 tp->c_iflag = tp->c_lflag = tp->c_line = 0; 293 tp->c_iflag = tp->c_lflag = tp->c_line = 0;
294 tp->c_oflag = OPOST | ONLCR; 294 tp->c_oflag = OPOST | ONLCR;
@@ -397,11 +397,11 @@ static char *get_logname(char *logname, unsigned size_logname,
397 char ascval; /* low 7 bits of input character */ 397 char ascval; /* low 7 bits of input character */
398 int bits; /* # of "1" bits per character */ 398 int bits; /* # of "1" bits per character */
399 int mask; /* mask with 1 bit up */ 399 int mask; /* mask with 1 bit up */
400 static const char erase[][3] = { /* backspace-space-backspace */ 400 static const char erase[][3] = {/* backspace-space-backspace */
401 "\010\040\010", /* space parity */ 401 "\010\040\010", /* space parity */
402 "\010\040\010", /* odd parity */ 402 "\010\040\010", /* odd parity */
403 "\210\240\210", /* even parity */ 403 "\210\240\210", /* even parity */
404 "\210\240\210", /* no parity */ 404 "\010\040\010", /* 8 bit no parity */
405 }; 405 };
406 406
407 /* NB: *cp is pre-initialized with init_chardata */ 407 /* NB: *cp is pre-initialized with init_chardata */
@@ -434,12 +434,11 @@ static char *get_logname(char *logname, unsigned size_logname,
434 return NULL; 434 return NULL;
435 435
436 /* Do parity bit handling. */ 436 /* Do parity bit handling. */
437 ascval = c & 0177; 437 if (!(op->flags & F_LOCAL) && (c & 0x80)) { /* "parity" bit on? */
438 if (!(op->flags & F_LOCAL) && (c != ascval)) { /* "parity" bit on ? */
439 bits = 1; 438 bits = 1;
440 mask = 1; 439 mask = 1;
441 while (mask & 0177) { 440 while (mask & 0x7f) {
442 if (mask & ascval) 441 if (mask & c)
443 bits++; /* count "1" bits */ 442 bits++; /* count "1" bits */
444 mask <<= 1; 443 mask <<= 1;
445 } 444 }
@@ -448,6 +447,7 @@ static char *get_logname(char *logname, unsigned size_logname,
448 } 447 }
449 448
450 /* Do erase, kill and end-of-line processing. */ 449 /* Do erase, kill and end-of-line processing. */
450 ascval = c & 0x7f;
451 switch (ascval) { 451 switch (ascval) {
452 case CR: 452 case CR:
453 case NL: 453 case NL:
@@ -507,7 +507,6 @@ static char *get_logname(char *logname, unsigned size_logname,
507static void termios_final(struct options *op, struct termios *tp, struct chardata *cp) 507static void termios_final(struct options *op, struct termios *tp, struct chardata *cp)
508{ 508{
509 /* General terminal-independent stuff. */ 509 /* General terminal-independent stuff. */
510
511 tp->c_iflag |= IXON | IXOFF; /* 2-way flow control */ 510 tp->c_iflag |= IXON | IXOFF; /* 2-way flow control */
512 tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE; 511 tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE;
513 /* no longer| ECHOCTL | ECHOPRT */ 512 /* no longer| ECHOCTL | ECHOPRT */
@@ -520,7 +519,6 @@ static void termios_final(struct options *op, struct termios *tp, struct chardat
520 tp->c_cc[VSWTC] = DEF_SWITCH; /* default switch character */ 519 tp->c_cc[VSWTC] = DEF_SWITCH; /* default switch character */
521 520
522 /* Account for special characters seen in input. */ 521 /* Account for special characters seen in input. */
523
524 if (cp->eol == CR) { 522 if (cp->eol == CR) {
525 tp->c_iflag |= ICRNL; /* map CR in input to NL */ 523 tp->c_iflag |= ICRNL; /* map CR in input to NL */
526 tp->c_oflag |= ONLCR; /* map NL in output to CR-NL */ 524 tp->c_oflag |= ONLCR; /* map NL in output to CR-NL */
@@ -529,9 +527,9 @@ static void termios_final(struct options *op, struct termios *tp, struct chardat
529 tp->c_cc[VKILL] = cp->kill; /* set kill character */ 527 tp->c_cc[VKILL] = cp->kill; /* set kill character */
530 528
531 /* Account for the presence or absence of parity bits in input. */ 529 /* Account for the presence or absence of parity bits in input. */
532
533 switch (cp->parity) { 530 switch (cp->parity) {
534 case 0: /* space (always 0) parity */ 531 case 0: /* space (always 0) parity */
532// I bet most people go here - they use only 7-bit chars in usernames....
535 break; 533 break;
536 case 1: /* odd parity */ 534 case 1: /* odd parity */
537 tp->c_cflag |= PARODD; 535 tp->c_cflag |= PARODD;
@@ -543,6 +541,9 @@ static void termios_final(struct options *op, struct termios *tp, struct chardat
543 case (1 | 2): /* no parity bit */ 541 case (1 | 2): /* no parity bit */
544 tp->c_cflag &= ~CSIZE; 542 tp->c_cflag &= ~CSIZE;
545 tp->c_cflag |= CS7; 543 tp->c_cflag |= CS7;
544// FIXME: wtf? case 3: we saw both even and odd 8-bit bytes -
545// it's probably some umlauts etc, but definitely NOT 7-bit!!!
546// Entire parity detection madness here just begs for deletion...
546 break; 547 break;
547 } 548 }
548 549
@@ -555,14 +556,12 @@ static void termios_final(struct options *op, struct termios *tp, struct chardat
555 } 556 }
556#endif 557#endif
557 /* Optionally enable hardware flow control */ 558 /* Optionally enable hardware flow control */
558
559#ifdef CRTSCTS 559#ifdef CRTSCTS
560 if (op->flags & F_RTSCTS) 560 if (op->flags & F_RTSCTS)
561 tp->c_cflag |= CRTSCTS; 561 tp->c_cflag |= CRTSCTS;
562#endif 562#endif
563 563
564 /* Finally, make the new settings effective */ 564 /* Finally, make the new settings effective */
565
566 ioctl_or_perror_and_die(0, TCSETS, tp, "%s: TCSETS", op->tty); 565 ioctl_or_perror_and_die(0, TCSETS, tp, "%s: TCSETS", op->tty);
567} 566}
568 567
@@ -634,6 +633,8 @@ int getty_main(int argc, char **argv)
634 struct termios termios; /* terminal mode bits */ 633 struct termios termios; /* terminal mode bits */
635 struct options options; 634 struct options options;
636 635
636 chardata = init_chardata;
637
637 memset(&options, 0, sizeof(options)); 638 memset(&options, 0, sizeof(options));
638 options.login = _PATH_LOGIN; /* default login program */ 639 options.login = _PATH_LOGIN; /* default login program */
639 options.tty = "tty1"; /* default tty line */ 640 options.tty = "tty1"; /* default tty line */
@@ -642,9 +643,9 @@ int getty_main(int argc, char **argv)
642 options.issue = ISSUE; /* default issue file */ 643 options.issue = ISSUE; /* default issue file */
643#endif 644#endif
644 645
645 /* Already too late because of theoretical 646 /* Parse command-line arguments. */
646 * possibility of getty --help somehow triggered 647 parse_args(argv, &options, &fakehost);
647 * inadvertently before we reach this. Oh well. */ 648
648 logmode = LOGMODE_NONE; 649 logmode = LOGMODE_NONE;
649 650
650 /* Create new session, lose controlling tty, if any */ 651 /* Create new session, lose controlling tty, if any */
@@ -652,16 +653,18 @@ int getty_main(int argc, char **argv)
652 * "This is allowed only when the current process 653 * "This is allowed only when the current process
653 * is not a process group leader" - is this a problem? */ 654 * is not a process group leader" - is this a problem? */
654 setsid(); 655 setsid();
655 656 /* close stdio, and stray descriptors, just in case */
656 n = xopen(bb_dev_null, O_RDWR); 657 n = xopen(bb_dev_null, O_RDWR);
657 /* dup2(n, 0); - no, because of possible "getty - 9600" */ 658 /* dup2(n, 0); - no, we need to handle "getty - 9600" too */
658 dup2(n, 1); 659 xdup2(n, 1);
659 dup2(n, 2); 660 xdup2(n, 2);
660 while (n > 2) 661 while (n > 2)
661 close(n--); 662 close(n--);
662 /* We want special flavor of error_msg_and_die */ 663
664 /* Logging. We want special flavor of error_msg_and_die */
663 die_sleep = 10; 665 die_sleep = 10;
664 msg_eol = "\r\n"; 666 msg_eol = "\r\n";
667 /* most likely will internally use fd #3 in CLOEXEC mode: */
665 openlog(applet_name, LOG_PID, LOG_AUTH); 668 openlog(applet_name, LOG_PID, LOG_AUTH);
666 logmode = LOGMODE_BOTH; 669 logmode = LOGMODE_BOTH;
667 670
@@ -673,15 +676,12 @@ int getty_main(int argc, char **argv)
673 } 676 }
674#endif 677#endif
675 678
676 /* Parse command-line arguments. */
677 parse_args(argv, &options, &fakehost);
678
679 debug("calling open_tty\n");
680 /* Open the tty as standard input, if it is not "-" */ 679 /* Open the tty as standard input, if it is not "-" */
680 /* If it's not "-" and not taken yet, it will become our ctty */
681 debug("calling open_tty\n");
681 open_tty(options.tty); 682 open_tty(options.tty);
682
683 debug("duping\n");
684 ndelay_off(0); 683 ndelay_off(0);
684 debug("duping\n");
685 xdup2(0, 1); 685 xdup2(0, 1);
686 xdup2(0, 2); 686 xdup2(0, 2);
687 687
@@ -695,17 +695,18 @@ int getty_main(int argc, char **argv)
695 */ 695 */
696 ioctl_or_perror_and_die(0, TCGETS, &termios, "%s: TCGETS", options.tty); 696 ioctl_or_perror_and_die(0, TCGETS, &termios, "%s: TCGETS", options.tty);
697 697
698#if ENABLE_FEATURE_UTMP
699 /* Update the utmp file */
700 update_utmp(options.tty, fakehost);
701#endif
702
703#ifdef __linux__ 698#ifdef __linux__
704 /* Make ourself a foreground process group within our session */ 699// FIXME: do we need this? Otherwise "-" case seems to be broken...
705 tcsetpgrp(0, getpid());
706 // /* Forcibly make fd 0 our controlling tty, even if another session 700 // /* Forcibly make fd 0 our controlling tty, even if another session
707 // * has it as a ctty. (Another session loses ctty). */ 701 // * has it as a ctty. (Another session loses ctty). */
708 // ioctl(0, TIOCSCTTY, (void*)1); 702 // ioctl(0, TIOCSCTTY, (void*)1);
703 /* Make ourself a foreground process group within our session */
704 tcsetpgrp(0, getpid());
705#endif
706
707#if ENABLE_FEATURE_UTMP
708 /* Update the utmp file. This tty is ours now! */
709 update_utmp(options.tty, fakehost);
709#endif 710#endif
710 711
711 /* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */ 712 /* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */
@@ -724,8 +725,7 @@ int getty_main(int argc, char **argv)
724 auto_baud(line_buf, sizeof(line_buf), &termios); 725 auto_baud(line_buf, sizeof(line_buf), &termios);
725 726
726 /* Set the optional timer */ 727 /* Set the optional timer */
727 if (options.timeout) 728 alarm(options.timeout); /* if 0, alarm is not set */
728 alarm(options.timeout);
729 729
730 /* Optionally wait for CR or LF before writing /etc/issue */ 730 /* Optionally wait for CR or LF before writing /etc/issue */
731 if (options.flags & F_WAITCRLF) { 731 if (options.flags & F_WAITCRLF) {
@@ -733,17 +733,14 @@ int getty_main(int argc, char **argv)
733 733
734 debug("waiting for cr-lf\n"); 734 debug("waiting for cr-lf\n");
735 while (safe_read(0, &ch, 1) == 1) { 735 while (safe_read(0, &ch, 1) == 1) {
736 debug("read %x\n", (unsigned char)ch);
736 ch &= 0x7f; /* strip "parity bit" */ 737 ch &= 0x7f; /* strip "parity bit" */
737#ifdef DEBUGGING
738 fprintf(dbf, "read %c\n", ch);
739#endif
740 if (ch == '\n' || ch == '\r') 738 if (ch == '\n' || ch == '\r')
741 break; 739 break;
742 } 740 }
743 } 741 }
744 742
745 logname = NULL; 743 logname = NULL;
746 chardata = init_chardata;
747 if (!(options.flags & F_NOPROMPT)) { 744 if (!(options.flags & F_NOPROMPT)) {
748 /* NB:termios_init already set line speed 745 /* NB:termios_init already set line speed
749 * to options.speeds[0] */ 746 * to options.speeds[0] */
@@ -753,7 +750,7 @@ int getty_main(int argc, char **argv)
753 /* Read the login name. */ 750 /* Read the login name. */
754 debug("reading login name\n"); 751 debug("reading login name\n");
755 logname = get_logname(line_buf, sizeof(line_buf), 752 logname = get_logname(line_buf, sizeof(line_buf),
756 &options, &chardata, &termios); 753 &options, &chardata, &termios);
757 if (logname) 754 if (logname)
758 break; 755 break;
759 /* we are here only if options.numspeed > 1 */ 756 /* we are here only if options.numspeed > 1 */
@@ -765,8 +762,7 @@ int getty_main(int argc, char **argv)
765 } 762 }
766 763
767 /* Disable timer. */ 764 /* Disable timer. */
768 if (options.timeout) 765 alarm(0);
769 alarm(0);
770 766
771 /* Finalize the termios settings. */ 767 /* Finalize the termios settings. */
772 termios_final(&options, &termios, &chardata); 768 termios_final(&options, &termios, &chardata);
@@ -777,7 +773,7 @@ int getty_main(int argc, char **argv)
777 /* Let the login program take care of password validation. */ 773 /* Let the login program take care of password validation. */
778 /* We use PATH because we trust that root doesn't set "bad" PATH, 774 /* We use PATH because we trust that root doesn't set "bad" PATH,
779 * and getty is not suid-root applet. */ 775 * and getty is not suid-root applet. */
780 /* Hmm... with -n, logname == NULL! Is it ok? */ 776 /* With -n, logname == NULL, and login will ask for username instead */
781 BB_EXECLP(options.login, options.login, "--", logname, NULL); 777 BB_EXECLP(options.login, options.login, "--", logname, NULL);
782 bb_error_msg_and_die("%s: can't exec %s", options.tty, options.login); 778 bb_error_msg_and_die("%s: can't exec %s", options.tty, options.login);
783} 779}