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
35 static const char copyright[] =
36 "@(#) Copyright (c) 1980, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
42 static char sccsid[] = "@(#)from: main.c 8.1 (Berkeley) 6/20/93";
44 static const char rcsid[] =
48 #include <sys/param.h>
50 #include <sys/ioctl.h>
51 #include <sys/resource.h>
52 #include <sys/ttydefaults.h>
53 #include <sys/utsname.h>
70 #include "pathnames.h"
74 * Set the amount of running time that getty should accumulate
75 * before deciding that something is wrong and exit.
77 #define GETTY_TIMEOUT 60 /* seconds */
80 #define CTRL(x) (x&037)
82 /* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
84 #define PPP_FRAME 0x7e /* PPP Framing character */
85 #define PPP_STATION 0xff /* "All Station" character */
86 #define PPP_ESCAPE 0x7d /* Escape Character */
87 #define PPP_CONTROL 0x03 /* PPP Control Field */
88 #define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */
89 #define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */
90 #define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */
92 struct termios tmode, omode;
94 int crmod, digit, lower, upper;
96 char hostname[MAXHOSTNAMELEN];
97 char name[MAXLOGNAME*3];
98 char dev[] = _PATH_DEV;
102 #define TABBUFSIZ 512
104 char defent[TABBUFSIZ];
105 char tabent[TABBUFSIZ];
110 0001,0201,0201,0001,0201,0001,0001,0201,
111 0202,0004,0003,0205,0005,0206,0201,0001,
112 0201,0001,0001,0201,0001,0201,0201,0001,
113 0001,0201,0201,0001,0201,0001,0001,0201,
114 0200,0000,0000,0200,0000,0200,0200,0000,
115 0000,0200,0200,0000,0200,0000,0000,0200,
116 0000,0200,0200,0000,0200,0000,0000,0200,
117 0200,0000,0000,0200,0000,0200,0200,0000,
118 0200,0000,0000,0200,0000,0200,0200,0000,
119 0000,0200,0200,0000,0200,0000,0000,0200,
120 0000,0200,0200,0000,0200,0000,0000,0200,
121 0200,0000,0000,0200,0000,0200,0200,0000,
122 0000,0200,0200,0000,0200,0000,0000,0200,
123 0200,0000,0000,0200,0000,0200,0200,0000,
124 0200,0000,0000,0200,0000,0200,0200,0000,
125 0000,0200,0200,0000,0200,0000,0000,0201
128 #define ERASE tmode.c_cc[VERASE]
129 #define KILL tmode.c_cc[VKILL]
130 #define EOT tmode.c_cc[VEOF]
132 static void dingdong __P((int));
133 static int getname __P((void));
134 static void interrupt __P((int));
135 static void oflush __P((void));
136 static void prompt __P((void));
137 static void putchr __P((int));
138 static void putf __P((const char *));
139 static void putpad __P((const char *));
140 static void puts __P((const char *));
141 static void timeoverrun __P((int));
142 static char *getline __P((int));
143 static void setttymode __P((const char *, int));
144 static void setdefttymode __P((const char *));
145 static int opentty __P((const char *, int));
147 int main __P((int, char **));
169 * Action to take when getty is running too long.
176 syslog(LOG_ERR, "getty exiting due to excessive running time");
185 extern char **environ;
187 int first_sleep = 1, first_time = 1;
191 signal(SIGINT, SIG_IGN);
192 signal(SIGQUIT, SIG_IGN);
194 openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH);
195 gethostname(hostname, sizeof(hostname));
196 if (hostname[0] == '\0')
197 strcpy(hostname, "Amnesiac");
200 * Limit running time to deal with broken or dead lines.
202 (void)signal(SIGXCPU, timeoverrun);
203 limit.rlim_max = RLIM_INFINITY;
204 limit.rlim_cur = GETTY_TIMEOUT;
205 (void)setrlimit(RLIMIT_CPU, &limit);
207 gettable("default", defent);
214 * The following is a work around for vhangup interactions
215 * which cause great problems getting window systems started.
216 * If the tty line is "-", we do the old style getty presuming
217 * that the file descriptors are already set up for us.
218 * J. Gettys - MIT Project Athena.
220 if (argc <= 2 || strcmp(argv[2], "-") == 0)
221 strcpy(ttyn, ttyname(STDIN_FILENO));
224 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
225 if (strcmp(argv[0], "+") != 0) {
230 gettable(tname, tabent);
232 /* Init modem sequence has been specified
235 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
237 setdefttymode(tname);
238 if (getty_chat(IC, CT, DC) > 0) {
239 syslog(LOG_ERR, "modem init problem on %s", ttyn);
240 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
247 struct timeval timeout;
249 if (!opentty(ttyn, O_RDWR|O_NONBLOCK))
251 setdefttymode(tname);
252 rfds = 1 << 0; /* FD_SET */
255 i = select(32, (fd_set*)&rfds, (fd_set*)NULL,
256 (fd_set*)NULL, RT ? &timeout : NULL);
258 syslog(LOG_ERR, "select %s: %m", ttyn);
260 syslog(LOG_NOTICE, "recycle tty %s", ttyn);
261 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
262 exit(0); /* recycle for init */
264 i = getty_chat(AC, CT, DC);
266 syslog(LOG_ERR, "modem answer problem on %s", ttyn);
267 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
270 } else { /* blocking open */
271 if (!opentty(ttyn, O_RDWR))
277 /* Start with default tty settings */
278 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
279 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
283 * Don't rely on the driver too much, and initialize crucial
284 * things according to <sys/ttydefaults.h>. Avoid clobbering
285 * the c_cc[] settings however, the console drivers might wish
286 * to leave their idea of the preferred VERASE key value
289 tmode.c_iflag = TTYDEF_IFLAG;
290 tmode.c_oflag = TTYDEF_OFLAG;
291 tmode.c_lflag = TTYDEF_LFLAG;
292 tmode.c_cflag = TTYDEF_CFLAG;
298 * if a delay was specified then sleep for that
299 * number of seconds before writing the initial prompt
301 if (first_sleep && DE) {
303 /* remove any noise */
304 (void)tcflush(STDIN_FILENO, TCIOFLUSH);
308 setttymode(tname, 0);
314 tname = portselector();
321 /* if this is the first time through this, and an
322 issue file has been given, then send it */
323 if (first_time && IF) {
326 if ((fd = open(IF, O_RDONLY)) != -1) {
329 while ((cp = getline(fd)) != NULL) {
339 if (setjmp(timeout)) {
340 cfsetispeed(&tmode, B0);
341 cfsetospeed(&tmode, B0);
342 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode);
346 signal(SIGALRM, dingdong);
349 if ((rval = getname()) == 2) {
352 execle(PP, "ppplogin", ttyn, (char *) 0, env);
353 syslog(LOG_ERR, "%s: %m", PP);
360 signal(SIGALRM, SIG_DFL);
361 if (name[0] == '-') {
362 puts("user names may not start with '-'.");
365 if (!(upper || lower || digit))
369 tmode.c_iflag |= ICRNL;
370 tmode.c_oflag |= ONLCR;
374 tmode.sg_flags |= LCASE;
376 tmode.sg_flags &= ~LCASE;
378 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
379 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
382 signal(SIGINT, SIG_DFL);
383 for (i = 0; environ[i] != (char *)0; i++)
387 limit.rlim_max = RLIM_INFINITY;
388 limit.rlim_cur = RLIM_INFINITY;
389 (void)setrlimit(RLIMIT_CPU, &limit);
390 execle(LO, "login", "-p", name, (char *) 0, env);
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);
431 if (tcgetattr(STDIN_FILENO, &tmode) < 0) {
432 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn);
435 tmode.c_iflag = TTYDEF_IFLAG;
436 tmode.c_oflag = TTYDEF_OFLAG;
437 tmode.c_lflag = TTYDEF_LFLAG;
438 tmode.c_cflag = TTYDEF_CFLAG;
440 setttymode(tname, 1);
444 setttymode(tname, raw)
450 gettable(tname, tabent);
451 if (OPset || EPset || APset)
452 APset++, OPset++, EPset++;
454 (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */
455 ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */
456 ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */
459 cfsetispeed(&tmode, speed(IS));
461 cfsetispeed(&tmode, speed(SP));
463 cfsetospeed(&tmode, speed(OS));
465 cfsetospeed(&tmode, speed(SP));
470 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
471 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn);
484 int ppp_connection = 0;
487 * Interrupt may happen if we use CBREAK mode
489 if (setjmp(intrupt)) {
490 signal(SIGINT, SIG_IGN);
493 signal(SIGINT, interrupt);
501 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) {
502 syslog(LOG_ERR, "%s: %m", ttyn);
505 crmod = digit = lower = upper = 0;
509 if (read(STDIN_FILENO, &cs, 1) <= 0)
511 if ((c = cs&0177) == 0)
514 /* PPP detection state machine..
516 PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
517 PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
519 Derived from code from Michael Hancock, <michaelh@cet.co.jp>
520 and Erik 'PPP' Olson, <eriko@wrq.com>
523 if (PP && (cs == PPP_FRAME)) {
525 } else if (ppp_state == 1 && cs == PPP_STATION) {
527 } else if (ppp_state == 2 && cs == PPP_ESCAPE) {
529 } else if ((ppp_state == 2 && cs == PPP_CONTROL)
530 || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
532 } else if (ppp_state == 4 && cs == PPP_LCP_HI) {
534 } else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
541 if (c == EOT || c == CTRL('d'))
543 if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) {
551 else if (c == ERASE || c == '\b' || c == 0177) {
554 if (cfgetospeed(&tmode) >= 1200)
560 } else if (c == KILL || c == CTRL('u')) {
562 if (cfgetospeed(&tmode) < 1200)
564 /* this is the way they do it down under ... */
570 } else if (isdigit(c))
572 if (IG && (c <= ' ' || c > 0176))
577 signal(SIGINT, SIG_IGN);
581 if ((upper && !lower && !LC) || UC)
582 for (np = name; *np; np++)
585 return (1 + ppp_connection);
590 register const char *s;
593 speed_t ospeed = cfgetospeed(&tmode);
596 while (isdigit(*s)) {
601 if (*s == '.' && isdigit(s[1])) {
609 * If no delay needed, or output speed is
610 * not comprehensible, then don't try to delay.
612 if (pad == 0 || ospeed <= 0)
616 * Round up by a half a character frame, and then do the delay.
617 * Too bad there are no user program accessible programmed delays.
618 * Transmitting pad characters slows many terminals down and also
621 pad = (pad * ospeed + 50000) / 100000;
628 register const char *s;
634 char outbuf[OBUFSIZ];
645 c |= partab[c&0177] & 0200;
650 outbuf[obufcnt++] = c;
651 if (obufcnt >= OBUFSIZ)
654 write(STDOUT_FILENO, &c, 1);
661 write(STDOUT_FILENO, outbuf, obufcnt);
680 static char linebuf[512];
683 * This is certainly slow, but it avoids having to include
684 * stdio.h unnecessarily. Issue files should be small anyway.
686 while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) {
687 if (linebuf[i] == '\n') {
688 /* Don't rely on newline mode, assume raw */
697 return i ? linebuf : 0;
702 register const char *cp;
704 extern char editedhost[];
706 char *slash, db[100];
708 static struct utsname kerninfo;
710 if (!*kerninfo.sysname)
721 slash = strrchr(ttyn, '/');
722 if (slash == (char *) 0)
736 (void)setlocale(LC_TIME, Lo);
737 (void)strftime(db, sizeof(db), "%+", localtime(&t));
742 puts(kerninfo.sysname);
746 puts(kerninfo.machine);
750 puts(kerninfo.release);
754 puts(kerninfo.version);