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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
30 * @(#)from: main.c 8.1 (Berkeley) 6/20/93
31 * $FreeBSD: src/libexec/getty/main.c,v 1.28.2.4 2003/02/06 11:45:31 sobomax Exp $
34 #include <sys/param.h>
36 #include <sys/ioctl.h>
37 #include <sys/resource.h>
38 #include <sys/ttydefaults.h>
39 #include <sys/utsname.h>
55 #include "pathnames.h"
59 * Set the amount of running time that getty should accumulate
60 * before deciding that something is wrong and exit.
62 #define GETTY_TIMEOUT 60 /* seconds */
65 #define CTRL(x) (x&037)
67 /* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
69 #define PPP_FRAME 0x7e /* PPP Framing character */
70 #define PPP_STATION 0xff /* "All Station" character */
71 #define PPP_ESCAPE 0x7d /* Escape Character */
72 #define PPP_CONTROL 0x03 /* PPP Control Field */
73 #define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */
74 #define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */
75 #define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */
77 struct termios tmode, omode;
79 int crmod, digit, lower, upper;
81 char hostname[MAXHOSTNAMELEN];
82 char name[MAXLOGNAME*3];
83 char dev[] = _PATH_DEV;
89 char defent[TABBUFSIZ];
90 char tabent[TABBUFSIZ];
95 0001,0201,0201,0001,0201,0001,0001,0201,
96 0202,0004,0003,0205,0005,0206,0201,0001,
97 0201,0001,0001,0201,0001,0201,0201,0001,
98 0001,0201,0201,0001,0201,0001,0001,0201,
99 0200,0000,0000,0200,0000,0200,0200,0000,
100 0000,0200,0200,0000,0200,0000,0000,0200,
101 0000,0200,0200,0000,0200,0000,0000,0200,
102 0200,0000,0000,0200,0000,0200,0200,0000,
103 0200,0000,0000,0200,0000,0200,0200,0000,
104 0000,0200,0200,0000,0200,0000,0000,0200,
105 0000,0200,0200,0000,0200,0000,0000,0200,
106 0200,0000,0000,0200,0000,0200,0200,0000,
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,0201
113 #define ERASE tmode.c_cc[VERASE]
114 #define KILL tmode.c_cc[VKILL]
115 #define EOT tmode.c_cc[VEOF]
119 static void dingdong (int);
120 static int getname (void);
121 static void interrupt (int);
122 static void oflush (void);
123 static void prompt (void);
124 static void putchr (int);
125 static void putf (const char *);
126 static void putpad (const char *);
127 static void puts (const char *);
128 static void timeoverrun (int);
129 static char *getline (int);
130 static void setttymode (const char *, int);
131 static void setdefttymode (const char *);
132 static int opentty (const char *, int);
134 int main (int, char **);
154 * Action to take when getty is running too long.
157 timeoverrun(int signo)
159 syslog(LOG_ERR, "getty exiting due to excessive running time");
164 main(int argc, char **argv)
166 extern char **environ;
168 int first_sleep = 1, first_time = 1;
172 signal(SIGINT, SIG_IGN);
173 signal(SIGQUIT, SIG_IGN);
175 openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH);
176 gethostname(hostname, sizeof(hostname) - 1);
177 hostname[sizeof(hostname) - 1] = '\0';
178 if (hostname[0] == '\0')
179 strcpy(hostname, "Amnesiac");
182 * Limit running time to deal with broken or dead lines.
184 (void)signal(SIGXCPU, timeoverrun);
185 limit.rlim_max = RLIM_INFINITY;
186 limit.rlim_cur = GETTY_TIMEOUT;
187 (void)setrlimit(RLIMIT_CPU, &limit);
189 gettable("default", defent);
196 * The following is a work around for vhangup interactions
197 * which cause great problems getting window systems started.
198 * If the tty line is "-", we do the old style getty presuming
199 * that the file descriptors are already set up for us.
200 * J. Gettys - MIT Project Athena.
202 if (argc <= 2 || strcmp(argv[2], "-") == 0)
203 strcpy(ttyn, ttyname(STDIN_FILENO));
206 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
207 if (strcmp(argv[0], "+") != 0) {
212 gettable(tname, tabent);
214 /* Init modem sequence has been specified
217 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
219 setdefttymode(tname);
220 if (getty_chat(IC, CT, DC) > 0) {
221 syslog(LOG_ERR, "modem init problem on %s", ttyn);
222 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
229 struct timeval timeout;
231 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
233 setdefttymode(tname);
234 rfds = 1 << 0; /* FD_SET */
237 i = select(32, (fd_set*)&rfds, NULL,
238 NULL, RT ? &timeout : NULL);
240 syslog(LOG_ERR, "select %s: %m", ttyn);
242 syslog(LOG_NOTICE, "recycle tty %s", ttyn);
243 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
244 exit(0); /* recycle for init */
246 i = getty_chat(AC, CT, DC);
248 syslog(LOG_ERR, "modem answer problem on %s", ttyn);
249 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
252 } else { /* maybe blocking open */
253 if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 )))
259 /* Start with default tty settings */
260 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
261 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
265 * Don't rely on the driver too much, and initialize crucial
266 * things according to <sys/ttydefaults.h>. Avoid clobbering
267 * the c_cc[] settings however, the console drivers might wish
268 * to leave their idea of the preferred VERASE key value
271 tmode.c_iflag = TTYDEF_IFLAG;
272 tmode.c_oflag = TTYDEF_OFLAG;
273 tmode.c_lflag = TTYDEF_LFLAG;
274 tmode.c_cflag = TTYDEF_CFLAG;
275 tmode.c_cflag |= (NC ? CLOCAL : 0);
281 * if a delay was specified then sleep for that
282 * number of seconds before writing the initial prompt
284 if (first_sleep && DE) {
286 /* remove any noise */
287 (void)tcflush(STDIN_FILENO, TCIOFLUSH);
291 setttymode(tname, 0);
297 tname = portselector();
304 /* if this is the first time through this, and an
305 issue file has been given, then send it */
306 if (first_time && IF) {
309 if ((fd = open(IF, O_RDONLY)) != -1) {
312 while ((cp = getline(fd)) != NULL) {
320 if (IM && *IM && !(PL && PP))
322 if (setjmp(timeout)) {
323 cfsetispeed(&tmode, B0);
324 cfsetospeed(&tmode, B0);
325 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
329 signal(SIGALRM, dingdong);
336 while (*p && q < &name[sizeof name - 1]) {
339 else if (islower(*p))
341 else if (isdigit(*p))
345 } else if (!(PL && PP))
347 if (rval == 2 || (PL && PP)) {
350 limit.rlim_max = RLIM_INFINITY;
351 limit.rlim_cur = RLIM_INFINITY;
352 (void)setrlimit(RLIMIT_CPU, &limit);
353 execle(PP, "ppplogin", ttyn, NULL, env);
354 syslog(LOG_ERR, "%s: %m", PP);
356 } else if (rval || AL) {
361 signal(SIGALRM, SIG_DFL);
362 if (name[0] == '-') {
363 puts("user names may not start with '-'.");
366 if (!(upper || lower || digit))
370 tmode.c_iflag |= ICRNL;
371 tmode.c_oflag |= ONLCR;
375 tmode.sg_flags |= LCASE;
377 tmode.sg_flags &= ~LCASE;
379 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
380 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
383 signal(SIGINT, SIG_DFL);
384 for (i = 0; environ[i] != NULL; i++)
388 limit.rlim_max = RLIM_INFINITY;
389 limit.rlim_cur = RLIM_INFINITY;
390 (void)setrlimit(RLIMIT_CPU, &limit);
391 execle(LO, "login", AL ? "-fp" : "-p", name,
393 syslog(LOG_ERR, "%s: %m", LO);
397 signal(SIGALRM, SIG_DFL);
398 signal(SIGINT, SIG_IGN);
405 opentty(const char *ttyn, int flags)
408 int failopenlogged = 0;
410 while (j < 10 && (i = open(ttyn, flags)) == -1)
412 if (((j % 10) == 0) && (errno != ENXIO || !failopenlogged)) {
413 syslog(LOG_ERR, "open %s: %m", ttyn);
420 syslog(LOG_ERR, "open %s: %m", ttyn);
424 if (login_tty(i) < 0) {
425 if (daemon(0,0) < 0) {
426 syslog(LOG_ERR,"daemon: %m");
430 if (login_tty(i) < 0) {
431 syslog(LOG_ERR, "login_tty %s: %m", ttyn);
441 setdefttymode(const char *tname)
443 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
444 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
447 tmode.c_iflag = TTYDEF_IFLAG;
448 tmode.c_oflag = TTYDEF_OFLAG;
449 tmode.c_lflag = TTYDEF_LFLAG;
450 tmode.c_cflag = TTYDEF_CFLAG;
452 setttymode(tname, 1);
456 setttymode(const char *tname, int raw)
460 gettable(tname, tabent);
461 if (OPset || EPset || APset)
462 APset++, OPset++, EPset++;
464 (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */
465 ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */
466 ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */
469 cfsetispeed(&tmode, speed(IS));
471 cfsetispeed(&tmode, speed(SP));
473 cfsetospeed(&tmode, speed(OS));
475 cfsetospeed(&tmode, speed(SP));
480 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
481 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
494 int ppp_connection = 0;
497 * Interrupt may happen if we use CBREAK mode
499 if (setjmp(intrupt)) {
500 signal(SIGINT, SIG_IGN);
503 signal(SIGINT, interrupt);
511 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
512 syslog(LOG_ERR, "%s: %m", ttyn);
515 crmod = digit = lower = upper = 0;
519 if (read(STDIN_FILENO, &cs, 1) <= 0)
521 if ((c = cs&0177) == 0)
524 /* PPP detection state machine..
526 PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
527 PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
529 Derived from code from Michael Hancock, <michaelh@cet.co.jp>
530 and Erik 'PPP' Olson, <eriko@wrq.com>
533 if (PP && (cs == PPP_FRAME)) {
535 } else if (ppp_state == 1 && cs == PPP_STATION) {
537 } else if (ppp_state == 2 && cs == PPP_ESCAPE) {
539 } else if ((ppp_state == 2 && cs == PPP_CONTROL)
540 || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
542 } else if (ppp_state == 4 && cs == PPP_LCP_HI) {
544 } else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
551 if (c == EOT || c == CTRL('d'))
553 if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) {
561 else if (c == ERASE || c == '\b' || c == 0177) {
564 if (cfgetospeed(&tmode) >= 1200)
570 } else if (c == KILL || c == CTRL('u')) {
572 if (cfgetospeed(&tmode) < 1200)
574 /* this is the way they do it down under ... */
580 } else if (isdigit(c))
582 if (IG && (c <= ' ' || c > 0176))
587 signal(SIGINT, SIG_IGN);
591 if ((upper && !lower && !LC) || UC)
592 for (np = name; *np; np++)
595 return (1 + ppp_connection);
599 putpad(const char *s)
604 ospeed = cfgetospeed(&tmode);
607 while (isdigit(*s)) {
612 if (*s == '.' && isdigit(s[1])) {
620 * If no delay needed, or output speed is
621 * not comprehensible, then don't try to delay.
623 if (pad == 0 || ospeed <= 0)
627 * Round up by a half a character frame, and then do the delay.
628 * Too bad there are no user program accessible programmed delays.
629 * Transmitting pad characters slows many terminals down and also
632 pad = (pad * ospeed + 50000) / 100000;
644 char outbuf[OBUFSIZ];
654 c |= partab[c&0177] & 0200;
659 outbuf[obufcnt++] = c;
660 if (obufcnt >= OBUFSIZ)
663 write(STDOUT_FILENO, &c, 1);
670 write(STDOUT_FILENO, outbuf, obufcnt);
687 static char linebuf[512];
690 * This is certainly slow, but it avoids having to include
691 * stdio.h unnecessarily. Issue files should be small anyway.
693 while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) {
694 if (linebuf[i] == '\n') {
695 /* Don't rely on newline mode, assume raw */
704 return i ? linebuf : 0;
710 extern char editedhost[];
712 char *slash, db[100];
714 static struct utsname kerninfo;
716 if (!*kerninfo.sysname)
727 slash = strrchr(ttyn, '/');
742 (void)setlocale(LC_TIME, Lo);
743 (void)strftime(db, sizeof(db), DF, localtime(&t));
748 puts(kerninfo.sysname);
752 puts(kerninfo.machine);
756 puts(kerninfo.release);
760 puts(kerninfo.version);