Added four options to be abel to delay agetty after start, to change the working directory, to change the root directory, and to modified scheduling priority. Do some code cleanup, e.g. use only one termios structure. Signed-off-by: Werner Fink <werner@xxxxxxx> --- term-utils/agetty.8 | 14 ++++ term-utils/agetty.c | 172 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 119 insertions(+), 67 deletions(-) diff --git a/term-utils/agetty.8 b/term-utils/agetty.8 index 8b29ad0..7529103 100644 --- a/term-utils/agetty.8 +++ b/term-utils/agetty.8 @@ -99,6 +99,12 @@ with \fB\-\-autologin\fP to save memory by lazily spawning shells. Don't reset terminal cflags (control modes). See \fItermios(3)\fP for more details. .TP +\-C, \-\-chdir \fIdirectory\fP +Change working \fIdirectory\fP before executing the login program. +.TP +\d, \-\-delay \fIseconds\fP +Sleep this many \fIseconds\fP after startup of agetty. +.TP \-f, \-\-issue\-file \fIissue_file\fP Display the contents of \fIissue_file\fP instead of \fI/etc/issue\fP. This allows custom messages to be displayed on different terminals. @@ -162,12 +168,20 @@ space parity, 7 bit characters, and ASCII CR (13) end-of-line character. Beware that the program that \fBagetty\fR starts (usually /bin/login) is run as root. .TP +\-N, \-\-nice \fIlevel\fP +Change the priority by calling \fBnice(2)\fP with specified \fIlevel\fP +before calling the login progam. +.TP \-o, \-\-login\-options \fI"login_options"\fP Options that are passed to the login program. \\u is replaced by the login name. Defaults to "\-\- \\u", which is suitable for \fB/bin/login\fP. Please read the SECURITY NOTICE below if you want to use this. .TP +\-r, \-\-chroot \fIdirectory\fP +Call chroot() with \fIdirectory\fP name before calling the +login program. +.TP \-s, \-\-keep\-baud Try to keep the existing baud rate. The baud rates from the command line are used when agetty receives a BREAK character. diff --git a/term-utils/agetty.c b/term-utils/agetty.c index 00bfda2..5f2fc9f 100644 --- a/term-utils/agetty.c +++ b/term-utils/agetty.c @@ -134,6 +134,8 @@ struct options { int flags; /* toggle switches, see below */ int timeout; /* time-out period */ char *autolog; /* login the user automatically */ + char *chdir; /* Chdir before the login */ + char *chroot; /* Chroot before the login */ char *login; /* login program */ char *logopt; /* options for login program */ char *tty; /* name of tty */ @@ -141,6 +143,8 @@ struct options { char *term; /* terminal type */ char *initstring; /* modem init string */ char *issue; /* alternative issue file */ + int delay; /* Sleep seconds before prompt */ + int nice; /* Run login with this priority */ int numspeed; /* number of baud rates to try */ speed_t speeds[MAX_SPEED]; /* baud rates to be tried */ }; @@ -235,7 +239,7 @@ static void parse_speeds(struct options *op, char *arg); static void update_utmp(struct options *op); static void open_tty(char *tty, struct termios *tp, struct options *op); static void termio_init(struct options *op, struct termios *tp); -static void reset_vc (const struct options *op); +static void reset_vc (const struct options *op, struct termios *tp); static void auto_baud(struct termios *tp); static void output_special_char (unsigned char c, struct options *op, struct termios *tp); static void do_prompt(struct options *op, struct termios *tp); @@ -307,6 +311,9 @@ int main(int argc, char **argv) update_utmp(&options); #endif + if (options.delay) + sleep(options.delay); + debug("calling open_tty\n"); /* Open the tty as standard { input, output, error }. */ @@ -368,7 +375,7 @@ int main(int argc, char **argv) /* Do the auto login */ debug("doing auto login\n"); do_prompt(&options, &termios); - printf ("%s%s (automatic login)\n", LOGIN, options.autolog); + printf ("%s%s (automatic login)\r\n", LOGIN, options.autolog); logname = options.autolog; options.logopt = "-f \\u"; } else { @@ -390,7 +397,7 @@ int main(int argc, char **argv) termio_final(&options, &termios, &chardata); /* Now the newline character should be properly written. */ - safe_write(STDOUT_FILENO, "\r\n", 1); + safe_write(STDOUT_FILENO, "\r\n", 2); } sigaction (SIGQUIT, &sa_quit, NULL); @@ -404,6 +411,13 @@ int main(int argc, char **argv) mkarray(logarr, logcmd); replacename(logarr, logname); + if (options.chroot) + chroot(options.chroot); + if (options.chdir) + chdir(options.chdir); + if (options.nice) + nice(options.nice); + /* Let the login program take care of password validation. */ execv(options.login, logarr); warn(_("%s: can't exec %s: %m"), options.tty, options.login); @@ -434,6 +448,8 @@ static void parse_args(int argc, char **argv, struct options *op) { "8bits", no_argument, 0, '8' }, { "autologin", required_argument, 0, 'a' }, { "noreset", no_argument, 0, 'c' }, + { "chdir", required_argument, 0, 'C' }, + { "delay", required_argument, 0, 'd' }, { "issue-file", required_argument, 0, 'f' }, { "flow-control", no_argument, 0, 'h' }, { "host", required_argument, 0, 'H' }, @@ -445,9 +461,11 @@ static void parse_args(int argc, char **argv, struct options *op) { "local-line", no_argument, 0, 'L' }, { "extract-baud", no_argument, 0, 'm' }, { "skip-login", no_argument, 0, 'n' }, + { "nice", required_argument, 0, 'N' }, { "login-options", required_argument, 0, 'o' }, { "loginopts", required_argument, 0, 'o' }, /* compat option */ { "logopts", required_argument, 0, 'o' }, /* compat option */ + { "chroot", required_argument, 0, 'r' }, { "keep-baud", no_argument, 0, 's' }, { "timeout", required_argument, 0, 't' }, { "detect-case", no_argument, 0, 'U' }, @@ -457,7 +475,7 @@ static void parse_args(int argc, char **argv, struct options *op) { NULL, 0, 0, 0 } }; - while ((c = getopt_long(argc, argv, "8a:cf:hH:iI:l:Lmno:st:Uw", longopts, + while ((c = getopt_long(argc, argv, "8a:cC:d:f:hH:iI:l:LmNno:r:st:Uw", longopts, &index)) != -1) { switch (c) { case 0: @@ -472,6 +490,12 @@ static void parse_args(int argc, char **argv, struct options *op) case 'c': op->flags |= F_KEEPCFLAGS; break; + case 'C': + op->chdir = optarg; + break; + case 'd': + op->delay = atoi(optarg); + break; case 'f': op->flags |= F_CUSTISSUE; op->issue = optarg; @@ -501,9 +525,15 @@ static void parse_args(int argc, char **argv, struct options *op) case 'n': op->flags |= F_NOPROMPT; break; + case 'N': + op->nice = atoi(optarg); + break; case 'o': op->logopt = optarg; break; + case 'r': + op->chroot = optarg; + break; case 's': op->flags |= F_KEEPSPEED; break; @@ -782,7 +812,7 @@ static void open_tty(char *tty, struct termios *tp, struct options *op) if (open(buf, O_RDWR|O_NOCTTY|O_NONBLOCK, 0) != 0) error(_("/dev/%s: cannot open as standard input: %m"), tty); if (((tid = tcgetsid(0)) < 0) || (pid != tid)) { - if (ioctl (0, TIOCSCTTY, 1) == -1) + if (ioctl (STDIN_FILENO, TIOCSCTTY, 1) == -1) error("/dev/%s: cannot get controlling tty: %m", tty); } @@ -823,6 +853,7 @@ static void open_tty(char *tty, struct termios *tp, struct options *op) * "zsadtrlow" to a larger value; 5 seconds seems to be a good value. * http://www.sunmanagers.org/archives/1993/0574.html */ + memset(tp, 0, sizeof(struct termios)); if (tcgetattr(STDIN_FILENO, tp) < 0) error("%s: tcgetattr: %m", tty); @@ -871,8 +902,11 @@ static void termio_init(struct options *op, struct termios *tp) setlocale(LC_CTYPE, "POSIX"); op->flags &= ~F_UTF8; #endif - reset_vc(op); - op->flags |= F_EIGHTBITS; + reset_vc(op, tp); + + if ((tp->c_cflag & (CS8|PARODD|PARENB)) == CS8) + op->flags |= F_EIGHTBITS; + if ((op->flags & F_NOCLEAR) == 0) { /* * Do not write a full reset (ESC c) because this destroys @@ -883,7 +917,7 @@ static void termio_init(struct options *op, struct termios *tp) * erase everything below the cursor (ESC [ J), and set the * scrolling region to the full window (ESC [ r) */ - safe_write(0, "\033[r\033[H\033[J", 9); + safe_write(STDIN_FILENO, "\033[r\033[H\033[J", 9); } return; } @@ -960,71 +994,67 @@ static void termio_init(struct options *op, struct termios *tp) } /* Reset virtual console on stdin to its defaults */ -static void reset_vc(const struct options *op) +static void reset_vc(const struct options *op, struct termios *tp) { - struct termios termios; - /* - * The above reset only puts the output things into a sane state. - * The input state is not reset. - */ - memset (&termios, 0, sizeof termios); - if (tcgetattr (0, &termios)) - warn ("tcgetattr problem: %m"); - /* Use defaults of <sys/ttydefaults.h> for base settings */ - termios.c_iflag |= TTYDEF_IFLAG; - termios.c_oflag |= TTYDEF_OFLAG; - termios.c_lflag |= TTYDEF_LFLAG; + tp->c_iflag |= TTYDEF_IFLAG; + tp->c_oflag |= TTYDEF_OFLAG; + tp->c_lflag |= TTYDEF_LFLAG; + + if ((op->flags & F_KEEPCFLAGS) == 0) { #ifdef CBAUD - termios.c_lflag &= ~CBAUD; + tp->c_lflag &= ~CBAUD; #endif - termios.c_cflag |= (B38400 | TTYDEF_CFLAG); + tp->c_cflag |= (B38400 | TTYDEF_CFLAG); + } /* Sane setting, allow eight bit characters, no carriage return delay * the same result as `stty sane cr0 pass8' */ - termios.c_iflag |= (BRKINT | ICRNL | IMAXBEL); - termios.c_iflag &= ~(IGNBRK | INLCR | IGNCR | IXOFF | IUCLC | IXANY | ISTRIP); - termios.c_oflag |= (OPOST | ONLCR | NL0 | CR0 | TAB0 | BS0 | VT0 | FF0); - termios.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL |\ + tp->c_iflag |= (BRKINT | ICRNL | IMAXBEL); + tp->c_iflag &= ~(IGNBRK | INLCR | IGNCR | IXOFF | IUCLC | IXANY | ISTRIP); + tp->c_oflag |= (OPOST | ONLCR | NL0 | CR0 | TAB0 | BS0 | VT0 | FF0); + tp->c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL |\ NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); - termios.c_lflag |= (ISIG | ICANON | IEXTEN | ECHO|ECHOE|ECHOK|ECHOKE); - termios.c_lflag &= ~(ECHONL|ECHOCTL|ECHOPRT | NOFLSH | XCASE | TOSTOP); - termios.c_cflag |= (CREAD | CS8 | HUPCL); - termios.c_cflag &= ~(PARODD | PARENB); + tp->c_lflag |= (ISIG | ICANON | IEXTEN | ECHO|ECHOE|ECHOK|ECHOKE); + tp->c_lflag &= ~(ECHONL|ECHOPRT | NOFLSH | XCASE | TOSTOP); + if ((op->flags & F_KEEPCFLAGS) == 0) { + tp->c_cflag |= (CREAD | CS8 | HUPCL); + tp->c_cflag &= ~(PARODD | PARENB); + } #ifdef IUTF8 if (op->flags & F_UTF8) - termios.c_iflag |= IUTF8; /* Set UTF-8 input flag */ + tp->c_iflag |= IUTF8; /* Set UTF-8 input flag */ else #endif - termios.c_iflag &= ~IUTF8; + tp->c_iflag &= ~IUTF8; /* VTIME and VMIN can overlap with VEOF and VEOL since they are * only used for non-canonical mode. We just set the at the * beginning, so nothing bad should happen. */ - termios.c_cc[VTIME] = 0; - termios.c_cc[VMIN] = 1; - termios.c_cc[VINTR] = CINTR; - termios.c_cc[VQUIT] = CQUIT; - termios.c_cc[VERASE] = CERASE; /* ASCII DEL (0177) */ - termios.c_cc[VKILL] = CKILL; - termios.c_cc[VEOF] = CEOF; + tp->c_cc[VTIME] = 0; + tp->c_cc[VMIN] = 1; + tp->c_cc[VINTR] = CINTR; + tp->c_cc[VQUIT] = CQUIT; + tp->c_cc[VERASE] = CERASE; /* ASCII DEL (0177) */ + tp->c_cc[VKILL] = CKILL; + tp->c_cc[VEOF] = CEOF; #ifdef VSWTC - termios.c_cc[VSWTC] = _POSIX_VDISABLE; -#else - termios.c_cc[VSWTCH] = _POSIX_VDISABLE; + tp->c_cc[VSWTC] = _POSIX_VDISABLE; +#elif defined(VSWTCH) + tp->c_cc[VSWTCH] = _POSIX_VDISABLE; #endif - termios.c_cc[VSTART] = CSTART; - termios.c_cc[VSTOP] = CSTOP; - termios.c_cc[VSUSP] = CSUSP; - termios.c_cc[VEOL] = _POSIX_VDISABLE; - termios.c_cc[VREPRINT] = CREPRINT; - termios.c_cc[VDISCARD] = CDISCARD; - termios.c_cc[VWERASE] = CWERASE; - termios.c_cc[VLNEXT] = CLNEXT; - termios.c_cc[VEOL2] = _POSIX_VDISABLE; - if (tcsetattr (0, TCSADRAIN, &termios)) + tp->c_cc[VSTART] = CSTART; + tp->c_cc[VSTOP] = CSTOP; + tp->c_cc[VSUSP] = CSUSP; + tp->c_cc[VEOL] = _POSIX_VDISABLE; + tp->c_cc[VREPRINT] = CREPRINT; + tp->c_cc[VDISCARD] = CDISCARD; + tp->c_cc[VWERASE] = CWERASE; + tp->c_cc[VLNEXT] = CLNEXT; + tp->c_cc[VEOL2] = _POSIX_VDISABLE; + if (tcsetattr (STDIN_FILENO, TCSADRAIN, tp)) warn ("tcsetattr problem: %m"); } @@ -1093,7 +1123,7 @@ static void do_prompt(struct options *op, struct termios *tp) { #ifdef ISSUE FILE *fd; -#endif /* ISSUE */ +#endif if ((op->flags & F_NONL) == 0) /* Issue not in use, start with a new line. */ @@ -1167,7 +1197,7 @@ static void do_prompt(struct options *op, struct termios *tp) } if (len) - printf ("Hint: %s\n\n", warn); + printf ("Hint: %s\r\n\r\n", warn); } } #endif @@ -1306,7 +1336,7 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata cp->erase = ascval; /* set erase character */ if (bp > logname) { if ((tp->c_cflag & (ECHO)) == 0) - safe_write(1, erase[cp->parity], 3); + safe_write(STDOUT_FILENO, erase[cp->parity], 3); bp--; } break; @@ -1315,7 +1345,7 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata cp->kill = ascval; /* set kill character */ while (bp > logname) { if ((tp->c_cflag & (ECHO)) == 0) - safe_write(1, erase[cp->parity], 3); + safe_write(STDOUT_FILENO, erase[cp->parity], 3); bp--; } break; @@ -1327,7 +1357,7 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata if ((size_t)(bp - logname) >= sizeof(logname) - 1) error(_("%s: input overrun"), op->tty); if ((tp->c_cflag & (ECHO)) == 0) - safe_write(1, &c, 1); /* echo the character */ + safe_write(STDOUT_FILENO, &c, 1); /* echo the character */ *bp++ = ascval; /* and store it */ break; } @@ -1335,7 +1365,8 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata } - if ((op->flags & F_UTF8) && (ic = iconv_open("WCHAR_T", "UTF-8"))) { + if ((op->flags & (F_EIGHTBITS|F_UTF8)) == (F_EIGHTBITS|F_UTF8) && + (ic = iconv_open("WCHAR_T", "UTF-8"))) { char tmpbuf[4*sizeof(logname)], *optr, *lptr; size_t len = bp - logname; size_t out = sizeof(tmpbuf) - 1; @@ -1379,15 +1410,18 @@ static void termio_final(struct options *op, struct termios *tp, struct chardata /* no longer| ECHOCTL | ECHOPRT */ tp->c_oflag |= OPOST; /* tp->c_cflag = 0; */ - tp->c_cc[VINTR] = DEF_INTR; - tp->c_cc[VQUIT] = DEF_QUIT; - tp->c_cc[VEOF] = DEF_EOF; - tp->c_cc[VEOL] = DEF_EOL; -#ifdef __linux__ - tp->c_cc[VSWTC] = DEF_SWITCH; + tp->c_cc[VINTR] = CINTR; + tp->c_cc[VQUIT] = CQUIT; + tp->c_cc[VEOF] = CEOF; + tp->c_cc[VEOL] = _POSIX_VDISABLE; +#if defined(VSWTC) + tp->c_cc[VSWTC] = _POSIX_VDISABLE; #elif defined(VSWTCH) - tp->c_cc[VSWTCH] = DEF_SWITCH; -#endif /* __linux__ */ + tp->c_cc[VSWTCH] = _POSIX_VDISABLE; +#endif + tp->c_cc[VSTART] = CSTART; + tp->c_cc[VSTOP] = CSTOP; + tp->c_cc[VSUSP] = CSUSP; /* Account for special characters seen in input. */ if (cp->eol == CR) { @@ -1618,6 +1652,10 @@ static void output_special_char(unsigned char c, struct options *op, { struct utsname uts; (void) uname(&uts); + + if ((op->flags & F_VCONSOLE) == 0) + setvbuf(stdout, NULL, _IONBF, 0); + switch (c) { case 's': (void) printf ("%s", uts.sysname); -- 1.6.0.2 -- To unsubscribe from this list: send the line "unsubscribe util-linux" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html