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);
152 * Action to take when getty is running too long.
155 timeoverrun(int signo)
157 syslog(LOG_ERR, "getty exiting due to excessive running time");
162 main(int argc, char **argv)
164 extern char **environ;
166 int first_sleep = 1, first_time = 1;
170 signal(SIGINT, SIG_IGN);
171 signal(SIGQUIT, SIG_IGN);
173 openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH);
174 gethostname(hostname, sizeof(hostname) - 1);
175 hostname[sizeof(hostname) - 1] = '\0';
176 if (hostname[0] == '\0')
177 strcpy(hostname, "Amnesiac");
180 * Limit running time to deal with broken or dead lines.
182 (void)signal(SIGXCPU, timeoverrun);
183 limit.rlim_max = RLIM_INFINITY;
184 limit.rlim_cur = GETTY_TIMEOUT;
185 (void)setrlimit(RLIMIT_CPU, &limit);
187 gettable("default", defent);
194 * The following is a work around for vhangup interactions
195 * which cause great problems getting window systems started.
196 * If the tty line is "-", we do the old style getty presuming
197 * that the file descriptors are already set up for us.
198 * J. Gettys - MIT Project Athena.
200 if (argc <= 2 || strcmp(argv[2], "-") == 0)
201 strcpy(ttyn, ttyname(STDIN_FILENO));
204 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
205 if (strcmp(argv[0], "+") != 0) {
210 gettable(tname, tabent);
212 /* Init modem sequence has been specified
215 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
217 setdefttymode(tname);
218 if (getty_chat(IC, CT, DC) > 0) {
219 syslog(LOG_ERR, "modem init problem on %s", ttyn);
220 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
227 struct timeval timeout;
229 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
231 setdefttymode(tname);
232 rfds = 1 << 0; /* FD_SET */
235 i = select(32, (fd_set*)&rfds, NULL,
236 NULL, RT ? &timeout : NULL);
238 syslog(LOG_ERR, "select %s: %m", ttyn);
240 syslog(LOG_NOTICE, "recycle tty %s", ttyn);
241 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
242 exit(0); /* recycle for init */
244 i = getty_chat(AC, CT, DC);
246 syslog(LOG_ERR, "modem answer problem on %s", ttyn);
247 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
250 } else { /* maybe blocking open */
251 if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 )))
257 /* Start with default tty settings */
258 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
259 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
263 * Don't rely on the driver too much, and initialize crucial
264 * things according to <sys/ttydefaults.h>. Avoid clobbering
265 * the c_cc[] settings however, the console drivers might wish
266 * to leave their idea of the preferred VERASE key value
269 tmode.c_iflag = TTYDEF_IFLAG;
270 tmode.c_oflag = TTYDEF_OFLAG;
271 tmode.c_lflag = TTYDEF_LFLAG;
272 tmode.c_cflag = TTYDEF_CFLAG;
273 tmode.c_cflag |= (NC ? CLOCAL : 0);
279 * if a delay was specified then sleep for that
280 * number of seconds before writing the initial prompt
282 if (first_sleep && DE) {
284 /* remove any noise */
285 (void)tcflush(STDIN_FILENO, TCIOFLUSH);
289 setttymode(tname, 0);
295 tname = portselector();
302 /* if this is the first time through this, and an
303 issue file has been given, then send it */
304 if (first_time && IF) {
307 if ((fd = open(IF, O_RDONLY)) != -1) {
310 while ((cp = getline(fd)) != NULL) {
318 if (IM && *IM && !(PL && PP))
320 if (setjmp(timeout)) {
321 cfsetispeed(&tmode, B0);
322 cfsetospeed(&tmode, B0);
323 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
327 signal(SIGALRM, dingdong);
334 while (*p && q < &name[sizeof name - 1]) {
337 else if (islower(*p))
339 else if (isdigit(*p))
343 } else if (!(PL && PP))
345 if (rval == 2 || (PL && PP)) {
348 limit.rlim_max = RLIM_INFINITY;
349 limit.rlim_cur = RLIM_INFINITY;
350 (void)setrlimit(RLIMIT_CPU, &limit);
351 execle(PP, "ppplogin", ttyn, NULL, env);
352 syslog(LOG_ERR, "%s: %m", PP);
354 } else if (rval || AL) {
359 signal(SIGALRM, SIG_DFL);
360 if (name[0] == '-') {
361 puts("user names may not start with '-'.");
364 if (!(upper || lower || digit))
368 tmode.c_iflag |= ICRNL;
369 tmode.c_oflag |= ONLCR;
373 tmode.sg_flags |= LCASE;
375 tmode.sg_flags &= ~LCASE;
377 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
378 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
381 signal(SIGINT, SIG_DFL);
382 for (i = 0; environ[i] != NULL; i++)
386 limit.rlim_max = RLIM_INFINITY;
387 limit.rlim_cur = RLIM_INFINITY;
388 (void)setrlimit(RLIMIT_CPU, &limit);
389 execle(LO, "login", AL ? "-fp" : "-p", name,
391 syslog(LOG_ERR, "%s: %m", LO);
395 signal(SIGALRM, SIG_DFL);
396 signal(SIGINT, SIG_IGN);
403 opentty(const char *ttyn, int flags)
406 int failopenlogged = 0;
408 while (j < 10 && (i = open(ttyn, flags)) == -1)
410 if (((j % 10) == 0) && (errno != ENXIO || !failopenlogged)) {
411 syslog(LOG_ERR, "open %s: %m", ttyn);
418 syslog(LOG_ERR, "open %s: %m", ttyn);
422 if (login_tty(i) < 0) {
423 if (daemon(0,0) < 0) {
424 syslog(LOG_ERR,"daemon: %m");
428 if (login_tty(i) < 0) {
429 syslog(LOG_ERR, "login_tty %s: %m", ttyn);
439 setdefttymode(const char *tname)
441 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
442 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
445 tmode.c_iflag = TTYDEF_IFLAG;
446 tmode.c_oflag = TTYDEF_OFLAG;
447 tmode.c_lflag = TTYDEF_LFLAG;
448 tmode.c_cflag = TTYDEF_CFLAG;
450 setttymode(tname, 1);
454 setttymode(const char *tname, int raw)
458 gettable(tname, tabent);
459 if (OPset || EPset || APset)
460 APset++, OPset++, EPset++;
462 (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */
463 ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */
464 ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */
467 cfsetispeed(&tmode, speed(IS));
469 cfsetispeed(&tmode, speed(SP));
471 cfsetospeed(&tmode, speed(OS));
473 cfsetospeed(&tmode, speed(SP));
478 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
479 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
492 int ppp_connection = 0;
495 * Interrupt may happen if we use CBREAK mode
497 if (setjmp(intrupt)) {
498 signal(SIGINT, SIG_IGN);
501 signal(SIGINT, interrupt);
509 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
510 syslog(LOG_ERR, "%s: %m", ttyn);
513 crmod = digit = lower = upper = 0;
517 if (read(STDIN_FILENO, &cs, 1) <= 0)
519 if ((c = cs&0177) == 0)
522 /* PPP detection state machine..
524 PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
525 PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
527 Derived from code from Michael Hancock, <michaelh@cet.co.jp>
528 and Erik 'PPP' Olson, <eriko@wrq.com>
531 if (PP && (cs == PPP_FRAME)) {
533 } else if (ppp_state == 1 && cs == PPP_STATION) {
535 } else if (ppp_state == 2 && cs == PPP_ESCAPE) {
537 } else if ((ppp_state == 2 && cs == PPP_CONTROL)
538 || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
540 } else if (ppp_state == 4 && cs == PPP_LCP_HI) {
542 } else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
549 if (c == EOT || c == CTRL('d'))
551 if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) {
559 else if (c == ERASE || c == '\b' || c == 0177) {
562 if (cfgetospeed(&tmode) >= 1200)
568 } else if (c == KILL || c == CTRL('u')) {
570 if (cfgetospeed(&tmode) < 1200)
572 /* this is the way they do it down under ... */
578 } else if (isdigit(c))
580 if (IG && (c <= ' ' || c > 0176))
585 signal(SIGINT, SIG_IGN);
589 if ((upper && !lower && !LC) || UC)
590 for (np = name; *np; np++)
593 return (1 + ppp_connection);
597 putpad(const char *s)
602 ospeed = cfgetospeed(&tmode);
605 while (isdigit(*s)) {
610 if (*s == '.' && isdigit(s[1])) {
618 * If no delay needed, or output speed is
619 * not comprehensible, then don't try to delay.
621 if (pad == 0 || ospeed <= 0)
625 * Round up by a half a character frame, and then do the delay.
626 * Too bad there are no user program accessible programmed delays.
627 * Transmitting pad characters slows many terminals down and also
630 pad = (pad * ospeed + 50000) / 100000;
642 char outbuf[OBUFSIZ];
652 c |= partab[c&0177] & 0200;
657 outbuf[obufcnt++] = c;
658 if (obufcnt >= OBUFSIZ)
661 write(STDOUT_FILENO, &c, 1);
668 write(STDOUT_FILENO, outbuf, obufcnt);
685 static char linebuf[512];
688 * This is certainly slow, but it avoids having to include
689 * stdio.h unnecessarily. Issue files should be small anyway.
691 while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) {
692 if (linebuf[i] == '\n') {
693 /* Don't rely on newline mode, assume raw */
702 return i ? linebuf : 0;
708 extern char editedhost[];
710 char *slash, db[100];
712 static struct utsname kerninfo;
714 if (!*kerninfo.sysname)
725 slash = strrchr(ttyn, '/');
740 (void)setlocale(LC_TIME, Lo);
741 (void)strftime(db, sizeof(db), DF, localtime(&t));
746 puts(kerninfo.sysname);
750 puts(kerninfo.machine);
754 puts(kerninfo.release);
758 puts(kerninfo.version);