]> git.ipfire.org Git - thirdparty/util-linux.git/blob - term-utils/agetty.c
docs: Fix word repetitions
[thirdparty/util-linux.git] / term-utils / agetty.c
1 /*
2 * Alternate Getty (agetty) 'agetty' is a versatile, portable, easy to use
3 * replacement for getty on SunOS 4.1.x or the SAC ttymon/ttyadm/sacadm/pmadm
4 * suite on Solaris and other SVR4 systems. 'agetty' was written by Wietse
5 * Venema, enhanced by John DiMarco, and further enhanced by Dennis Cronin.
6 *
7 * Ported to Linux by Peter Orbaek <poe@daimi.aau.dk>
8 * Adopt the mingetty features for a better support
9 * of virtual consoles by Werner Fink <werner@suse.de>
10 *
11 * This program is freely distributable.
12 */
13
14 #include <stdio.h>
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <termios.h>
19 #include <signal.h>
20 #include <errno.h>
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/wait.h>
25 #include <fcntl.h>
26 #include <stdarg.h>
27 #include <ctype.h>
28 #include <utmpx.h>
29 #include <getopt.h>
30 #include <time.h>
31 #include <sys/socket.h>
32 #include <langinfo.h>
33 #include <grp.h>
34 #include <arpa/inet.h>
35 #include <netdb.h>
36 #include <ifaddrs.h>
37 #include <net/if.h>
38
39 #include "strutils.h"
40 #include "all-io.h"
41 #include "nls.h"
42 #include "pathnames.h"
43 #include "c.h"
44 #include "widechar.h"
45 #include "ttyutils.h"
46 #include "color-names.h"
47 #include "env.h"
48
49 #ifdef USE_PLYMOUTH_SUPPORT
50 # include "plymouth-ctrl.h"
51 #endif
52
53 #ifdef HAVE_SYS_PARAM_H
54 # include <sys/param.h>
55 #endif
56
57 #if defined(__FreeBSD_kernel__)
58 # include <pty.h>
59 # ifdef HAVE_UTMP_H
60 # include <utmp.h>
61 # endif
62 # ifdef HAVE_LIBUTIL_H
63 # include <libutil.h>
64 # endif
65 #endif
66
67 #ifdef __linux__
68 # include <sys/kd.h>
69 # define USE_SYSLOG
70 # ifndef DEFAULT_VCTERM
71 # define DEFAULT_VCTERM "linux"
72 # endif
73 # if defined (__s390__) || defined (__s390x__)
74 # define DEFAULT_TTYS0 "dumb"
75 # define DEFAULT_TTY32 "ibm327x"
76 # define DEFAULT_TTYS1 "vt220"
77 # endif
78 # ifndef DEFAULT_STERM
79 # define DEFAULT_STERM "vt102"
80 # endif
81 #elif defined(__GNU__)
82 # define USE_SYSLOG
83 # ifndef DEFAULT_VCTERM
84 # define DEFAULT_VCTERM "hurd"
85 # endif
86 # ifndef DEFAULT_STERM
87 # define DEFAULT_STERM "vt102"
88 # endif
89 #else
90 # ifndef DEFAULT_VCTERM
91 # define DEFAULT_VCTERM "vt100"
92 # endif
93 # ifndef DEFAULT_STERM
94 # define DEFAULT_STERM "vt100"
95 # endif
96 #endif
97
98 #ifdef __FreeBSD_kernel__
99 #define USE_SYSLOG
100 #endif
101
102 /* If USE_SYSLOG is undefined all diagnostics go to /dev/console. */
103 #ifdef USE_SYSLOG
104 # include <syslog.h>
105 #endif
106
107 /*
108 * Some heuristics to find out what environment we are in: if it is not
109 * System V, assume it is SunOS 4. The LOGIN_PROCESS is defined in System V
110 * utmp.h, which will select System V style getty.
111 */
112 #ifdef LOGIN_PROCESS
113 # define SYSV_STYLE
114 #endif
115
116 /*
117 * Things you may want to modify.
118 *
119 * If ISSUE is not defined, agetty will never display the contents of the
120 * /etc/issue file. You will not want to spit out large "issue" files at the
121 * wrong baud rate. Relevant for System V only.
122 *
123 * You may disagree with the default line-editing etc. characters defined
124 * below. Note, however, that DEL cannot be used for interrupt generation
125 * and for line editing at the same time.
126 */
127
128 /* Displayed before the login prompt. */
129 #ifdef SYSV_STYLE
130 # define ISSUE _PATH_ISSUE
131 # include <sys/utsname.h>
132 #endif
133
134 /* Login prompt. */
135 #define LOGIN "login: "
136 #define LOGIN_ARGV_MAX 16 /* Numbers of args for login */
137
138 /*
139 * agetty --reload
140 */
141 #ifdef AGETTY_RELOAD
142 # include <sys/inotify.h>
143 # include <linux/netlink.h>
144 # include <linux/rtnetlink.h>
145 # define AGETTY_RELOAD_FILENAME "/run/agetty.reload" /* trigger file */
146 # define AGETTY_RELOAD_FDNONE -2 /* uninitialized fd */
147 static int inotify_fd = AGETTY_RELOAD_FDNONE;
148 static int netlink_fd = AGETTY_RELOAD_FDNONE;
149 #endif
150
151 /*
152 * When multiple baud rates are specified on the command line, the first one
153 * we will try is the first one specified.
154 */
155 #define FIRST_SPEED 0
156
157 /* Storage for command-line options. */
158 #define MAX_SPEED 10 /* max. nr. of baud rates */
159
160 struct options {
161 int flags; /* toggle switches, see below */
162 unsigned int timeout; /* time-out period */
163 char *autolog; /* login the user automatically */
164 char *chdir; /* Chdir before the login */
165 char *chroot; /* Chroot before the login */
166 char *login; /* login program */
167 char *logopt; /* options for login program */
168 char *tty; /* name of tty */
169 char *vcline; /* line of virtual console */
170 char *term; /* terminal type */
171 char *initstring; /* modem init string */
172 char *issue; /* alternative issue file */
173 char *erasechars; /* string with erase chars */
174 char *killchars; /* string with kill chars */
175 char *osrelease; /* /etc/os-release data */
176 unsigned int delay; /* Sleep seconds before prompt */
177 int nice; /* Run login with this priority */
178 int numspeed; /* number of baud rates to try */
179 int clocal; /* CLOCAL_MODE_* */
180 int kbmode; /* Keyboard mode if virtual console */
181 speed_t speeds[MAX_SPEED]; /* baud rates to be tried */
182 };
183
184 enum {
185 CLOCAL_MODE_AUTO = 0,
186 CLOCAL_MODE_ALWAYS,
187 CLOCAL_MODE_NEVER
188 };
189
190 #define F_PARSE (1<<0) /* process modem status messages */
191 #define F_ISSUE (1<<1) /* display /etc/issue */
192 #define F_RTSCTS (1<<2) /* enable RTS/CTS flow control */
193
194 #define F_INITSTRING (1<<4) /* initstring is set */
195 #define F_WAITCRLF (1<<5) /* wait for CR or LF */
196 #define F_CUSTISSUE (1<<6) /* give alternative issue file */
197 #define F_NOPROMPT (1<<7) /* do not ask for login name! */
198 #define F_LCUC (1<<8) /* support for *LCUC stty modes */
199 #define F_KEEPSPEED (1<<9) /* follow baud rate from kernel */
200 #define F_KEEPCFLAGS (1<<10) /* reuse c_cflags setup from kernel */
201 #define F_EIGHTBITS (1<<11) /* Assume 8bit-clean tty */
202 #define F_VCONSOLE (1<<12) /* This is a virtual console */
203 #define F_HANGUP (1<<13) /* Do call vhangup(2) */
204 #define F_UTF8 (1<<14) /* We can do UTF8 */
205 #define F_LOGINPAUSE (1<<15) /* Wait for any key before dropping login prompt */
206 #define F_NOCLEAR (1<<16) /* Do not clear the screen before prompting */
207 #define F_NONL (1<<17) /* No newline before issue */
208 #define F_NOHOSTNAME (1<<18) /* Do not show the hostname */
209 #define F_LONGHNAME (1<<19) /* Show Full qualified hostname */
210 #define F_NOHINTS (1<<20) /* Don't print hints */
211 #define F_REMOTE (1<<21) /* Add '-h fakehost' to login(1) command line */
212
213 #define serial_tty_option(opt, flag) \
214 (((opt)->flags & (F_VCONSOLE|(flag))) == (flag))
215
216 struct Speedtab {
217 long speed;
218 speed_t code;
219 };
220
221 static const struct Speedtab speedtab[] = {
222 {50, B50},
223 {75, B75},
224 {110, B110},
225 {134, B134},
226 {150, B150},
227 {200, B200},
228 {300, B300},
229 {600, B600},
230 {1200, B1200},
231 {1800, B1800},
232 {2400, B2400},
233 {4800, B4800},
234 {9600, B9600},
235 #ifdef B19200
236 {19200, B19200},
237 #elif defined(EXTA)
238 {19200, EXTA},
239 #endif
240 #ifdef B38400
241 {38400, B38400},
242 #elif defined(EXTB)
243 {38400, EXTB},
244 #endif
245 #ifdef B57600
246 {57600, B57600},
247 #endif
248 #ifdef B115200
249 {115200, B115200},
250 #endif
251 #ifdef B230400
252 {230400, B230400},
253 #endif
254 #ifdef B460800
255 {460800, B460800},
256 #endif
257 #ifdef B500000
258 {500000, B500000},
259 #endif
260 #ifdef B576000
261 {576000, B576000},
262 #endif
263 #ifdef B921600
264 {921600, B921600},
265 #endif
266 #ifdef B1000000
267 {1000000, B1000000},
268 #endif
269 #ifdef B1152000
270 {1152000, B1152000},
271 #endif
272 #ifdef B1500000
273 {1500000, B1500000},
274 #endif
275 #ifdef B2000000
276 {2000000, B2000000},
277 #endif
278 #ifdef B2500000
279 {2500000, B2500000},
280 #endif
281 #ifdef B3000000
282 {3000000, B3000000},
283 #endif
284 #ifdef B3500000
285 {3500000, B3500000},
286 #endif
287 #ifdef B4000000
288 {4000000, B4000000},
289 #endif
290 {0, 0},
291 };
292
293 static void init_special_char(char* arg, struct options *op);
294 static void parse_args(int argc, char **argv, struct options *op);
295 static void parse_speeds(struct options *op, char *arg);
296 static void update_utmp(struct options *op);
297 static void open_tty(char *tty, struct termios *tp, struct options *op);
298 static void termio_init(struct options *op, struct termios *tp);
299 static void reset_vc (const struct options *op, struct termios *tp);
300 static void auto_baud(struct termios *tp);
301 static void output_special_char (unsigned char c, struct options *op,
302 struct termios *tp, FILE *fp);
303 static void do_prompt(struct options *op, struct termios *tp);
304 static void next_speed(struct options *op, struct termios *tp);
305 static char *get_logname(struct options *op,
306 struct termios *tp, struct chardata *cp);
307 static void termio_final(struct options *op,
308 struct termios *tp, struct chardata *cp);
309 static int caps_lock(char *s);
310 static speed_t bcode(char *s);
311 static void usage(FILE * out) __attribute__((__noreturn__));
312 static void log_err(const char *, ...) __attribute__((__noreturn__))
313 __attribute__((__format__(printf, 1, 2)));
314 static void log_warn (const char *, ...)
315 __attribute__((__format__(printf, 1, 2)));
316 static ssize_t append(char *dest, size_t len, const char *sep, const char *src);
317 static void check_username (const char* nm);
318 static void login_options_to_argv(char *argv[], int *argc, char *str, char *username);
319 static void reload_agettys(void);
320
321 /* Fake hostname for ut_host specified on command line. */
322 static char *fakehost;
323
324 #ifdef DEBUGGING
325 # include "closestream.h"
326 # ifndef DEBUG_OUTPUT
327 # define DEBUG_OUTPUT "/dev/tty10"
328 # endif
329 # define debug(s) do { fprintf(dbf,s); fflush(dbf); } while (0)
330 FILE *dbf;
331 #else
332 # define debug(s) do { ; } while (0)
333 #endif
334
335 int main(int argc, char **argv)
336 {
337 char *username = NULL; /* login name, given to /bin/login */
338 struct chardata chardata; /* will be set by get_logname() */
339 struct termios termios; /* terminal mode bits */
340 struct options options = {
341 .flags = F_ISSUE, /* show /etc/issue (SYSV_STYLE) */
342 .login = _PATH_LOGIN, /* default login program */
343 .tty = "tty1", /* default tty line */
344 .issue = ISSUE /* default issue file */
345 };
346 char *login_argv[LOGIN_ARGV_MAX + 1];
347 int login_argc = 0;
348 struct sigaction sa, sa_hup, sa_quit, sa_int;
349 sigset_t set;
350
351 setlocale(LC_ALL, "");
352 bindtextdomain(PACKAGE, LOCALEDIR);
353 textdomain(PACKAGE);
354
355 /* In case vhangup(2) has to called */
356 sa.sa_handler = SIG_IGN;
357 sa.sa_flags = SA_RESTART;
358 sigemptyset (&sa.sa_mask);
359 sigaction(SIGHUP, &sa, &sa_hup);
360 sigaction(SIGQUIT, &sa, &sa_quit);
361 sigaction(SIGINT, &sa, &sa_int);
362
363 #ifdef DEBUGGING
364 dbf = fopen(DEBUG_OUTPUT, "w");
365 for (int i = 1; i < argc; i++) {
366 if (i > 1)
367 debug(" ");
368 debug(argv[i]);
369 }
370 debug("\n");
371 #endif /* DEBUGGING */
372
373 /* Parse command-line arguments. */
374 parse_args(argc, argv, &options);
375
376 login_argv[login_argc++] = options.login; /* set login program name */
377
378 /* Update the utmp file. */
379 #ifdef SYSV_STYLE
380 update_utmp(&options);
381 #endif
382 if (options.delay)
383 sleep(options.delay);
384
385 debug("calling open_tty\n");
386
387 /* Open the tty as standard { input, output, error }. */
388 open_tty(options.tty, &termios, &options);
389
390 /* Unmask SIGHUP if inherited */
391 sigemptyset(&set);
392 sigaddset(&set, SIGHUP);
393 sigprocmask(SIG_UNBLOCK, &set, NULL);
394 sigaction(SIGHUP, &sa_hup, NULL);
395
396 tcsetpgrp(STDIN_FILENO, getpid());
397
398 /* Default is to follow the current line speed and then default to 9600 */
399 if ((options.flags & F_VCONSOLE) == 0 && options.numspeed == 0) {
400 options.speeds[options.numspeed++] = bcode("9600");
401 options.flags |= F_KEEPSPEED;
402 }
403
404 /* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */
405 debug("calling termio_init\n");
406 termio_init(&options, &termios);
407
408 /* Write the modem init string and DO NOT flush the buffers. */
409 if (serial_tty_option(&options, F_INITSTRING) &&
410 options.initstring && *options.initstring != '\0') {
411 debug("writing init string\n");
412 write_all(STDOUT_FILENO, options.initstring,
413 strlen(options.initstring));
414 }
415
416 if (options.flags & F_VCONSOLE || options.clocal != CLOCAL_MODE_ALWAYS)
417 /* Go to blocking mode unless -L is specified, this change
418 * affects stdout, stdin and stderr as all the file descriptors
419 * are created by dup(). */
420 fcntl(STDOUT_FILENO, F_SETFL,
421 fcntl(STDOUT_FILENO, F_GETFL, 0) & ~O_NONBLOCK);
422
423 /* Optionally detect the baud rate from the modem status message. */
424 debug("before autobaud\n");
425 if (serial_tty_option(&options, F_PARSE))
426 auto_baud(&termios);
427
428 /* Set the optional timer. */
429 if (options.timeout)
430 alarm(options.timeout);
431
432 /* Optionally wait for CR or LF before writing /etc/issue */
433 if (serial_tty_option(&options, F_WAITCRLF)) {
434 char ch;
435
436 debug("waiting for cr-lf\n");
437 while (read(STDIN_FILENO, &ch, 1) == 1) {
438 /* Strip "parity bit". */
439 ch &= 0x7f;
440 #ifdef DEBUGGING
441 fprintf(dbf, "read %c\n", ch);
442 #endif
443 if (ch == '\n' || ch == '\r')
444 break;
445 }
446 }
447
448 INIT_CHARDATA(&chardata);
449
450 if (options.autolog) {
451 debug("doing auto login\n");
452 username = options.autolog;
453 }
454
455 if ((options.flags & F_NOPROMPT) == 0) {
456 if (options.autolog) {
457 /* Autologin prompt */
458 do_prompt(&options, &termios);
459 printf(_("%s%s (automatic login)\n"), LOGIN, options.autolog);
460 } else {
461 /* Read the login name. */
462 debug("reading login name\n");
463 while ((username =
464 get_logname(&options, &termios, &chardata)) == NULL)
465 if ((options.flags & F_VCONSOLE) == 0 && options.numspeed)
466 next_speed(&options, &termios);
467 }
468 }
469
470 /* Disable timer. */
471 if (options.timeout)
472 alarm(0);
473
474 if ((options.flags & F_VCONSOLE) == 0) {
475 /* Finalize the termios settings. */
476 termio_final(&options, &termios, &chardata);
477
478 /* Now the newline character should be properly written. */
479 write_all(STDOUT_FILENO, "\r\n", 2);
480 }
481
482 sigaction(SIGQUIT, &sa_quit, NULL);
483 sigaction(SIGINT, &sa_int, NULL);
484
485 if (username)
486 check_username(username);
487
488 if (options.logopt) {
489 /*
490 * The --login-options completely overwrites the default
491 * way how agetty composes login(1) command line.
492 */
493 login_options_to_argv(login_argv, &login_argc,
494 options.logopt, username);
495 } else {
496 if (fakehost && (options.flags & F_REMOTE)) {
497 login_argv[login_argc++] = "-h";
498 login_argv[login_argc++] = fakehost;
499 }
500 if (username) {
501 if (options.autolog)
502 login_argv[login_argc++] = "-f";
503 else
504 login_argv[login_argc++] = "--";
505 login_argv[login_argc++] = username;
506 }
507 }
508
509 login_argv[login_argc] = NULL; /* last login argv */
510
511 if (options.chroot && chroot(options.chroot) < 0)
512 log_err(_("%s: can't change root directory %s: %m"),
513 options.tty, options.chroot);
514 if (options.chdir && chdir(options.chdir) < 0)
515 log_err(_("%s: can't change working directory %s: %m"),
516 options.tty, options.chdir);
517 if (options.nice && nice(options.nice) < 0)
518 log_warn(_("%s: can't change process priority: %m"),
519 options.tty);
520
521 free(options.osrelease);
522 #ifdef DEBUGGING
523 if (close_stream(dbf) != 0)
524 log_err("write failed: %s", DEBUG_OUTPUT);
525 #endif
526
527 /* Let the login program take care of password validation. */
528 execv(options.login, login_argv);
529 log_err(_("%s: can't exec %s: %m"), options.tty, login_argv[0]);
530 }
531
532 /*
533 * Returns : @str if \u not found
534 * : @username if @str equal to "\u"
535 * : newly allocated string if \u mixed with something other
536 */
537 static char *replace_u(char *str, char *username)
538 {
539 char *entry = NULL, *p = str;
540 size_t usz = username ? strlen(username) : 0;
541
542 while (*p) {
543 size_t sz;
544 char *tp, *old = entry;
545
546 if (memcmp(p, "\\u", 2)) {
547 p++;
548 continue; /* no \u */
549 }
550 sz = strlen(str);
551
552 if (p == str && sz == 2) {
553 /* 'str' contains only '\u' */
554 free(old);
555 return username;
556 }
557
558 tp = entry = malloc(sz + usz);
559 if (!tp)
560 log_err(_("failed to allocate memory: %m"));
561
562 if (p != str) {
563 /* copy chars before \u */
564 memcpy(tp, str, p - str);
565 tp += p - str;
566 }
567 if (usz) {
568 /* copy username */
569 memcpy(tp, username, usz);
570 tp += usz;
571 }
572 if (*(p + 2))
573 /* copy chars after \u + \0 */
574 memcpy(tp, p + 2, sz - (p - str) - 1);
575 else
576 *tp = '\0';
577
578 p = tp;
579 str = entry;
580 free(old);
581 }
582
583 return entry ? entry : str;
584 }
585
586 static void login_options_to_argv(char *argv[], int *argc,
587 char *str, char *username)
588 {
589 char *p;
590 int i = *argc;
591
592 while (str && isspace(*str))
593 str++;
594 p = str;
595
596 while (p && *p && i < LOGIN_ARGV_MAX) {
597 if (isspace(*p)) {
598 *p = '\0';
599 while (isspace(*++p))
600 ;
601 if (*p) {
602 argv[i++] = replace_u(str, username);
603 str = p;
604 }
605 } else
606 p++;
607 }
608 if (str && *str && i < LOGIN_ARGV_MAX)
609 argv[i++] = replace_u(str, username);
610 *argc = i;
611 }
612
613 #define is_speed(str) (strlen((str)) == strspn((str), "0123456789,"))
614
615 /* Parse command-line arguments. */
616 static void parse_args(int argc, char **argv, struct options *op)
617 {
618 int c;
619
620 enum {
621 VERSION_OPTION = CHAR_MAX + 1,
622 NOHINTS_OPTION,
623 NOHOSTNAME_OPTION,
624 LONGHOSTNAME_OPTION,
625 HELP_OPTION,
626 ERASE_CHARS_OPTION,
627 KILL_CHARS_OPTION,
628 RELOAD_OPTION,
629 };
630 const struct option longopts[] = {
631 { "8bits", no_argument, 0, '8' },
632 { "autologin", required_argument, 0, 'a' },
633 { "noreset", no_argument, 0, 'c' },
634 { "chdir", required_argument, 0, 'C' },
635 { "delay", required_argument, 0, 'd' },
636 { "remote", no_argument, 0, 'E' },
637 { "issue-file", required_argument, 0, 'f' },
638 { "flow-control", no_argument, 0, 'h' },
639 { "host", required_argument, 0, 'H' },
640 { "noissue", no_argument, 0, 'i' },
641 { "init-string", required_argument, 0, 'I' },
642 { "noclear", no_argument, 0, 'J' },
643 { "login-program", required_argument, 0, 'l' },
644 { "local-line", optional_argument, 0, 'L' },
645 { "extract-baud", no_argument, 0, 'm' },
646 { "skip-login", no_argument, 0, 'n' },
647 { "nonewline", no_argument, 0, 'N' },
648 { "login-options", required_argument, 0, 'o' },
649 { "login-pause", no_argument, 0, 'p' },
650 { "nice", required_argument, 0, 'P' },
651 { "chroot", required_argument, 0, 'r' },
652 { "hangup", no_argument, 0, 'R' },
653 { "keep-baud", no_argument, 0, 's' },
654 { "timeout", required_argument, 0, 't' },
655 { "detect-case", no_argument, 0, 'U' },
656 { "wait-cr", no_argument, 0, 'w' },
657 { "nohints", no_argument, 0, NOHINTS_OPTION },
658 { "nohostname", no_argument, 0, NOHOSTNAME_OPTION },
659 { "long-hostname", no_argument, 0, LONGHOSTNAME_OPTION },
660 { "reload", no_argument, 0, RELOAD_OPTION },
661 { "version", no_argument, 0, VERSION_OPTION },
662 { "help", no_argument, 0, HELP_OPTION },
663 { "erase-chars", required_argument, 0, ERASE_CHARS_OPTION },
664 { "kill-chars", required_argument, 0, KILL_CHARS_OPTION },
665 { NULL, 0, 0, 0 }
666 };
667
668 while ((c = getopt_long(argc, argv,
669 "8a:cC:d:Ef:hH:iI:Jl:L::mnNo:pP:r:Rst:Uw", longopts,
670 NULL)) != -1) {
671 switch (c) {
672 case '8':
673 op->flags |= F_EIGHTBITS;
674 break;
675 case 'a':
676 op->autolog = optarg;
677 break;
678 case 'c':
679 op->flags |= F_KEEPCFLAGS;
680 break;
681 case 'C':
682 op->chdir = optarg;
683 break;
684 case 'd':
685 op->delay = strtou32_or_err(optarg, _("invalid delay argument"));
686 break;
687 case 'E':
688 op->flags |= F_REMOTE;
689 break;
690 case 'f':
691 op->flags |= F_CUSTISSUE;
692 op->issue = optarg;
693 break;
694 case 'h':
695 op->flags |= F_RTSCTS;
696 break;
697 case 'H':
698 fakehost = optarg;
699 break;
700 case 'i':
701 op->flags &= ~F_ISSUE;
702 break;
703 case 'I':
704 init_special_char(optarg, op);
705 op->flags |= F_INITSTRING;
706 break;
707 case 'J':
708 op->flags |= F_NOCLEAR;
709 break;
710 case 'l':
711 op->login = optarg;
712 break;
713 case 'L':
714 /* -L and -L=always have the same meaning */
715 op->clocal = CLOCAL_MODE_ALWAYS;
716 if (optarg) {
717 if (strcmp(optarg, "=always") == 0)
718 op->clocal = CLOCAL_MODE_ALWAYS;
719 else if (strcmp(optarg, "=never") == 0)
720 op->clocal = CLOCAL_MODE_NEVER;
721 else if (strcmp(optarg, "=auto") == 0)
722 op->clocal = CLOCAL_MODE_AUTO;
723 else
724 log_err(_("invalid argument of --local-line"));
725 }
726 break;
727 case 'm':
728 op->flags |= F_PARSE;
729 break;
730 case 'n':
731 op->flags |= F_NOPROMPT;
732 break;
733 case 'N':
734 op->flags |= F_NONL;
735 break;
736 case 'o':
737 op->logopt = optarg;
738 break;
739 case 'p':
740 op->flags |= F_LOGINPAUSE;
741 break;
742 case 'P':
743 op->nice = strtos32_or_err(optarg, _("invalid nice argument"));
744 break;
745 case 'r':
746 op->chroot = optarg;
747 break;
748 case 'R':
749 op->flags |= F_HANGUP;
750 break;
751 case 's':
752 op->flags |= F_KEEPSPEED;
753 break;
754 case 't':
755 op->timeout = strtou32_or_err(optarg, _("invalid timeout argument"));
756 break;
757 case 'U':
758 op->flags |= F_LCUC;
759 break;
760 case 'w':
761 op->flags |= F_WAITCRLF;
762 break;
763 case NOHINTS_OPTION:
764 op->flags |= F_NOHINTS;
765 break;
766 case NOHOSTNAME_OPTION:
767 op->flags |= F_NOHOSTNAME;
768 break;
769 case LONGHOSTNAME_OPTION:
770 op->flags |= F_LONGHNAME;
771 break;
772 case ERASE_CHARS_OPTION:
773 op->erasechars = optarg;
774 break;
775 case KILL_CHARS_OPTION:
776 op->killchars = optarg;
777 break;
778 case RELOAD_OPTION:
779 reload_agettys();
780 exit(EXIT_SUCCESS);
781 case VERSION_OPTION:
782 printf(UTIL_LINUX_VERSION);
783 exit(EXIT_SUCCESS);
784 case HELP_OPTION:
785 usage(stdout);
786 default:
787 usage(stderr);
788 }
789 }
790
791 debug("after getopt loop\n");
792
793 if (argc < optind + 1) {
794 log_warn(_("not enough arguments"));
795 usage(stderr);
796 }
797
798 /* Accept "tty", "baudrate tty", and "tty baudrate". */
799 if (is_speed(argv[optind])) {
800 /* Assume BSD style speed. */
801 parse_speeds(op, argv[optind++]);
802 if (argc < optind + 1) {
803 warn(_("not enough arguments"));
804 usage(stderr);
805 }
806 op->tty = argv[optind++];
807 } else {
808 op->tty = argv[optind++];
809 if (argc > optind) {
810 char *v = argv[optind];
811 if (is_speed(v)) {
812 parse_speeds(op, v);
813 optind++;
814 }
815 }
816 }
817
818 /* On virtual console remember the line which is used for */
819 if (strncmp(op->tty, "tty", 3) == 0 &&
820 strspn(op->tty + 3, "0123456789") == strlen(op->tty+3))
821 op->vcline = op->tty+3;
822
823 if (argc > optind && argv[optind])
824 op->term = argv[optind];
825
826 #ifdef DO_DEVFS_FIDDLING
827 /*
828 * Some devfs junk, following Goswin Brederlow:
829 * turn ttyS<n> into tts/<n>
830 * turn tty<n> into vc/<n>
831 * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=72241
832 */
833 if (op->tty && strlen(op->tty) < 90) {
834 char dev_name[100];
835 struct stat st;
836
837 if (strncmp(op->tty, "ttyS", 4) == 0) {
838 strcpy(dev_name, "/dev/");
839 strcat(dev_name, op->tty);
840 if (stat(dev_name, &st) < 0) {
841 strcpy(dev_name, "/dev/tts/");
842 strcat(dev_name, op->tty + 4);
843 if (stat(dev_name, &st) == 0) {
844 op->tty = strdup(dev_name + 5);
845 if (!op->tty)
846 log_err(_("failed to allocate memory: %m"));
847 }
848 }
849 } else if (strncmp(op->tty, "tty", 3) == 0) {
850 strcpy(dev_name, "/dev/");
851 strncat(dev_name, op->tty, 90);
852 if (stat(dev_name, &st) < 0) {
853 strcpy(dev_name, "/dev/vc/");
854 strcat(dev_name, op->tty + 3);
855 if (stat(dev_name, &st) == 0) {
856 op->tty = strdup(dev_name + 5);
857 if (!op->tty)
858 log_err(_("failed to allocate memory: %m"));
859 }
860 }
861 }
862 }
863 #endif /* DO_DEVFS_FIDDLING */
864
865 debug("exiting parseargs\n");
866 }
867
868 /* Parse alternate baud rates. */
869 static void parse_speeds(struct options *op, char *arg)
870 {
871 char *cp;
872 char *str = strdup(arg);
873
874 if (!str)
875 log_err(_("failed to allocate memory: %m"));
876
877 debug("entered parse_speeds:\n");
878 for (cp = strtok(str, ","); cp != NULL; cp = strtok((char *)0, ",")) {
879 if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0)
880 log_err(_("bad speed: %s"), cp);
881 if (op->numspeed >= MAX_SPEED)
882 log_err(_("too many alternate speeds"));
883 }
884 debug("exiting parsespeeds\n");
885 free(str);
886 }
887
888 #ifdef SYSV_STYLE
889
890 /* Update our utmp entry. */
891 static void update_utmp(struct options *op)
892 {
893 struct utmpx ut;
894 time_t t;
895 pid_t pid = getpid();
896 pid_t sid = getsid(0);
897 char *vcline = op->vcline;
898 char *line = op->tty;
899 struct utmpx *utp;
900
901 /*
902 * The utmp file holds miscellaneous information about things started by
903 * /sbin/init and other system-related events. Our purpose is to update
904 * the utmp entry for the current process, in particular the process type
905 * and the tty line we are listening to. Return successfully only if the
906 * utmp file can be opened for update, and if we are able to find our
907 * entry in the utmp file.
908 */
909 utmpxname(_PATH_UTMP);
910 setutxent();
911
912 /*
913 * Find my pid in utmp.
914 *
915 * FIXME: Earlier (when was that?) code here tested only utp->ut_type !=
916 * INIT_PROCESS, so maybe the >= here should be >.
917 *
918 * FIXME: The present code is taken from login.c, so if this is changed,
919 * maybe login has to be changed as well (is this true?).
920 */
921 while ((utp = getutxent()))
922 if (utp->ut_pid == pid
923 && utp->ut_type >= INIT_PROCESS
924 && utp->ut_type <= DEAD_PROCESS)
925 break;
926
927 if (utp) {
928 memcpy(&ut, utp, sizeof(ut));
929 } else {
930 /* Some inits do not initialize utmp. */
931 memset(&ut, 0, sizeof(ut));
932 if (vcline && *vcline)
933 /* Standard virtual console devices */
934 strncpy(ut.ut_id, vcline, sizeof(ut.ut_id));
935 else {
936 size_t len = strlen(line);
937 char * ptr;
938 if (len >= sizeof(ut.ut_id))
939 ptr = line + len - sizeof(ut.ut_id);
940 else
941 ptr = line;
942 strncpy(ut.ut_id, ptr, sizeof(ut.ut_id));
943 }
944 }
945
946 strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
947 strncpy(ut.ut_line, line, sizeof(ut.ut_line));
948 if (fakehost)
949 strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host));
950 time(&t);
951 ut.ut_tv.tv_sec = t;
952 ut.ut_type = LOGIN_PROCESS;
953 ut.ut_pid = pid;
954 ut.ut_session = sid;
955
956 pututxline(&ut);
957 endutxent();
958
959 updwtmpx(_PATH_WTMP, &ut);
960 }
961
962 #endif /* SYSV_STYLE */
963
964 /* Set up tty as stdin, stdout & stderr. */
965 static void open_tty(char *tty, struct termios *tp, struct options *op)
966 {
967 const pid_t pid = getpid();
968 int closed = 0;
969 #ifndef KDGKBMODE
970 int serial;
971 #endif
972
973 /* Set up new standard input, unless we are given an already opened port. */
974
975 if (strcmp(tty, "-") != 0) {
976 char buf[PATH_MAX+1];
977 struct group *gr = NULL;
978 struct stat st;
979 int fd, len;
980 pid_t tid;
981 gid_t gid = 0;
982
983 /* Use tty group if available */
984 if ((gr = getgrnam("tty")))
985 gid = gr->gr_gid;
986
987 len = snprintf(buf, sizeof(buf), "/dev/%s", tty);
988 if (len < 0 || (size_t)len >= sizeof(buf))
989 log_err(_("/dev/%s: cannot open as standard input: %m"), tty);
990
991 /* Open the tty as standard input. */
992 if ((fd = open(buf, O_RDWR|O_NOCTTY|O_NONBLOCK, 0)) < 0)
993 log_err(_("/dev/%s: cannot open as standard input: %m"), tty);
994
995 /*
996 * There is always a race between this reset and the call to
997 * vhangup() that s.o. can use to get access to your tty.
998 * Linux login(1) will change tty permissions. Use root owner and group
999 * with permission -rw------- for the period between getty and login.
1000 */
1001 if (fchown(fd, 0, gid) || fchmod(fd, (gid ? 0620 : 0600))) {
1002 if (errno == EROFS)
1003 log_warn("%s: %m", buf);
1004 else
1005 log_err("%s: %m", buf);
1006 }
1007
1008 /* Sanity checks... */
1009 if (fstat(fd, &st) < 0)
1010 log_err("%s: %m", buf);
1011 if ((st.st_mode & S_IFMT) != S_IFCHR)
1012 log_err(_("/dev/%s: not a character device"), tty);
1013 if (!isatty(fd))
1014 log_err(_("/dev/%s: not a tty"), tty);
1015
1016 if (((tid = tcgetsid(fd)) < 0) || (pid != tid)) {
1017 if (ioctl(fd, TIOCSCTTY, 1) == -1)
1018 log_warn(_("/dev/%s: cannot get controlling tty: %m"), tty);
1019 }
1020
1021 close(STDIN_FILENO);
1022 errno = 0;
1023
1024 if (op->flags & F_HANGUP) {
1025
1026 if (ioctl(fd, TIOCNOTTY))
1027 debug("TIOCNOTTY ioctl failed\n");
1028
1029 /*
1030 * Let's close all file descriptors before vhangup
1031 * https://lkml.org/lkml/2012/6/5/145
1032 */
1033 close(fd);
1034 close(STDOUT_FILENO);
1035 close(STDERR_FILENO);
1036 errno = 0;
1037 closed = 1;
1038
1039 if (vhangup())
1040 log_err(_("/dev/%s: vhangup() failed: %m"), tty);
1041 } else
1042 close(fd);
1043
1044 debug("open(2)\n");
1045 if (open(buf, O_RDWR|O_NOCTTY|O_NONBLOCK, 0) != 0)
1046 log_err(_("/dev/%s: cannot open as standard input: %m"), tty);
1047
1048 if (((tid = tcgetsid(STDIN_FILENO)) < 0) || (pid != tid)) {
1049 if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) == -1)
1050 log_warn(_("/dev/%s: cannot get controlling tty: %m"), tty);
1051 }
1052
1053 } else {
1054
1055 /*
1056 * Standard input should already be connected to an open port. Make
1057 * sure it is open for read/write.
1058 */
1059
1060 if ((fcntl(STDIN_FILENO, F_GETFL, 0) & O_RDWR) != O_RDWR)
1061 log_err(_("%s: not open for read/write"), tty);
1062
1063 }
1064
1065 if (tcsetpgrp(STDIN_FILENO, pid))
1066 log_warn(_("/dev/%s: cannot set process group: %m"), tty);
1067
1068 /* Get rid of the present outputs. */
1069 if (!closed) {
1070 close(STDOUT_FILENO);
1071 close(STDERR_FILENO);
1072 errno = 0;
1073 }
1074
1075 /* Set up standard output and standard error file descriptors. */
1076 debug("duping\n");
1077
1078 /* set up stdout and stderr */
1079 if (dup(STDIN_FILENO) != 1 || dup(STDIN_FILENO) != 2)
1080 log_err(_("%s: dup problem: %m"), tty);
1081
1082 /* make stdio unbuffered for slow modem lines */
1083 setvbuf(stdout, NULL, _IONBF, 0);
1084
1085 /*
1086 * The following ioctl will fail if stdin is not a tty, but also when
1087 * there is noise on the modem control lines. In the latter case, the
1088 * common course of action is (1) fix your cables (2) give the modem
1089 * more time to properly reset after hanging up.
1090 *
1091 * SunOS users can achieve (2) by patching the SunOS kernel variable
1092 * "zsadtrlow" to a larger value; 5 seconds seems to be a good value.
1093 * http://www.sunmanagers.org/archives/1993/0574.html
1094 */
1095 memset(tp, 0, sizeof(struct termios));
1096 if (tcgetattr(STDIN_FILENO, tp) < 0)
1097 log_err(_("%s: failed to get terminal attributes: %m"), tty);
1098
1099 #if defined (__s390__) || defined (__s390x__)
1100 if (!op->term) {
1101 /*
1102 * Special terminal on first serial line on a S/390(x) which
1103 * is due legacy reasons a block terminal of type 3270 or
1104 * higher. Whereas the second serial line on a S/390(x) is
1105 * a real character terminal which is compatible with VT220.
1106 */
1107 if (strcmp(op->tty, "ttyS0") == 0) /* linux/drivers/s390/char/con3215.c */
1108 op->term = DEFAULT_TTYS0;
1109 else if (strncmp(op->tty, "3270/tty", 8) == 0) /* linux/drivers/s390/char/con3270.c */
1110 op->term = DEFAULT_TTY32;
1111 else if (strcmp(op->tty, "ttyS1") == 0) /* linux/drivers/s390/char/sclp_vt220.c */
1112 op->term = DEFAULT_TTYS1;
1113 }
1114 #endif
1115
1116 #if defined(__FreeBSD_kernel__)
1117 login_tty (0);
1118 #endif
1119
1120 /*
1121 * Detect if this is a virtual console or serial/modem line.
1122 * In case of a virtual console the ioctl KDGKBMODE succeeds
1123 * whereas on other lines it will fails.
1124 */
1125 #ifdef KDGKBMODE
1126 if (ioctl(STDIN_FILENO, KDGKBMODE, &op->kbmode) == 0)
1127 #else
1128 if (ioctl(STDIN_FILENO, TIOCMGET, &serial) < 0 && (errno == EINVAL))
1129 #endif
1130 {
1131 op->flags |= F_VCONSOLE;
1132 if (!op->term)
1133 op->term = DEFAULT_VCTERM;
1134 } else {
1135 #ifdef K_RAW
1136 op->kbmode = K_RAW;
1137 #endif
1138 if (!op->term)
1139 op->term = DEFAULT_STERM;
1140 }
1141
1142 if (setenv("TERM", op->term, 1) != 0)
1143 log_err(_("failed to set the %s environment variable"), "TERM");
1144 }
1145
1146 /* Initialize termios settings. */
1147 static void termio_clear(int fd)
1148 {
1149 /*
1150 * Do not write a full reset (ESC c) because this destroys
1151 * the unicode mode again if the terminal was in unicode
1152 * mode. Also it clears the CONSOLE_MAGIC features which
1153 * are required for some languages/console-fonts.
1154 * Just put the cursor to the home position (ESC [ H),
1155 * erase everything below the cursor (ESC [ J), and set the
1156 * scrolling region to the full window (ESC [ r)
1157 */
1158 write_all(fd, "\033[r\033[H\033[J", 9);
1159 }
1160
1161 /* Initialize termios settings. */
1162 static void termio_init(struct options *op, struct termios *tp)
1163 {
1164 speed_t ispeed, ospeed;
1165 struct winsize ws;
1166 #ifdef USE_PLYMOUTH_SUPPORT
1167 struct termios lock;
1168 int i = (plymouth_command(MAGIC_PING) == 0) ? PLYMOUTH_TERMIOS_FLAGS_DELAY : 0;
1169 if (i)
1170 plymouth_command(MAGIC_QUIT);
1171 while (i-- > 0) {
1172 /*
1173 * Even with TTYReset=no it seems with systemd or plymouth
1174 * the termios flags become changed from under the first
1175 * agetty on a serial system console as the flags are locked.
1176 */
1177 memset(&lock, 0, sizeof(struct termios));
1178 if (ioctl(STDIN_FILENO, TIOCGLCKTRMIOS, &lock) < 0)
1179 break;
1180 if (!lock.c_iflag && !lock.c_oflag && !lock.c_cflag && !lock.c_lflag)
1181 break;
1182 debug("termios locked\n");
1183 sleep(1);
1184 }
1185 memset(&lock, 0, sizeof(struct termios));
1186 ioctl(STDIN_FILENO, TIOCSLCKTRMIOS, &lock);
1187 #endif
1188
1189 if (op->flags & F_VCONSOLE) {
1190 #if defined(IUTF8) && defined(KDGKBMODE)
1191 switch(op->kbmode) {
1192 case K_UNICODE:
1193 setlocale(LC_CTYPE, "C.UTF-8");
1194 op->flags |= F_UTF8;
1195 break;
1196 case K_RAW:
1197 case K_MEDIUMRAW:
1198 case K_XLATE:
1199 default:
1200 setlocale(LC_CTYPE, "POSIX");
1201 op->flags &= ~F_UTF8;
1202 break;
1203 }
1204 #else
1205 setlocale(LC_CTYPE, "POSIX");
1206 op->flags &= ~F_UTF8;
1207 #endif
1208 reset_vc(op, tp);
1209
1210 if ((tp->c_cflag & (CS8|PARODD|PARENB)) == CS8)
1211 op->flags |= F_EIGHTBITS;
1212
1213 if ((op->flags & F_NOCLEAR) == 0)
1214 termio_clear(STDOUT_FILENO);
1215 return;
1216 }
1217
1218 /*
1219 * Serial line
1220 */
1221
1222 if (op->flags & F_KEEPSPEED || !op->numspeed) {
1223 /* Save the original setting. */
1224 ispeed = cfgetispeed(tp);
1225 ospeed = cfgetospeed(tp);
1226
1227 if (!ispeed) ispeed = TTYDEF_SPEED;
1228 if (!ospeed) ospeed = TTYDEF_SPEED;
1229
1230 } else {
1231 ospeed = ispeed = op->speeds[FIRST_SPEED];
1232 }
1233
1234 /*
1235 * Initial termios settings: 8-bit characters, raw-mode, blocking i/o.
1236 * Special characters are set after we have read the login name; all
1237 * reads will be done in raw mode anyway. Errors will be dealt with
1238 * later on.
1239 */
1240
1241 #ifdef IUTF8
1242 tp->c_iflag = tp->c_iflag & IUTF8;
1243 if (tp->c_iflag & IUTF8)
1244 op->flags |= F_UTF8;
1245 #else
1246 tp->c_iflag = 0;
1247 #endif
1248 tp->c_lflag = 0;
1249 tp->c_oflag &= OPOST | ONLCR;
1250
1251 if ((op->flags & F_KEEPCFLAGS) == 0)
1252 tp->c_cflag = CS8 | HUPCL | CREAD | (tp->c_cflag & CLOCAL);
1253
1254 /*
1255 * Note that the speed is stored in the c_cflag termios field, so we have
1256 * set the speed always when the cflag is reset.
1257 */
1258 cfsetispeed(tp, ispeed);
1259 cfsetospeed(tp, ospeed);
1260
1261 /* The default is to follow setting from kernel, but it's possible
1262 * to explicitly remove/add CLOCAL flag by -L[=<mode>]*/
1263 switch (op->clocal) {
1264 case CLOCAL_MODE_ALWAYS:
1265 tp->c_cflag |= CLOCAL; /* -L or -L=always */
1266 break;
1267 case CLOCAL_MODE_NEVER:
1268 tp->c_cflag &= ~CLOCAL; /* -L=never */
1269 break;
1270 case CLOCAL_MODE_AUTO: /* -L=auto */
1271 break;
1272 }
1273
1274 #ifdef HAVE_STRUCT_TERMIOS_C_LINE
1275 tp->c_line = 0;
1276 #endif
1277 tp->c_cc[VMIN] = 1;
1278 tp->c_cc[VTIME] = 0;
1279
1280 /* Check for terminal size and if not found set default */
1281 if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) {
1282 int set = 0;
1283 if (ws.ws_row == 0) {
1284 ws.ws_row = 24;
1285 set++;
1286 }
1287 if (ws.ws_col == 0) {
1288 ws.ws_col = 80;
1289 set++;
1290 }
1291 if (ioctl(STDIN_FILENO, TIOCSWINSZ, &ws))
1292 debug("TIOCSWINSZ ioctl failed\n");
1293 }
1294
1295 /* Optionally enable hardware flow control. */
1296 #ifdef CRTSCTS
1297 if (op->flags & F_RTSCTS)
1298 tp->c_cflag |= CRTSCTS;
1299 #endif
1300 /* Flush input and output queues, important for modems! */
1301 tcflush(STDIN_FILENO, TCIOFLUSH);
1302
1303 if (tcsetattr(STDIN_FILENO, TCSANOW, tp))
1304 log_warn(_("setting terminal attributes failed: %m"));
1305
1306 /* Go to blocking input even in local mode. */
1307 fcntl(STDIN_FILENO, F_SETFL,
1308 fcntl(STDIN_FILENO, F_GETFL, 0) & ~O_NONBLOCK);
1309
1310 debug("term_io 2\n");
1311 }
1312
1313 /* Reset virtual console on stdin to its defaults */
1314 static void reset_vc(const struct options *op, struct termios *tp)
1315 {
1316 int fl = 0;
1317
1318 fl |= (op->flags & F_KEEPCFLAGS) == 0 ? 0 : UL_TTY_KEEPCFLAGS;
1319 fl |= (op->flags & F_UTF8) == 0 ? 0 : UL_TTY_UTF8;
1320
1321 reset_virtual_console(tp, fl);
1322
1323 if (tcsetattr(STDIN_FILENO, TCSADRAIN, tp))
1324 log_warn(_("setting terminal attributes failed: %m"));
1325
1326 /* Go to blocking input even in local mode. */
1327 fcntl(STDIN_FILENO, F_SETFL,
1328 fcntl(STDIN_FILENO, F_GETFL, 0) & ~O_NONBLOCK);
1329 }
1330
1331 /* Extract baud rate from modem status message. */
1332 static void auto_baud(struct termios *tp)
1333 {
1334 speed_t speed;
1335 int vmin;
1336 unsigned iflag;
1337 char buf[BUFSIZ];
1338 char *bp;
1339 int nread;
1340
1341 /*
1342 * This works only if the modem produces its status code AFTER raising
1343 * the DCD line, and if the computer is fast enough to set the proper
1344 * baud rate before the message has gone by. We expect a message of the
1345 * following format:
1346 *
1347 * <junk><number><junk>
1348 *
1349 * The number is interpreted as the baud rate of the incoming call. If the
1350 * modem does not tell us the baud rate within one second, we will keep
1351 * using the current baud rate. It is advisable to enable BREAK
1352 * processing (comma-separated list of baud rates) if the processing of
1353 * modem status messages is enabled.
1354 */
1355
1356 /*
1357 * Use 7-bit characters, don't block if input queue is empty. Errors will
1358 * be dealt with later on.
1359 */
1360 iflag = tp->c_iflag;
1361 /* Enable 8th-bit stripping. */
1362 tp->c_iflag |= ISTRIP;
1363 vmin = tp->c_cc[VMIN];
1364 /* Do not block when queue is empty. */
1365 tp->c_cc[VMIN] = 0;
1366 tcsetattr(STDIN_FILENO, TCSANOW, tp);
1367
1368 /*
1369 * Wait for a while, then read everything the modem has said so far and
1370 * try to extract the speed of the dial-in call.
1371 */
1372 sleep(1);
1373 if ((nread = read(STDIN_FILENO, buf, sizeof(buf) - 1)) > 0) {
1374 buf[nread] = '\0';
1375 for (bp = buf; bp < buf + nread; bp++)
1376 if (isascii(*bp) && isdigit(*bp)) {
1377 if ((speed = bcode(bp))) {
1378 cfsetispeed(tp, speed);
1379 cfsetospeed(tp, speed);
1380 }
1381 break;
1382 }
1383 }
1384
1385 /* Restore terminal settings. Errors will be dealt with later on. */
1386 tp->c_iflag = iflag;
1387 tp->c_cc[VMIN] = vmin;
1388 tcsetattr(STDIN_FILENO, TCSANOW, tp);
1389 }
1390
1391 static char *xgethostname(void)
1392 {
1393 char *name;
1394 size_t sz = get_hostname_max() + 1;
1395
1396 name = malloc(sizeof(char) * sz);
1397 if (!name)
1398 log_err(_("failed to allocate memory: %m"));
1399
1400 if (gethostname(name, sz) != 0) {
1401 free(name);
1402 return NULL;
1403 }
1404 name[sz - 1] = '\0';
1405 return name;
1406 }
1407
1408 static char *xgetdomainname(void)
1409 {
1410 #ifdef HAVE_GETDOMAINNAME
1411 char *name;
1412 const size_t sz = get_hostname_max() + 1;
1413
1414 name = malloc(sizeof(char) * sz);
1415 if (!name)
1416 log_err(_("failed to allocate memory: %m"));
1417
1418 if (getdomainname(name, sz) != 0) {
1419 free(name);
1420 return NULL;
1421 }
1422 name[sz - 1] = '\0';
1423 return name;
1424 #else
1425 return NULL;
1426 #endif
1427 }
1428
1429 static char *read_os_release(struct options *op, const char *varname)
1430 {
1431 int fd = -1;
1432 struct stat st;
1433 size_t varsz = strlen(varname);
1434 char *p, *buf = NULL, *ret = NULL;
1435
1436 /* read the file only once */
1437 if (!op->osrelease) {
1438 fd = open(_PATH_OS_RELEASE_ETC, O_RDONLY);
1439 if (fd == -1) {
1440 fd = open(_PATH_OS_RELEASE_USR, O_RDONLY);
1441 if (fd == -1) {
1442 log_warn(_("cannot open os-release file"));
1443 return NULL;
1444 }
1445 }
1446
1447 if (fstat(fd, &st) < 0 || st.st_size > 4 * 1024 * 1024)
1448 goto done;
1449
1450 op->osrelease = malloc(st.st_size + 1);
1451 if (!op->osrelease)
1452 log_err(_("failed to allocate memory: %m"));
1453 if (read_all(fd, op->osrelease, st.st_size) != (ssize_t) st.st_size) {
1454 free(op->osrelease);
1455 op->osrelease = NULL;
1456 goto done;
1457 }
1458 op->osrelease[st.st_size] = 0;
1459 }
1460 buf = strdup(op->osrelease);
1461 if (!buf)
1462 log_err(_("failed to allocate memory: %m"));
1463 p = buf;
1464
1465 for (;;) {
1466 char *eol, *eon;
1467
1468 p += strspn(p, "\n\r");
1469 p += strspn(p, " \t\n\r");
1470 if (!*p)
1471 break;
1472 if (strspn(p, "#;\n") != 0) {
1473 p += strcspn(p, "\n\r");
1474 continue;
1475 }
1476 if (strncmp(p, varname, varsz) != 0) {
1477 p += strcspn(p, "\n\r");
1478 continue;
1479 }
1480 p += varsz;
1481 p += strspn(p, " \t\n\r=\"");
1482 eol = p + strcspn(p, "\n\r");
1483 *eol = '\0';
1484 eon = eol-1;
1485 while (eon > p) {
1486 if (*eon == '\t' || *eon == ' ') {
1487 eon--;
1488 continue;
1489 }
1490 if (*eon == '"') {
1491 *eon = '\0';
1492 break;
1493 }
1494 break;
1495 }
1496 free(ret);
1497 ret = strdup(p);
1498 if (!ret)
1499 log_err(_("failed to allocate memory: %m"));
1500 p = eol + 1;
1501 }
1502 done:
1503 free(buf);
1504 if (fd >= 0)
1505 close(fd);
1506 return ret;
1507 }
1508
1509 #ifdef AGETTY_RELOAD
1510 static void open_netlink(void)
1511 {
1512 struct sockaddr_nl addr = { 0, };
1513 int sock;
1514
1515 if (netlink_fd != AGETTY_RELOAD_FDNONE)
1516 return;
1517
1518 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1519 if (sock >= 0) {
1520 addr.nl_family = AF_NETLINK;
1521 addr.nl_pid = getpid();
1522 addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
1523 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
1524 close(sock);
1525 else
1526 netlink_fd = sock;
1527 }
1528 }
1529
1530 static int process_netlink_msg(int *changed)
1531 {
1532 char buf[4096];
1533 struct sockaddr_nl snl;
1534 struct nlmsghdr *h;
1535 int rc;
1536
1537 struct iovec iov = {
1538 .iov_base = buf,
1539 .iov_len = sizeof(buf)
1540 };
1541 struct msghdr msg = {
1542 .msg_name = &snl,
1543 .msg_namelen = sizeof(snl),
1544 .msg_iov = &iov,
1545 .msg_iovlen = 1,
1546 .msg_control = NULL,
1547 .msg_controllen = 0,
1548 .msg_flags = 0
1549 };
1550
1551 rc = recvmsg(netlink_fd, &msg, MSG_DONTWAIT);
1552 if (rc < 0) {
1553 if (errno == EWOULDBLOCK || errno == EAGAIN)
1554 return 0;
1555
1556 /* Failure, just stop listening for changes */
1557 close(netlink_fd);
1558 netlink_fd = AGETTY_RELOAD_FDNONE;
1559 return 0;
1560 }
1561
1562 for (h = (struct nlmsghdr *)buf; NLMSG_OK(h, (unsigned int)rc); h = NLMSG_NEXT(h, rc)) {
1563 if (h->nlmsg_type == NLMSG_DONE ||
1564 h->nlmsg_type == NLMSG_ERROR) {
1565 close(netlink_fd);
1566 netlink_fd = AGETTY_RELOAD_FDNONE;
1567 return 0;
1568 }
1569
1570 *changed = 1;
1571 break;
1572 }
1573
1574 return 1;
1575 }
1576
1577 static int process_netlink(void)
1578 {
1579 int changed = 0;
1580 while (process_netlink_msg(&changed));
1581 return changed;
1582 }
1583
1584 static int wait_for_term_input(int fd)
1585 {
1586 char buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
1587 struct termios orig, nonc;
1588 fd_set rfds;
1589 int count, i;
1590
1591 /* Our aim here is to fall through if something fails
1592 * and not be stuck waiting. On failure assume we have input */
1593
1594 if (tcgetattr(fd, &orig) != 0)
1595 return 1;
1596
1597 memcpy(&nonc, &orig, sizeof (nonc));
1598 nonc.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHOKE);
1599 nonc.c_cc[VMIN] = 1;
1600 nonc.c_cc[VTIME] = 0;
1601
1602 if (tcsetattr(fd, TCSANOW, &nonc) != 0)
1603 return 1;
1604
1605 if (inotify_fd == AGETTY_RELOAD_FDNONE) {
1606 /* make sure the reload trigger file exists */
1607 int reload_fd = open(AGETTY_RELOAD_FILENAME,
1608 O_CREAT|O_CLOEXEC|O_RDONLY,
1609 S_IRUSR|S_IWUSR);
1610
1611 /* initialize reload trigger inotify stuff */
1612 if (reload_fd >= 0) {
1613 inotify_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
1614 if (inotify_fd > 0)
1615 inotify_add_watch(inotify_fd, AGETTY_RELOAD_FILENAME,
1616 IN_ATTRIB | IN_MODIFY);
1617
1618 close(reload_fd);
1619 } else
1620 log_warn(_("failed to create reload file: %s: %m"),
1621 AGETTY_RELOAD_FILENAME);
1622 }
1623
1624 while (1) {
1625 int nfds = fd;
1626
1627 FD_ZERO(&rfds);
1628 FD_SET(fd, &rfds);
1629
1630 if (inotify_fd >= 0) {
1631 FD_SET(inotify_fd, &rfds);
1632 nfds = max(nfds, inotify_fd);
1633 }
1634 if (netlink_fd >= 0) {
1635 FD_SET(netlink_fd, &rfds);
1636 nfds = max(nfds, netlink_fd);
1637 }
1638
1639 /* If waiting fails, just fall through, presumably reading input will fail */
1640 if (select(nfds + 1, &rfds, NULL, NULL, NULL) < 0)
1641 return 1;
1642
1643 if (FD_ISSET(fd, &rfds)) {
1644 count = read(fd, buffer, sizeof (buffer));
1645
1646 tcsetattr(fd, TCSANOW, &orig);
1647
1648 /* Reinject the bytes we read back into the buffer, usually just one byte */
1649 for (i = 0; i < count; i++)
1650 ioctl(fd, TIOCSTI, buffer + i);
1651
1652 /* Have terminal input */
1653 return 1;
1654
1655 } else if (netlink_fd >= 0 && FD_ISSET(netlink_fd, &rfds)) {
1656 if (!process_netlink())
1657 continue;
1658
1659 /* Just drain the inotify buffer */
1660 } else if (inotify_fd >= 0 && FD_ISSET(inotify_fd, &rfds)) {
1661 while (read(inotify_fd, buffer, sizeof (buffer)) > 0);
1662 }
1663
1664 tcsetattr(fd, TCSANOW, &orig);
1665
1666 /* Need to reprompt */
1667 return 0;
1668 }
1669 }
1670 #endif /* AGETTY_RELOAD */
1671 static void print_issue_file(struct options *op, struct termios *tp)
1672 {
1673 #ifdef ISSUE
1674 FILE *fd;
1675 #endif
1676 if ((op->flags & F_NONL) == 0) {
1677 /* Issue not in use, start with a new line. */
1678 write_all(STDOUT_FILENO, "\r\n", 2);
1679 }
1680
1681 #ifdef ISSUE
1682 if ((op->flags & F_ISSUE) && (fd = fopen(op->issue, "r"))) {
1683 int c, oflag = tp->c_oflag; /* Save current setting. */
1684
1685 if ((op->flags & F_VCONSOLE) == 0) {
1686 /* Map new line in output to carriage return & new line. */
1687 tp->c_oflag |= (ONLCR | OPOST);
1688 tcsetattr(STDIN_FILENO, TCSADRAIN, tp);
1689 }
1690
1691 while ((c = getc(fd)) != EOF) {
1692 if (c == '\\')
1693 output_special_char(getc(fd), op, tp, fd);
1694 else
1695 putchar(c);
1696 }
1697 fflush(stdout);
1698
1699 if ((op->flags & F_VCONSOLE) == 0) {
1700 /* Restore settings. */
1701 tp->c_oflag = oflag;
1702 /* Wait till output is gone. */
1703 tcsetattr(STDIN_FILENO, TCSADRAIN, tp);
1704 }
1705 fclose(fd);
1706 }
1707 #endif /* ISSUE */
1708 }
1709
1710 /* Show login prompt, optionally preceded by /etc/issue contents. */
1711 static void do_prompt(struct options *op, struct termios *tp)
1712 {
1713 #ifdef AGETTY_RELOAD
1714 again:
1715 #endif
1716 print_issue_file(op, tp);
1717
1718 if (op->flags & F_LOGINPAUSE) {
1719 puts(_("[press ENTER to login]"));
1720 #ifdef AGETTY_RELOAD
1721 if (!wait_for_term_input(STDIN_FILENO)) {
1722 /* reload issue */
1723 if (op->flags & F_VCONSOLE)
1724 termio_clear(STDOUT_FILENO);
1725 goto again;
1726 }
1727 #endif
1728 getc(stdin);
1729 }
1730 #ifdef KDGKBLED
1731 if (!(op->flags & F_NOHINTS) && !op->autolog &&
1732 (op->flags & F_VCONSOLE)) {
1733 int kb = 0;
1734
1735 if (ioctl(STDIN_FILENO, KDGKBLED, &kb) == 0) {
1736 char hint[256] = { '\0' };
1737 int nl = 0;
1738
1739 if (access(_PATH_NUMLOCK_ON, F_OK) == 0)
1740 nl = 1;
1741
1742 if (nl && (kb & 0x02) == 0)
1743 append(hint, sizeof(hint), NULL, _("Num Lock off"));
1744
1745 else if (nl == 0 && (kb & 2) && (kb & 0x20) == 0)
1746 append(hint, sizeof(hint), NULL, _("Num Lock on"));
1747
1748 if ((kb & 0x04) && (kb & 0x40) == 0)
1749 append(hint, sizeof(hint), ", ", _("Caps Lock on"));
1750
1751 if ((kb & 0x01) && (kb & 0x10) == 0)
1752 append(hint, sizeof(hint), ", ", _("Scroll Lock on"));
1753
1754 if (*hint)
1755 printf(_("Hint: %s\n\n"), hint);
1756 }
1757 }
1758 #endif /* KDGKBLED */
1759 if ((op->flags & F_NOHOSTNAME) == 0) {
1760 char *hn = xgethostname();
1761
1762 if (hn) {
1763 char *dot = strchr(hn, '.');
1764 char *cn = hn;
1765 struct addrinfo *res = NULL;
1766
1767 if ((op->flags & F_LONGHNAME) == 0) {
1768 if (dot)
1769 *dot = '\0';
1770
1771 } else if (dot == NULL) {
1772 struct addrinfo hints;
1773
1774 memset(&hints, 0, sizeof(hints));
1775 hints.ai_flags = AI_CANONNAME;
1776
1777 if (!getaddrinfo(hn, NULL, &hints, &res)
1778 && res && res->ai_canonname)
1779 cn = res->ai_canonname;
1780 }
1781
1782 write_all(STDOUT_FILENO, cn, strlen(cn));
1783 write_all(STDOUT_FILENO, " ", 1);
1784
1785 if (res)
1786 freeaddrinfo(res);
1787 free(hn);
1788 }
1789 }
1790 if (!op->autolog) {
1791 /* Always show login prompt. */
1792 write_all(STDOUT_FILENO, LOGIN, sizeof(LOGIN) - 1);
1793 }
1794 }
1795
1796 /* Select next baud rate. */
1797 static void next_speed(struct options *op, struct termios *tp)
1798 {
1799 static int baud_index = -1;
1800
1801 if (baud_index == -1)
1802 /*
1803 * If the F_KEEPSPEED flags is set then the FIRST_SPEED is not
1804 * tested yet (see termio_init()).
1805 */
1806 baud_index =
1807 (op->flags & F_KEEPSPEED) ? FIRST_SPEED : 1 % op->numspeed;
1808 else
1809 baud_index = (baud_index + 1) % op->numspeed;
1810
1811 cfsetispeed(tp, op->speeds[baud_index]);
1812 cfsetospeed(tp, op->speeds[baud_index]);
1813 tcsetattr(STDIN_FILENO, TCSANOW, tp);
1814 }
1815
1816 /* Get user name, establish parity, speed, erase, kill & eol. */
1817 static char *get_logname(struct options *op, struct termios *tp, struct chardata *cp)
1818 {
1819 static char logname[BUFSIZ];
1820 char *bp;
1821 char c; /* input character, full eight bits */
1822 char ascval; /* low 7 bits of input character */
1823 int eightbit;
1824 static char *erase[] = { /* backspace-space-backspace */
1825 "\010\040\010", /* space parity */
1826 "\010\040\010", /* odd parity */
1827 "\210\240\210", /* even parity */
1828 "\210\240\210", /* no parity */
1829 };
1830
1831 /* Initialize kill, erase, parity etc. (also after switching speeds). */
1832 INIT_CHARDATA(cp);
1833
1834 /*
1835 * Flush pending input (especially important after parsing or switching
1836 * the baud rate).
1837 */
1838 if ((op->flags & F_VCONSOLE) == 0)
1839 sleep(1);
1840 tcflush(STDIN_FILENO, TCIFLUSH);
1841
1842 eightbit = (op->flags & F_EIGHTBITS);
1843 bp = logname;
1844 *bp = '\0';
1845
1846 while (*logname == '\0') {
1847
1848 /* Write issue file and prompt */
1849 do_prompt(op, tp);
1850
1851 #ifdef AGETTY_RELOAD
1852 /* If asked to reprompt *before* terminal input arrives, then do so */
1853 if (!wait_for_term_input(STDIN_FILENO)) {
1854 if (op->flags & F_VCONSOLE)
1855 termio_clear(STDOUT_FILENO);
1856 continue;
1857 }
1858 #endif
1859 cp->eol = '\0';
1860
1861 /* Read name, watch for break and end-of-line. */
1862 while (cp->eol == '\0') {
1863
1864 char key;
1865
1866 if (read(STDIN_FILENO, &c, 1) < 1) {
1867
1868 /* The terminal could be open with O_NONBLOCK when
1869 * -L (force CLOCAL) is specified... */
1870 if (errno == EINTR || errno == EAGAIN) {
1871 xusleep(250000);
1872 continue;
1873 }
1874 switch (errno) {
1875 case 0:
1876 case EIO:
1877 case ESRCH:
1878 case EINVAL:
1879 case ENOENT:
1880 break;
1881 default:
1882 log_err(_("%s: read: %m"), op->tty);
1883 }
1884 }
1885
1886 /* Do parity bit handling. */
1887 if (eightbit)
1888 ascval = c;
1889 else if (c != (ascval = (c & 0177))) {
1890 uint32_t bits; /* # of "1" bits per character */
1891 uint32_t mask; /* mask with 1 bit up */
1892 for (bits = 1, mask = 1; mask & 0177; mask <<= 1) {
1893 if (mask & ascval)
1894 bits++;
1895 }
1896 cp->parity |= ((bits & 1) ? 1 : 2);
1897 }
1898
1899 if (op->killchars && strchr(op->killchars, ascval))
1900 key = CTL('U');
1901 else if (op->erasechars && strchr(op->erasechars, ascval))
1902 key = DEL;
1903 else
1904 key = ascval;
1905
1906 /* Do erase, kill and end-of-line processing. */
1907 switch (key) {
1908 case 0:
1909 *bp = 0;
1910 if (op->numspeed > 1)
1911 return NULL;
1912 break;
1913 case CR:
1914 case NL:
1915 *bp = 0; /* terminate logname */
1916 cp->eol = ascval; /* set end-of-line char */
1917 break;
1918 case BS:
1919 case DEL:
1920 cp->erase = ascval; /* set erase character */
1921 if (bp > logname) {
1922 if ((tp->c_lflag & ECHO) == 0)
1923 write_all(1, erase[cp->parity], 3);
1924 bp--;
1925 }
1926 break;
1927 case CTL('U'):
1928 cp->kill = ascval; /* set kill character */
1929 while (bp > logname) {
1930 if ((tp->c_lflag & ECHO) == 0)
1931 write_all(1, erase[cp->parity], 3);
1932 bp--;
1933 }
1934 break;
1935 case CTL('D'):
1936 exit(EXIT_SUCCESS);
1937 default:
1938 if (!isascii(ascval) || !isprint(ascval))
1939 break;
1940 if ((size_t)(bp - logname) >= sizeof(logname) - 1)
1941 log_err(_("%s: input overrun"), op->tty);
1942 if ((tp->c_lflag & ECHO) == 0)
1943 write_all(1, &c, 1); /* echo the character */
1944 *bp++ = ascval; /* and store it */
1945 break;
1946 }
1947 }
1948 }
1949 #ifdef HAVE_WIDECHAR
1950 if ((op->flags & (F_EIGHTBITS|F_UTF8)) == (F_EIGHTBITS|F_UTF8)) {
1951 /* Check out UTF-8 multibyte characters */
1952 ssize_t len;
1953 wchar_t *wcs, *wcp;
1954
1955 len = mbstowcs((wchar_t *)0, logname, 0);
1956 if (len < 0)
1957 log_err(_("%s: invalid character conversion for login name"), op->tty);
1958
1959 wcs = malloc((len + 1) * sizeof(wchar_t));
1960 if (!wcs)
1961 log_err(_("failed to allocate memory: %m"));
1962
1963 len = mbstowcs(wcs, logname, len + 1);
1964 if (len < 0)
1965 log_err(_("%s: invalid character conversion for login name"), op->tty);
1966
1967 wcp = wcs;
1968 while (*wcp) {
1969 const wint_t wc = *wcp++;
1970 if (!iswprint(wc))
1971 log_err(_("%s: invalid character 0x%x in login name"), op->tty, wc);
1972 }
1973 free(wcs);
1974 } else
1975 #endif
1976 if ((op->flags & F_LCUC) && (cp->capslock = caps_lock(logname))) {
1977
1978 /* Handle names with upper case and no lower case. */
1979 for (bp = logname; *bp; bp++)
1980 if (isupper(*bp))
1981 *bp = tolower(*bp); /* map name to lower case */
1982 }
1983
1984 return logname;
1985 }
1986
1987 /* Set the final tty mode bits. */
1988 static void termio_final(struct options *op, struct termios *tp, struct chardata *cp)
1989 {
1990 /* General terminal-independent stuff. */
1991
1992 /* 2-way flow control */
1993 tp->c_iflag |= IXON | IXOFF;
1994 tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE;
1995 /* no longer| ECHOCTL | ECHOPRT */
1996 tp->c_oflag |= OPOST;
1997 /* tp->c_cflag = 0; */
1998 tp->c_cc[VINTR] = DEF_INTR;
1999 tp->c_cc[VQUIT] = DEF_QUIT;
2000 tp->c_cc[VEOF] = DEF_EOF;
2001 tp->c_cc[VEOL] = DEF_EOL;
2002 #ifdef __linux__
2003 tp->c_cc[VSWTC] = DEF_SWITCH;
2004 #elif defined(VSWTCH)
2005 tp->c_cc[VSWTCH] = DEF_SWITCH;
2006 #endif /* __linux__ */
2007
2008 /* Account for special characters seen in input. */
2009 if (cp->eol == CR) {
2010 tp->c_iflag |= ICRNL;
2011 tp->c_oflag |= ONLCR;
2012 }
2013 tp->c_cc[VERASE] = cp->erase;
2014 tp->c_cc[VKILL] = cp->kill;
2015
2016 /* Account for the presence or absence of parity bits in input. */
2017 switch (cp->parity) {
2018 case 0:
2019 /* space (always 0) parity */
2020 break;
2021 case 1:
2022 /* odd parity */
2023 tp->c_cflag |= PARODD;
2024 /* do not break */
2025 case 2:
2026 /* even parity */
2027 tp->c_cflag |= PARENB;
2028 tp->c_iflag |= INPCK | ISTRIP;
2029 /* do not break */
2030 case (1 | 2):
2031 /* no parity bit */
2032 tp->c_cflag &= ~CSIZE;
2033 tp->c_cflag |= CS7;
2034 break;
2035 }
2036 /* Account for upper case without lower case. */
2037 if (cp->capslock) {
2038 #ifdef IUCLC
2039 tp->c_iflag |= IUCLC;
2040 #endif
2041 #ifdef XCASE
2042 tp->c_lflag |= XCASE;
2043 #endif
2044 #ifdef OLCUC
2045 tp->c_oflag |= OLCUC;
2046 #endif
2047 }
2048 /* Optionally enable hardware flow control. */
2049 #ifdef CRTSCTS
2050 if (op->flags & F_RTSCTS)
2051 tp->c_cflag |= CRTSCTS;
2052 #endif
2053
2054 /* Finally, make the new settings effective. */
2055 if (tcsetattr(STDIN_FILENO, TCSANOW, tp) < 0)
2056 log_err(_("%s: failed to set terminal attributes: %m"), op->tty);
2057 }
2058
2059 /*
2060 * String contains upper case without lower case.
2061 * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=52940
2062 * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=156242
2063 */
2064 static int caps_lock(char *s)
2065 {
2066 int capslock;
2067
2068 for (capslock = 0; *s; s++) {
2069 if (islower(*s))
2070 return EXIT_SUCCESS;
2071 if (capslock == 0)
2072 capslock = isupper(*s);
2073 }
2074 return capslock;
2075 }
2076
2077 /* Convert speed string to speed code; return 0 on failure. */
2078 static speed_t bcode(char *s)
2079 {
2080 const struct Speedtab *sp;
2081 long speed = atol(s);
2082
2083 for (sp = speedtab; sp->speed; sp++)
2084 if (sp->speed == speed)
2085 return sp->code;
2086 return 0;
2087 }
2088
2089 static void __attribute__ ((__noreturn__)) usage(FILE *out)
2090 {
2091 fputs(USAGE_HEADER, out);
2092 fprintf(out, _(" %1$s [options] <line> [<baud_rate>,...] [<termtype>]\n"
2093 " %1$s [options] <baud_rate>,... <line> [<termtype>]\n"), program_invocation_short_name);
2094
2095 fputs(USAGE_SEPARATOR, out);
2096 fputs(_("Open a terminal and set its mode.\n"), out);
2097
2098 fputs(USAGE_OPTIONS, out);
2099 fputs(_(" -8, --8bits assume 8-bit tty\n"), out);
2100 fputs(_(" -a, --autologin <user> login the specified user automatically\n"), out);
2101 fputs(_(" -c, --noreset do not reset control mode\n"), out);
2102 fputs(_(" -E, --remote use -r <hostname> for login(1)\n"), out);
2103 fputs(_(" -f, --issue-file <file> display issue file\n"), out);
2104 fputs(_(" -h, --flow-control enable hardware flow control\n"), out);
2105 fputs(_(" -H, --host <hostname> specify login host\n"), out);
2106 fputs(_(" -i, --noissue do not display issue file\n"), out);
2107 fputs(_(" -I, --init-string <string> set init string\n"), out);
2108 fputs(_(" -J --noclear do not clear the screen before prompt\n"), out);
2109 fputs(_(" -l, --login-program <file> specify login program\n"), out);
2110 fputs(_(" -L, --local-line[=<mode>] control the local line flag\n"), out);
2111 fputs(_(" -m, --extract-baud extract baud rate during connect\n"), out);
2112 fputs(_(" -n, --skip-login do not prompt for login\n"), out);
2113 fputs(_(" -N --nonewline do not print a newline before issue\n"), out);
2114 fputs(_(" -o, --login-options <opts> options that are passed to login\n"), out);
2115 fputs(_(" -p, --login-pause wait for any key before the login\n"), out);
2116 fputs(_(" -r, --chroot <dir> change root to the directory\n"), out);
2117 fputs(_(" -R, --hangup do virtually hangup on the tty\n"), out);
2118 fputs(_(" -s, --keep-baud try to keep baud rate after break\n"), out);
2119 fputs(_(" -t, --timeout <number> login process timeout\n"), out);
2120 fputs(_(" -U, --detect-case detect uppercase terminal\n"), out);
2121 fputs(_(" -w, --wait-cr wait carriage-return\n"), out);
2122 fputs(_(" --nohints do not print hints\n"), out);
2123 fputs(_(" --nohostname no hostname at all will be shown\n"), out);
2124 fputs(_(" --long-hostname show full qualified hostname\n"), out);
2125 fputs(_(" --erase-chars <string> additional backspace chars\n"), out);
2126 fputs(_(" --kill-chars <string> additional kill chars\n"), out);
2127 fputs(_(" --chdir <directory> chdir before the login\n"), out);
2128 fputs(_(" --delay <number> sleep seconds before prompt\n"), out);
2129 fputs(_(" --nice <number> run login with this priority\n"), out);
2130 fputs(_(" --reload reload prompts on running agetty instances\n"), out);
2131 fputs(_(" --help display this help and exit\n"), out);
2132 fputs(_(" --version output version information and exit\n"), out);
2133 fprintf(out, USAGE_MAN_TAIL("agetty(8)"));
2134
2135 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
2136 }
2137
2138 /*
2139 * Helper function reports errors to console or syslog.
2140 * Will be used by log_err() and log_warn() therefore
2141 * it takes a format as well as va_list.
2142 */
2143 #define str2cpy(b,s1,s2) strcat(strcpy(b,s1),s2)
2144
2145 static void dolog(int priority, const char *fmt, va_list ap)
2146 {
2147 #ifndef USE_SYSLOG
2148 int fd;
2149 #endif
2150 char buf[BUFSIZ];
2151 char *bp;
2152
2153 /*
2154 * If the diagnostic is reported via syslog(3), the process name is
2155 * automatically prepended to the message. If we write directly to
2156 * /dev/console, we must prepend the process name ourselves.
2157 */
2158 #ifdef USE_SYSLOG
2159 buf[0] = '\0';
2160 bp = buf;
2161 #else
2162 str2cpy(buf, program_invocation_short_name, ": ");
2163 bp = buf + strlen(buf);
2164 #endif /* USE_SYSLOG */
2165 vsnprintf(bp, sizeof(buf)-strlen(buf), fmt, ap);
2166
2167 /*
2168 * Write the diagnostic directly to /dev/console if we do not use the
2169 * syslog(3) facility.
2170 */
2171 #ifdef USE_SYSLOG
2172 openlog(program_invocation_short_name, LOG_PID, LOG_AUTHPRIV);
2173 syslog(priority, "%s", buf);
2174 closelog();
2175 #else
2176 /* Terminate with CR-LF since the console mode is unknown. */
2177 strcat(bp, "\r\n");
2178 if ((fd = open("/dev/console", 1)) >= 0) {
2179 write_all(fd, buf, strlen(buf));
2180 close(fd);
2181 }
2182 #endif /* USE_SYSLOG */
2183 }
2184
2185 static void log_err(const char *fmt, ...)
2186 {
2187 va_list ap;
2188
2189 va_start(ap, fmt);
2190 dolog(LOG_ERR, fmt, ap);
2191 va_end(ap);
2192
2193 /* Be kind to init(8). */
2194 sleep(10);
2195 exit(EXIT_FAILURE);
2196 }
2197
2198 static void log_warn(const char *fmt, ...)
2199 {
2200 va_list ap;
2201
2202 va_start(ap, fmt);
2203 dolog(LOG_WARNING, fmt, ap);
2204 va_end(ap);
2205 }
2206
2207 static void print_addr(sa_family_t family, void *addr)
2208 {
2209 char buff[INET6_ADDRSTRLEN + 1];
2210
2211 inet_ntop(family, addr, buff, sizeof(buff));
2212 printf("%s", buff);
2213 }
2214
2215 /*
2216 * Prints IP for the specified interface (@iface), if the interface is not
2217 * specified then prints the "best" one (UP, RUNNING, non-LOOPBACK). If not
2218 * found the "best" interface then prints at least host IP.
2219 */
2220 static void output_iface_ip(struct ifaddrs *addrs,
2221 const char *iface,
2222 sa_family_t family)
2223 {
2224 struct ifaddrs *p;
2225 struct addrinfo hints, *info = NULL;
2226 char *host = NULL;
2227 void *addr = NULL;
2228
2229 if (!addrs)
2230 return;
2231
2232 for (p = addrs; p; p = p->ifa_next) {
2233
2234 if (!p->ifa_name ||
2235 !p->ifa_addr ||
2236 p->ifa_addr->sa_family != family)
2237 continue;
2238
2239 if (iface) {
2240 /* Filter out by interface name */
2241 if (strcmp(p->ifa_name, iface) != 0)
2242 continue;
2243 } else {
2244 /* Select the "best" interface */
2245 if ((p->ifa_flags & IFF_LOOPBACK) ||
2246 !(p->ifa_flags & IFF_UP) ||
2247 !(p->ifa_flags & IFF_RUNNING))
2248 continue;
2249 }
2250
2251 addr = NULL;
2252 switch (p->ifa_addr->sa_family) {
2253 case AF_INET:
2254 addr = &((struct sockaddr_in *) p->ifa_addr)->sin_addr;
2255 break;
2256 case AF_INET6:
2257 addr = &((struct sockaddr_in6 *) p->ifa_addr)->sin6_addr;
2258 break;
2259 }
2260
2261 if (addr) {
2262 print_addr(family, addr);
2263 return;
2264 }
2265 }
2266
2267 if (iface)
2268 return;
2269
2270 /* Hmm.. not found the best interface, print host IP at least */
2271 memset(&hints, 0, sizeof(hints));
2272 hints.ai_family = family;
2273 if (family == AF_INET6)
2274 hints.ai_flags = AI_V4MAPPED;
2275
2276 host = xgethostname();
2277 if (host && getaddrinfo(host, NULL, &hints, &info) == 0 && info) {
2278 switch (info->ai_family) {
2279 case AF_INET:
2280 addr = &((struct sockaddr_in *) info->ai_addr)->sin_addr;
2281 break;
2282 case AF_INET6:
2283 addr = &((struct sockaddr_in6 *) info->ai_addr)->sin6_addr;
2284 break;
2285 }
2286 if (addr)
2287 print_addr(family, addr);
2288
2289 freeaddrinfo(info);
2290 }
2291 free(host);
2292 }
2293
2294 /*
2295 * parses \x{argument}, if not argument specified then returns NULL, the @fd
2296 * has to point to one char after the sequence (it means '{').
2297 */
2298 static char *get_escape_argument(FILE *fd, char *buf, size_t bufsz)
2299 {
2300 size_t i = 0;
2301 int c = fgetc(fd);
2302
2303 if (c == EOF || (unsigned char) c != '{') {
2304 ungetc(c, fd);
2305 return NULL;
2306 }
2307
2308 do {
2309 c = fgetc(fd);
2310 if (c == EOF)
2311 return NULL;
2312 if ((unsigned char) c != '}' && i < bufsz - 1)
2313 buf[i++] = (unsigned char) c;
2314
2315 } while ((unsigned char) c != '}');
2316
2317 buf[i] = '\0';
2318 return buf;
2319 }
2320
2321 static void output_special_char(unsigned char c, struct options *op,
2322 struct termios *tp, FILE *fp)
2323 {
2324 struct utsname uts;
2325
2326 switch (c) {
2327 case 'e':
2328 {
2329 char escname[UL_COLORNAME_MAXSZ];
2330
2331 if (get_escape_argument(fp, escname, sizeof(escname))) {
2332 const char *esc = color_sequence_from_colorname(escname);
2333 if (esc)
2334 fputs(esc, stdout);
2335 } else
2336 fputs("\033", stdout);
2337 break;
2338 }
2339 case 's':
2340 uname(&uts);
2341 printf("%s", uts.sysname);
2342 break;
2343 case 'n':
2344 uname(&uts);
2345 printf("%s", uts.nodename);
2346 break;
2347 case 'r':
2348 uname(&uts);
2349 printf("%s", uts.release);
2350 break;
2351 case 'v':
2352 uname(&uts);
2353 printf("%s", uts.version);
2354 break;
2355 case 'm':
2356 uname(&uts);
2357 printf("%s", uts.machine);
2358 break;
2359 case 'o':
2360 {
2361 char *dom = xgetdomainname();
2362
2363 fputs(dom ? dom : "unknown_domain", stdout);
2364 free(dom);
2365 break;
2366 }
2367 case 'O':
2368 {
2369 char *dom = NULL;
2370 char *host = xgethostname();
2371 struct addrinfo hints, *info = NULL;
2372
2373 memset(&hints, 0, sizeof(hints));
2374 hints.ai_flags = AI_CANONNAME;
2375
2376 if (host && getaddrinfo(host, NULL, &hints, &info) == 0 && info) {
2377 char *canon;
2378
2379 if (info->ai_canonname &&
2380 (canon = strchr(info->ai_canonname, '.')))
2381 dom = canon + 1;
2382 }
2383 fputs(dom ? dom : "unknown_domain", stdout);
2384 if (info)
2385 freeaddrinfo(info);
2386 free(host);
2387 break;
2388 }
2389 case 'd':
2390 case 't':
2391 {
2392 time_t now;
2393 struct tm *tm;
2394
2395 time(&now);
2396 tm = localtime(&now);
2397
2398 if (!tm)
2399 break;
2400
2401 if (c == 'd') /* ISO 8601 */
2402 printf("%s %s %d %d",
2403 nl_langinfo(ABDAY_1 + tm->tm_wday),
2404 nl_langinfo(ABMON_1 + tm->tm_mon),
2405 tm->tm_mday,
2406 tm->tm_year < 70 ? tm->tm_year + 2000 :
2407 tm->tm_year + 1900);
2408 else
2409 printf("%02d:%02d:%02d",
2410 tm->tm_hour, tm->tm_min, tm->tm_sec);
2411 break;
2412 }
2413 case 'l':
2414 printf ("%s", op->tty);
2415 break;
2416 case 'b':
2417 {
2418 const speed_t speed = cfgetispeed(tp);
2419 int i;
2420
2421 for (i = 0; speedtab[i].speed; i++) {
2422 if (speedtab[i].code == speed) {
2423 printf("%ld", speedtab[i].speed);
2424 break;
2425 }
2426 }
2427 break;
2428 }
2429 case 'S':
2430 {
2431 char *var = NULL, varname[64];
2432
2433 /* \S{varname} */
2434 if (get_escape_argument(fp, varname, sizeof(varname))) {
2435 var = read_os_release(op, varname);
2436 if (var) {
2437 if (strcmp(varname, "ANSI_COLOR") == 0)
2438 printf("\033[%sm", var);
2439 else
2440 fputs(var, stdout);
2441 }
2442 /* \S */
2443 } else if ((var = read_os_release(op, "PRETTY_NAME"))) {
2444 fputs(var, stdout);
2445
2446 /* \S and PRETTY_NAME not found */
2447 } else {
2448 uname(&uts);
2449 fputs(uts.sysname, stdout);
2450 }
2451 break;
2452 }
2453 case 'u':
2454 case 'U':
2455 {
2456 int users = 0;
2457 struct utmpx *ut;
2458 setutxent();
2459 while ((ut = getutxent()))
2460 if (ut->ut_type == USER_PROCESS)
2461 users++;
2462 endutxent();
2463 if (c == 'U')
2464 printf(P_("%d user", "%d users", users), users);
2465 else
2466 printf ("%d ", users);
2467 break;
2468 }
2469 case '4':
2470 case '6':
2471 {
2472 sa_family_t family = c == '4' ? AF_INET : AF_INET6;
2473 struct ifaddrs *addrs = NULL;
2474 char iface[128];
2475
2476 #ifdef AGETTY_RELOAD
2477 open_netlink();
2478 #endif
2479
2480 if (getifaddrs(&addrs))
2481 break;
2482
2483 if (get_escape_argument(fp, iface, sizeof(iface)))
2484 output_iface_ip(addrs, iface, family);
2485 else
2486 output_iface_ip(addrs, NULL, family);
2487
2488 freeifaddrs(addrs);
2489 break;
2490 }
2491 default:
2492 putchar(c);
2493 break;
2494 }
2495 }
2496
2497 static void init_special_char(char* arg, struct options *op)
2498 {
2499 char ch, *p, *q;
2500 int i;
2501
2502 op->initstring = malloc(strlen(arg) + 1);
2503 if (!op->initstring)
2504 log_err(_("failed to allocate memory: %m"));
2505
2506 /*
2507 * Copy optarg into op->initstring decoding \ddd octal
2508 * codes into chars.
2509 */
2510 q = op->initstring;
2511 p = arg;
2512 while (*p) {
2513 /* The \\ is converted to \ */
2514 if (*p == '\\') {
2515 p++;
2516 if (*p == '\\') {
2517 ch = '\\';
2518 p++;
2519 } else {
2520 /* Handle \000 - \177. */
2521 ch = 0;
2522 for (i = 1; i <= 3; i++) {
2523 if (*p >= '0' && *p <= '7') {
2524 ch <<= 3;
2525 ch += *p - '0';
2526 p++;
2527 } else {
2528 break;
2529 }
2530 }
2531 }
2532 *q++ = ch;
2533 } else
2534 *q++ = *p++;
2535 }
2536 *q = '\0';
2537 }
2538
2539 /*
2540 * Appends @str to @dest and if @dest is not empty then use @sep as a
2541 * separator. The maximal final length of the @dest is @len.
2542 *
2543 * Returns the final @dest length or -1 in case of error.
2544 */
2545 static ssize_t append(char *dest, size_t len, const char *sep, const char *src)
2546 {
2547 size_t dsz = 0, ssz = 0, sz;
2548 char *p;
2549
2550 if (!dest || !len || !src)
2551 return -1;
2552
2553 if (*dest)
2554 dsz = strlen(dest);
2555 if (dsz && sep)
2556 ssz = strlen(sep);
2557 sz = strlen(src);
2558
2559 if (dsz + ssz + sz + 1 > len)
2560 return -1;
2561
2562 p = dest + dsz;
2563 if (ssz) {
2564 memcpy(p, sep, ssz);
2565 p += ssz;
2566 }
2567 memcpy(p, src, sz);
2568 *(p + sz) = '\0';
2569
2570 return dsz + ssz + sz;
2571 }
2572
2573 /*
2574 * Do not allow the user to pass an option as a user name
2575 * To be more safe: Use `--' to make sure the rest is
2576 * interpreted as non-options by the program, if it supports it.
2577 */
2578 static void check_username(const char* nm)
2579 {
2580 const char *p = nm;
2581 if (!nm)
2582 goto err;
2583 if (strlen(nm) > 42)
2584 goto err;
2585 while (isspace(*p))
2586 p++;
2587 if (*p == '-')
2588 goto err;
2589 return;
2590 err:
2591 errno = EPERM;
2592 log_err(_("checkname failed: %m"));
2593 }
2594
2595 static void reload_agettys(void)
2596 {
2597 #ifdef AGETTY_RELOAD
2598 int fd = open(AGETTY_RELOAD_FILENAME, O_CREAT|O_CLOEXEC|O_WRONLY,
2599 S_IRUSR|S_IWUSR);
2600 if (fd < 0)
2601 err(EXIT_FAILURE, _("cannot open %s"), AGETTY_RELOAD_FILENAME);
2602
2603 if (futimens(fd, NULL) < 0 || close(fd) < 0)
2604 err(EXIT_FAILURE, _("cannot touch file %s"),
2605 AGETTY_RELOAD_FILENAME);
2606 #else
2607 /* very unusual */
2608 errx(EXIT_FAILURE, _("--reload is unsupported on your system"));
2609 #endif
2610 }