2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
34 * @(#)from: main.c 8.1 (Berkeley) 6/20/93
35 * $FreeBSD: src/libexec/getty/main.c,v 1.28.2.4 2003/02/06 11:45:31 sobomax Exp $
36 * $DragonFly: src/libexec/getty/main.c,v 1.3 2003/11/14 03:54:30 dillon Exp $
39 #include <sys/param.h>
41 #include <sys/ioctl.h>
42 #include <sys/resource.h>
43 #include <sys/ttydefaults.h>
44 #include <sys/utsname.h>
61 #include "pathnames.h"
65 * Set the amount of running time that getty should accumulate
66 * before deciding that something is wrong and exit.
68 #define GETTY_TIMEOUT 60 /* seconds */
71 #define CTRL(x) (x&037)
73 /* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
75 #define PPP_FRAME 0x7e /* PPP Framing character */
76 #define PPP_STATION 0xff /* "All Station" character */
77 #define PPP_ESCAPE 0x7d /* Escape Character */
78 #define PPP_CONTROL 0x03 /* PPP Control Field */
79 #define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */
80 #define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */
81 #define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */
83 struct termios tmode, omode;
85 int crmod, digit, lower, upper;
87 char hostname[MAXHOSTNAMELEN];
88 char name[MAXLOGNAME*3];
89 char dev[] = _PATH_DEV;
95 char defent[TABBUFSIZ];
96 char tabent[TABBUFSIZ];
101 0001,0201,0201,0001,0201,0001,0001,0201,
102 0202,0004,0003,0205,0005,0206,0201,0001,
103 0201,0001,0001,0201,0001,0201,0201,0001,
104 0001,0201,0201,0001,0201,0001,0001,0201,
105 0200,0000,0000,0200,0000,0200,0200,0000,
106 0000,0200,0200,0000,0200,0000,0000,0200,
107 0000,0200,0200,0000,0200,0000,0000,0200,
108 0200,0000,0000,0200,0000,0200,0200,0000,
109 0200,0000,0000,0200,0000,0200,0200,0000,
110 0000,0200,0200,0000,0200,0000,0000,0200,
111 0000,0200,0200,0000,0200,0000,0000,0200,
112 0200,0000,0000,0200,0000,0200,0200,0000,
113 0000,0200,0200,0000,0200,0000,0000,0200,
114 0200,0000,0000,0200,0000,0200,0200,0000,
115 0200,0000,0000,0200,0000,0200,0200,0000,
116 0000,0200,0200,0000,0200,0000,0000,0201
119 #define ERASE tmode.c_cc[VERASE]
120 #define KILL tmode.c_cc[VKILL]
121 #define EOT tmode.c_cc[VEOF]
125 static void dingdong (int);
126 static int getname (void);
127 static void interrupt (int);
128 static void oflush (void);
129 static void prompt (void);
130 static void putchr (int);
131 static void putf (const char *);
132 static void putpad (const char *);
133 static void puts (const char *);
134 static void timeoverrun (int);
135 static char *getline (int);
136 static void setttymode (const char *, int);
137 static void setdefttymode (const char *);
138 static int opentty (const char *, int);
140 int main (int, char **);
162 * Action to take when getty is running too long.
169 syslog(LOG_ERR, "getty exiting due to excessive running time");
178 extern char **environ;
180 int first_sleep = 1, first_time = 1;
184 signal(SIGINT, SIG_IGN);
185 signal(SIGQUIT, SIG_IGN);
187 openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH);
188 gethostname(hostname, sizeof(hostname) - 1);
189 hostname[sizeof(hostname) - 1] = '\0';
190 if (hostname[0] == '\0')
191 strcpy(hostname, "Amnesiac");
194 * Limit running time to deal with broken or dead lines.
196 (void)signal(SIGXCPU, timeoverrun);
197 limit.rlim_max = RLIM_INFINITY;
198 limit.rlim_cur = GETTY_TIMEOUT;
199 (void)setrlimit(RLIMIT_CPU, &limit);
201 gettable("default", defent);
208 * The following is a work around for vhangup interactions
209 * which cause great problems getting window systems started.
210 * If the tty line is "-", we do the old style getty presuming
211 * that the file descriptors are already set up for us.
212 * J. Gettys - MIT Project Athena.
214 if (argc <= 2 || strcmp(argv[2], "-") == 0)
215 strcpy(ttyn, ttyname(STDIN_FILENO));
218 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
219 if (strcmp(argv[0], "+") != 0) {
224 gettable(tname, tabent);
226 /* Init modem sequence has been specified
229 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
231 setdefttymode(tname);
232 if (getty_chat(IC, CT, DC) > 0) {
233 syslog(LOG_ERR, "modem init problem on %s", ttyn);
234 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
241 struct timeval timeout;
243 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
245 setdefttymode(tname);
246 rfds = 1 << 0; /* FD_SET */
249 i = select(32, (fd_set*)&rfds, (fd_set*)NULL,
250 (fd_set*)NULL, RT ? &timeout : NULL);
252 syslog(LOG_ERR, "select %s: %m", ttyn);
254 syslog(LOG_NOTICE, "recycle tty %s", ttyn);
255 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
256 exit(0); /* recycle for init */
258 i = getty_chat(AC, CT, DC);
260 syslog(LOG_ERR, "modem answer problem on %s", ttyn);
261 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
264 } else { /* maybe blocking open */
265 if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 )))
271 /* Start with default tty settings */
272 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
273 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
277 * Don't rely on the driver too much, and initialize crucial
278 * things according to <sys/ttydefaults.h>. Avoid clobbering
279 * the c_cc[] settings however, the console drivers might wish
280 * to leave their idea of the preferred VERASE key value
283 tmode.c_iflag = TTYDEF_IFLAG;
284 tmode.c_oflag = TTYDEF_OFLAG;
285 tmode.c_lflag = TTYDEF_LFLAG;
286 tmode.c_cflag = TTYDEF_CFLAG;
287 tmode.c_cflag |= (NC ? CLOCAL : 0);
293 * if a delay was specified then sleep for that
294 * number of seconds before writing the initial prompt
296 if (first_sleep && DE) {
298 /* remove any noise */
299 (void)tcflush(STDIN_FILENO, TCIOFLUSH);
303 setttymode(tname, 0);
309 tname = portselector();
316 /* if this is the first time through this, and an
317 issue file has been given, then send it */
318 if (first_time && IF) {
321 if ((fd = open(IF, O_RDONLY)) != -1) {
324 while ((cp = getline(fd)) != NULL) {
332 if (IM && *IM && !(PL && PP))
334 if (setjmp(timeout)) {
335 cfsetispeed(&tmode, B0);
336 cfsetospeed(&tmode, B0);
337 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
341 signal(SIGALRM, dingdong);
349 while (*p && q < &name[sizeof name - 1]) {
352 else if (islower(*p))
354 else if (isdigit(*p))
358 } else if (!(PL && PP))
360 if (rval == 2 || (PL && PP)) {
363 limit.rlim_max = RLIM_INFINITY;
364 limit.rlim_cur = RLIM_INFINITY;
365 (void)setrlimit(RLIMIT_CPU, &limit);
366 execle(PP, "ppplogin", ttyn, (char *) 0, env);
367 syslog(LOG_ERR, "%s: %m", PP);
369 } else if (rval || AL) {
374 signal(SIGALRM, SIG_DFL);
375 if (name[0] == '-') {
376 puts("user names may not start with '-'.");
379 if (!(upper || lower || digit))
383 tmode.c_iflag |= ICRNL;
384 tmode.c_oflag |= ONLCR;
388 tmode.sg_flags |= LCASE;
390 tmode.sg_flags &= ~LCASE;
392 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
393 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
396 signal(SIGINT, SIG_DFL);
397 for (i = 0; environ[i] != (char *)0; i++)
401 limit.rlim_max = RLIM_INFINITY;
402 limit.rlim_cur = RLIM_INFINITY;
403 (void)setrlimit(RLIMIT_CPU, &limit);
404 execle(LO, "login", AL ? "-fp" : "-p", name,
406 syslog(LOG_ERR, "%s: %m", LO);
410 signal(SIGALRM, SIG_DFL);
411 signal(SIGINT, SIG_IGN);
418 opentty(const char *ttyn, int flags)
421 int failopenlogged = 0;
423 while (j < 10 && (i = open(ttyn, flags)) == -1)
425 if (((j % 10) == 0) && (errno != ENXIO || !failopenlogged)) {
426 syslog(LOG_ERR, "open %s: %m", ttyn);
433 syslog(LOG_ERR, "open %s: %m", ttyn);
437 if (login_tty(i) < 0) {
438 if (daemon(0,0) < 0) {
439 syslog(LOG_ERR,"daemon: %m");
443 if (login_tty(i) < 0) {
444 syslog(LOG_ERR, "login_tty %s: %m", ttyn);
457 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
458 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
461 tmode.c_iflag = TTYDEF_IFLAG;
462 tmode.c_oflag = TTYDEF_OFLAG;
463 tmode.c_lflag = TTYDEF_LFLAG;
464 tmode.c_cflag = TTYDEF_CFLAG;
466 setttymode(tname, 1);
470 setttymode(tname, raw)
476 gettable(tname, tabent);
477 if (OPset || EPset || APset)
478 APset++, OPset++, EPset++;
480 (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */
481 ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */
482 ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */
485 cfsetispeed(&tmode, speed(IS));
487 cfsetispeed(&tmode, speed(SP));
489 cfsetospeed(&tmode, speed(OS));
491 cfsetospeed(&tmode, speed(SP));
496 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
497 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
510 int ppp_connection = 0;
513 * Interrupt may happen if we use CBREAK mode
515 if (setjmp(intrupt)) {
516 signal(SIGINT, SIG_IGN);
519 signal(SIGINT, interrupt);
527 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
528 syslog(LOG_ERR, "%s: %m", ttyn);
531 crmod = digit = lower = upper = 0;
535 if (read(STDIN_FILENO, &cs, 1) <= 0)
537 if ((c = cs&0177) == 0)
540 /* PPP detection state machine..
542 PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
543 PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
545 Derived from code from Michael Hancock, <michaelh@cet.co.jp>
546 and Erik 'PPP' Olson, <eriko@wrq.com>
549 if (PP && (cs == PPP_FRAME)) {
551 } else if (ppp_state == 1 && cs == PPP_STATION) {
553 } else if (ppp_state == 2 && cs == PPP_ESCAPE) {
555 } else if ((ppp_state == 2 && cs == PPP_CONTROL)
556 || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
558 } else if (ppp_state == 4 && cs == PPP_LCP_HI) {
560 } else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
567 if (c == EOT || c == CTRL('d'))
569 if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) {
577 else if (c == ERASE || c == '\b' || c == 0177) {
580 if (cfgetospeed(&tmode) >= 1200)
586 } else if (c == KILL || c == CTRL('u')) {
588 if (cfgetospeed(&tmode) < 1200)
590 /* this is the way they do it down under ... */
596 } else if (isdigit(c))
598 if (IG && (c <= ' ' || c > 0176))
603 signal(SIGINT, SIG_IGN);
607 if ((upper && !lower && !LC) || UC)
608 for (np = name; *np; np++)
611 return (1 + ppp_connection);
616 register const char *s;
619 speed_t ospeed = cfgetospeed(&tmode);
622 while (isdigit(*s)) {
627 if (*s == '.' && isdigit(s[1])) {
635 * If no delay needed, or output speed is
636 * not comprehensible, then don't try to delay.
638 if (pad == 0 || ospeed <= 0)
642 * Round up by a half a character frame, and then do the delay.
643 * Too bad there are no user program accessible programmed delays.
644 * Transmitting pad characters slows many terminals down and also
647 pad = (pad * ospeed + 50000) / 100000;
654 register const char *s;
660 char outbuf[OBUFSIZ];
671 c |= partab[c&0177] & 0200;
676 outbuf[obufcnt++] = c;
677 if (obufcnt >= OBUFSIZ)
680 write(STDOUT_FILENO, &c, 1);
687 write(STDOUT_FILENO, outbuf, obufcnt);
706 static char linebuf[512];
709 * This is certainly slow, but it avoids having to include
710 * stdio.h unnecessarily. Issue files should be small anyway.
712 while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) {
713 if (linebuf[i] == '\n') {
714 /* Don't rely on newline mode, assume raw */
723 return i ? linebuf : 0;
728 register const char *cp;
730 extern char editedhost[];
732 char *slash, db[100];
734 static struct utsname kerninfo;
736 if (!*kerninfo.sysname)
747 slash = strrchr(ttyn, '/');
748 if (slash == (char *) 0)
762 (void)setlocale(LC_TIME, Lo);
763 (void)strftime(db, sizeof(db), DF, localtime(&t));
768 puts(kerninfo.sysname);
772 puts(kerninfo.machine);
776 puts(kerninfo.release);
780 puts(kerninfo.version);