2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/param.h>
33 #include <sys/ioctl.h>
35 #include <sys/resource.h>
37 #include <sys/ttydefaults.h>
38 #include <sys/utsname.h>
57 #include "pathnames.h"
60 * Set the amount of running time that getty should accumulate
61 * before deciding that something is wrong and exit.
63 #define GETTY_TIMEOUT 60 /* seconds */
66 #define CTRL(x) (x&037)
68 /* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
70 #define PPP_FRAME 0x7e /* PPP Framing character */
71 #define PPP_STATION 0xff /* "All Station" character */
72 #define PPP_ESCAPE 0x7d /* Escape Character */
73 #define PPP_CONTROL 0x03 /* PPP Control Field */
74 #define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */
75 #define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */
76 #define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */
78 /* original mode; flags've been reset using values from <sys/ttydefaults.h> */
83 static int crmod
, digit
, lower
, upper
;
85 char hostname
[MAXHOSTNAMELEN
];
86 static char name
[MAXLOGNAME
*3];
91 static const char *tname
;
93 static char *env
[128];
95 static char partab
[] = {
96 0001,0201,0201,0001,0201,0001,0001,0201,
97 0202,0004,0003,0205,0005,0206,0201,0001,
98 0201,0001,0001,0201,0001,0201,0201,0001,
99 0001,0201,0201,0001,0201,0001,0001,0201,
100 0200,0000,0000,0200,0000,0200,0200,0000,
101 0000,0200,0200,0000,0200,0000,0000,0200,
102 0000,0200,0200,0000,0200,0000,0000,0200,
103 0200,0000,0000,0200,0000,0200,0200,0000,
104 0200,0000,0000,0200,0000,0200,0200,0000,
105 0000,0200,0200,0000,0200,0000,0000,0200,
106 0000,0200,0200,0000,0200,0000,0000,0200,
107 0200,0000,0000,0200,0000,0200,0200,0000,
108 0000,0200,0200,0000,0200,0000,0000,0200,
109 0200,0000,0000,0200,0000,0200,0200,0000,
110 0200,0000,0000,0200,0000,0200,0200,0000,
111 0000,0200,0200,0000,0200,0000,0000,0201
114 #define ERASE tmode.c_cc[VERASE]
115 #define KILL tmode.c_cc[VKILL]
116 #define EOT tmode.c_cc[VEOF]
120 static void defttymode(void);
121 static void dingdong(int);
122 static void dogettytab(void);
123 static int getname(void);
124 static void interrupt(int);
125 static void oflush(void);
126 static void prompt(void);
127 static void putchr(int);
128 static void putf(const char *);
129 static void putpad(const char *);
130 static void puts(const char *);
131 static void timeoverrun(int);
132 static char *get_line(int);
133 static void setttymode(int);
134 static int opentty(const char *, int);
136 static jmp_buf timeout
;
139 dingdong(int signo __unused
)
145 static jmp_buf intrupt
;
148 interrupt(int signo __unused
)
154 * Action to take when getty is running too long.
157 timeoverrun(int signo __unused
)
160 syslog(LOG_ERR
, "getty exiting due to excessive running time");
165 main(int argc
, char *argv
[])
167 int first_sleep
= 1, first_time
= 1;
171 signal(SIGINT
, SIG_IGN
);
172 signal(SIGQUIT
, SIG_IGN
);
174 openlog("getty", LOG_CONS
|LOG_PID
, LOG_AUTH
);
175 gethostname(hostname
, sizeof(hostname
) - 1);
176 hostname
[sizeof(hostname
) - 1] = '\0';
177 if (hostname
[0] == '\0')
178 snprintf(hostname
, sizeof(hostname
), "Amnesiac");
181 * Limit running time to deal with broken or dead lines.
183 (void)signal(SIGXCPU
, timeoverrun
);
184 limit
.rlim_max
= RLIM_INFINITY
;
185 limit
.rlim_cur
= GETTY_TIMEOUT
;
186 (void)setrlimit(RLIMIT_CPU
, &limit
);
195 * The following is a work around for vhangup interactions
196 * which cause great problems getting window systems started.
197 * If the tty line is "-", we do the old style getty presuming
198 * that the file descriptors are already set up for us.
199 * J. Gettys - MIT Project Athena.
201 if (argc
<= 2 || strcmp(argv
[2], "-") == 0) {
202 char *n
= ttyname(STDIN_FILENO
);
204 syslog(LOG_ERR
, "ttyname: %m");
207 snprintf(ttyn
, sizeof(ttyn
), "%s", n
);
209 snprintf(ttyn
, sizeof(ttyn
), "%s%s", _PATH_DEV
, argv
[2]);
210 if (strcmp(argv
[0], "+") != 0) {
216 * Do the first scan through gettytab.
217 * Terminal mode parameters will be wrong until
218 * defttymode() called, but they're irrelevant for
219 * the initial setup of the terminal device.
224 * Init or answer modem sequence has been specified.
227 if (!opentty(ttyn
, O_RDWR
|O_NONBLOCK
))
234 if (getty_chat(IC
, CT
, DC
) > 0) {
235 syslog(LOG_ERR
, "modem init problem on %s", ttyn
);
236 (void)tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
);
250 i
= select(32, &rfds
, NULL
, NULL
, RT
? &to
: 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 )))
275 * if a delay was specified then sleep for that
276 * number of seconds before writing the initial prompt
278 if (first_sleep
&& DE
) {
280 /* remove any noise */
281 (void)tcflush(STDIN_FILENO
, TCIOFLUSH
);
292 tname
= portselector();
300 /* if this is the first time through this, and an
301 issue file has been given, then send it */
302 if (first_time
&& IF
) {
305 if ((fd
= open(IF
, O_RDONLY
)) != -1) {
308 while ((cp
= get_line(fd
)) != NULL
) {
316 if (IMP
&& *IMP
&& !(PL
&& PP
))
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
);
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
, (char *) 0, env
);
354 syslog(LOG_ERR
, "%s: %m", PP
);
356 } else if (rval
|| AL
) {
361 signal(SIGALRM
, SIG_DFL
);
364 if (name
[0] == '-') {
365 puts("user names may not start with '-'.");
368 if (!(upper
|| lower
|| digit
)) {
371 "invalid auto-login name: %s", AL
);
378 tmode
.c_iflag
|= ICRNL
;
379 tmode
.c_oflag
|= ONLCR
;
383 tmode
.sg_flags
|= LCASE
;
385 tmode
.sg_flags
&= ~LCASE
;
387 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
) < 0) {
388 syslog(LOG_ERR
, "tcsetattr %s: %m", ttyn
);
391 signal(SIGINT
, SIG_DFL
);
392 for (i
= 0; environ
[i
] != (char *)0; i
++)
396 limit
.rlim_max
= RLIM_INFINITY
;
397 limit
.rlim_cur
= RLIM_INFINITY
;
398 (void)setrlimit(RLIMIT_CPU
, &limit
);
399 execle(LO
, "login", AL
? "-fp" : "-p", name
,
401 syslog(LOG_ERR
, "%s: %m", LO
);
405 signal(SIGALRM
, SIG_DFL
);
406 signal(SIGINT
, SIG_IGN
);
415 opentty(const char *tty
, int flags
)
417 int failopenlogged
= 0, i
, saved_errno
;
419 while ((i
= open(tty
, flags
)) == -1)
422 if (!failopenlogged
) {
423 syslog(LOG_ERR
, "open %s: %m", tty
);
426 if (saved_errno
== ENOENT
)
430 if (login_tty(i
) < 0) {
431 if (daemon(0,0) < 0) {
432 syslog(LOG_ERR
,"daemon: %m");
436 if (login_tty(i
) < 0) {
437 syslog(LOG_ERR
, "login_tty %s: %m", tty
);
450 /* Start with default tty settings. */
451 if (tcgetattr(STDIN_FILENO
, &tmode
) < 0) {
452 syslog(LOG_ERR
, "tcgetattr %s: %m", ttyn
);
455 omode
= tmode
; /* fill c_cc for dogettytab() */
458 * Don't rely on the driver too much, and initialize crucial
459 * things according to <sys/ttydefaults.h>. Avoid clobbering
460 * the c_cc[] settings however, the console drivers might wish
461 * to leave their idea of the preferred VERASE key value
465 tmode
.c_iflag
= def
.c_iflag
;
466 tmode
.c_oflag
= def
.c_oflag
;
467 tmode
.c_lflag
= def
.c_lflag
;
468 tmode
.c_cflag
= def
.c_cflag
;
470 tmode
.c_cflag
|= CLOCAL
;
479 (void)tcflush(STDIN_FILENO
, TCIOFLUSH
); /* clear out the crap */
480 ioctl(STDIN_FILENO
, FIONBIO
, &off
); /* turn off non-blocking mode */
481 ioctl(STDIN_FILENO
, FIOASYNC
, &off
); /* ditto for async mode */
484 cfsetispeed(&tmode
, speed(IS
));
486 cfsetispeed(&tmode
, speed(SP
));
488 cfsetospeed(&tmode
, speed(OS
));
490 cfsetospeed(&tmode
, speed(SP
));
495 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
) < 0) {
496 syslog(LOG_ERR
, "tcsetattr %s: %m", ttyn
);
509 int ppp_connection
= 0;
512 * Interrupt may happen if we use CBREAK mode
514 if (setjmp(intrupt
)) {
515 signal(SIGINT
, SIG_IGN
);
518 signal(SIGINT
, interrupt
);
526 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
) < 0) {
527 syslog(LOG_ERR
, "%s: %m", ttyn
);
530 crmod
= digit
= lower
= upper
= 0;
534 if (read(STDIN_FILENO
, &cs
, 1) <= 0)
536 if ((c
= cs
&0177) == 0)
539 /* PPP detection state machine..
541 PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
542 PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
544 Derived from code from Michael Hancock, <michaelh@cet.co.jp>
545 and Erik 'PPP' Olson, <eriko@wrq.com>
548 if (PP
&& (cs
== PPP_FRAME
)) {
550 } else if (ppp_state
== 1 && cs
== PPP_STATION
) {
552 } else if (ppp_state
== 2 && cs
== PPP_ESCAPE
) {
554 } else if ((ppp_state
== 2 && cs
== PPP_CONTROL
)
555 || (ppp_state
== 3 && cs
== PPP_CONTROL_ESCAPED
)) {
557 } else if (ppp_state
== 4 && cs
== PPP_LCP_HI
) {
559 } else if (ppp_state
== 5 && cs
== PPP_LCP_LOW
) {
566 if (c
== EOT
|| c
== CTRL('d'))
568 if (c
== '\r' || c
== '\n' || np
>= &name
[sizeof name
-1]) {
576 else if (c
== ERASE
|| c
== '\b' || c
== 0177) {
579 if (cfgetospeed(&tmode
) >= 1200)
585 } else if (c
== KILL
|| c
== CTRL('u')) {
587 if (cfgetospeed(&tmode
) < 1200)
589 /* this is the way they do it down under ... */
593 digit
= lower
= upper
= 0;
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
);
615 putpad(const char *s
)
618 speed_t ospeed
= cfgetospeed(&tmode
);
621 while (isdigit(*s
)) {
626 if (*s
== '.' && isdigit(s
[1])) {
634 * If no delay needed, or output speed is
635 * not comprehensible, then don't try to delay.
637 if (pad
== 0 || ospeed
<= 0)
641 * Round up by a half a character frame, and then do the delay.
642 * Too bad there are no user program accessible programmed delays.
643 * Transmitting pad characters slows many terminals down and also
646 pad
= (pad
* ospeed
+ 50000) / 100000;
658 static char outbuf
[OBUFSIZ
];
659 static int obufcnt
= 0;
668 c
|= partab
[c
&0177] & 0200;
673 outbuf
[obufcnt
++] = c
;
674 if (obufcnt
>= OBUFSIZ
)
677 write(STDOUT_FILENO
, &c
, 1);
684 write(STDOUT_FILENO
, outbuf
, obufcnt
);
702 static char linebuf
[512];
705 * This is certainly slow, but it avoids having to include
706 * stdio.h unnecessarily. Issue files should be small anyway.
708 while (i
< (sizeof linebuf
- 3) && read(fd
, linebuf
+i
, 1)==1) {
709 if (linebuf
[i
] == '\n') {
710 /* Don't rely on newline mode, assume raw */
719 return i
? linebuf
: 0;
729 static struct utsname kerninfo
;
731 if (!*kerninfo
.sysname
)
742 slash
= strrchr(ttyn
, '/');
743 if (slash
== (char *) 0)
757 (void)setlocale(LC_TIME
, Lo
);
758 (void)strftime(db
, sizeof(db
), DF
, localtime(&t
));
763 puts(kerninfo
.sysname
);
767 puts(kerninfo
.machine
);
771 puts(kerninfo
.release
);
775 puts(kerninfo
.version
);
787 * Read a gettytab database entry and perform necessary quirks.
793 /* Read the database entry. */
797 * Avoid inheriting the parity values from the default entry
798 * if any of them is set in the current entry.
799 * Mixing different parity settings is unreasonable.
801 if (OPset
|| EPset
|| APset
|| NPset
)
802 OPset
= EPset
= APset
= NPset
= 1;
804 /* Fill in default values for unset capabilities. */