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.4 2004/03/26 00:30:12 cpressey 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 **);
160 * Action to take when getty is running too long.
163 timeoverrun(int signo
)
165 syslog(LOG_ERR
, "getty exiting due to excessive running time");
170 main(int argc
, char **argv
)
172 extern char **environ
;
174 int first_sleep
= 1, first_time
= 1;
178 signal(SIGINT
, SIG_IGN
);
179 signal(SIGQUIT
, SIG_IGN
);
181 openlog("getty", LOG_ODELAY
|LOG_CONS
|LOG_PID
, LOG_AUTH
);
182 gethostname(hostname
, sizeof(hostname
) - 1);
183 hostname
[sizeof(hostname
) - 1] = '\0';
184 if (hostname
[0] == '\0')
185 strcpy(hostname
, "Amnesiac");
188 * Limit running time to deal with broken or dead lines.
190 (void)signal(SIGXCPU
, timeoverrun
);
191 limit
.rlim_max
= RLIM_INFINITY
;
192 limit
.rlim_cur
= GETTY_TIMEOUT
;
193 (void)setrlimit(RLIMIT_CPU
, &limit
);
195 gettable("default", defent
);
202 * The following is a work around for vhangup interactions
203 * which cause great problems getting window systems started.
204 * If the tty line is "-", we do the old style getty presuming
205 * that the file descriptors are already set up for us.
206 * J. Gettys - MIT Project Athena.
208 if (argc
<= 2 || strcmp(argv
[2], "-") == 0)
209 strcpy(ttyn
, ttyname(STDIN_FILENO
));
212 strncat(ttyn
, argv
[2], sizeof(ttyn
)-sizeof(dev
));
213 if (strcmp(argv
[0], "+") != 0) {
218 gettable(tname
, tabent
);
220 /* Init modem sequence has been specified
223 if (!opentty(ttyn
, O_RDWR
|O_NONBLOCK
))
225 setdefttymode(tname
);
226 if (getty_chat(IC
, CT
, DC
) > 0) {
227 syslog(LOG_ERR
, "modem init problem on %s", ttyn
);
228 (void)tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
);
235 struct timeval timeout
;
237 if (!opentty(ttyn
, O_RDWR
|O_NONBLOCK
))
239 setdefttymode(tname
);
240 rfds
= 1 << 0; /* FD_SET */
243 i
= select(32, (fd_set
*)&rfds
, NULL
,
244 NULL
, RT
? &timeout
: NULL
);
246 syslog(LOG_ERR
, "select %s: %m", ttyn
);
248 syslog(LOG_NOTICE
, "recycle tty %s", ttyn
);
249 (void)tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
);
250 exit(0); /* recycle for init */
252 i
= getty_chat(AC
, CT
, DC
);
254 syslog(LOG_ERR
, "modem answer problem on %s", ttyn
);
255 (void)tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
);
258 } else { /* maybe blocking open */
259 if (!opentty(ttyn
, O_RDWR
| (NC
? O_NONBLOCK
: 0 )))
265 /* Start with default tty settings */
266 if (tcgetattr(STDIN_FILENO
, &tmode
) < 0) {
267 syslog(LOG_ERR
, "tcgetattr %s: %m", ttyn
);
271 * Don't rely on the driver too much, and initialize crucial
272 * things according to <sys/ttydefaults.h>. Avoid clobbering
273 * the c_cc[] settings however, the console drivers might wish
274 * to leave their idea of the preferred VERASE key value
277 tmode
.c_iflag
= TTYDEF_IFLAG
;
278 tmode
.c_oflag
= TTYDEF_OFLAG
;
279 tmode
.c_lflag
= TTYDEF_LFLAG
;
280 tmode
.c_cflag
= TTYDEF_CFLAG
;
281 tmode
.c_cflag
|= (NC
? CLOCAL
: 0);
287 * if a delay was specified then sleep for that
288 * number of seconds before writing the initial prompt
290 if (first_sleep
&& DE
) {
292 /* remove any noise */
293 (void)tcflush(STDIN_FILENO
, TCIOFLUSH
);
297 setttymode(tname
, 0);
303 tname
= portselector();
310 /* if this is the first time through this, and an
311 issue file has been given, then send it */
312 if (first_time
&& IF
) {
315 if ((fd
= open(IF
, O_RDONLY
)) != -1) {
318 while ((cp
= getline(fd
)) != NULL
) {
326 if (IM
&& *IM
&& !(PL
&& PP
))
328 if (setjmp(timeout
)) {
329 cfsetispeed(&tmode
, B0
);
330 cfsetospeed(&tmode
, B0
);
331 (void)tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
);
335 signal(SIGALRM
, dingdong
);
342 while (*p
&& q
< &name
[sizeof name
- 1]) {
345 else if (islower(*p
))
347 else if (isdigit(*p
))
351 } else if (!(PL
&& PP
))
353 if (rval
== 2 || (PL
&& PP
)) {
356 limit
.rlim_max
= RLIM_INFINITY
;
357 limit
.rlim_cur
= RLIM_INFINITY
;
358 (void)setrlimit(RLIMIT_CPU
, &limit
);
359 execle(PP
, "ppplogin", ttyn
, NULL
, env
);
360 syslog(LOG_ERR
, "%s: %m", PP
);
362 } else if (rval
|| AL
) {
367 signal(SIGALRM
, SIG_DFL
);
368 if (name
[0] == '-') {
369 puts("user names may not start with '-'.");
372 if (!(upper
|| lower
|| digit
))
376 tmode
.c_iflag
|= ICRNL
;
377 tmode
.c_oflag
|= ONLCR
;
381 tmode
.sg_flags
|= LCASE
;
383 tmode
.sg_flags
&= ~LCASE
;
385 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
) < 0) {
386 syslog(LOG_ERR
, "tcsetattr %s: %m", ttyn
);
389 signal(SIGINT
, SIG_DFL
);
390 for (i
= 0; environ
[i
] != NULL
; i
++)
394 limit
.rlim_max
= RLIM_INFINITY
;
395 limit
.rlim_cur
= RLIM_INFINITY
;
396 (void)setrlimit(RLIMIT_CPU
, &limit
);
397 execle(LO
, "login", AL
? "-fp" : "-p", name
,
399 syslog(LOG_ERR
, "%s: %m", LO
);
403 signal(SIGALRM
, SIG_DFL
);
404 signal(SIGINT
, SIG_IGN
);
411 opentty(const char *ttyn
, int flags
)
414 int failopenlogged
= 0;
416 while (j
< 10 && (i
= open(ttyn
, flags
)) == -1)
418 if (((j
% 10) == 0) && (errno
!= ENXIO
|| !failopenlogged
)) {
419 syslog(LOG_ERR
, "open %s: %m", ttyn
);
426 syslog(LOG_ERR
, "open %s: %m", ttyn
);
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", ttyn
);
447 setdefttymode(const char *tname
)
449 if (tcgetattr(STDIN_FILENO
, &tmode
) < 0) {
450 syslog(LOG_ERR
, "tcgetattr %s: %m", ttyn
);
453 tmode
.c_iflag
= TTYDEF_IFLAG
;
454 tmode
.c_oflag
= TTYDEF_OFLAG
;
455 tmode
.c_lflag
= TTYDEF_LFLAG
;
456 tmode
.c_cflag
= TTYDEF_CFLAG
;
458 setttymode(tname
, 1);
462 setttymode(const char *tname
, int raw
)
466 gettable(tname
, tabent
);
467 if (OPset
|| EPset
|| APset
)
468 APset
++, OPset
++, EPset
++;
470 (void)tcflush(STDIN_FILENO
, TCIOFLUSH
); /* clear out the crap */
471 ioctl(STDIN_FILENO
, FIONBIO
, &off
); /* turn off non-blocking mode */
472 ioctl(STDIN_FILENO
, FIOASYNC
, &off
); /* ditto for async mode */
475 cfsetispeed(&tmode
, speed(IS
));
477 cfsetispeed(&tmode
, speed(SP
));
479 cfsetospeed(&tmode
, speed(OS
));
481 cfsetospeed(&tmode
, speed(SP
));
486 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
) < 0) {
487 syslog(LOG_ERR
, "tcsetattr %s: %m", ttyn
);
500 int ppp_connection
= 0;
503 * Interrupt may happen if we use CBREAK mode
505 if (setjmp(intrupt
)) {
506 signal(SIGINT
, SIG_IGN
);
509 signal(SIGINT
, interrupt
);
517 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
) < 0) {
518 syslog(LOG_ERR
, "%s: %m", ttyn
);
521 crmod
= digit
= lower
= upper
= 0;
525 if (read(STDIN_FILENO
, &cs
, 1) <= 0)
527 if ((c
= cs
&0177) == 0)
530 /* PPP detection state machine..
532 PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
533 PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
535 Derived from code from Michael Hancock, <michaelh@cet.co.jp>
536 and Erik 'PPP' Olson, <eriko@wrq.com>
539 if (PP
&& (cs
== PPP_FRAME
)) {
541 } else if (ppp_state
== 1 && cs
== PPP_STATION
) {
543 } else if (ppp_state
== 2 && cs
== PPP_ESCAPE
) {
545 } else if ((ppp_state
== 2 && cs
== PPP_CONTROL
)
546 || (ppp_state
== 3 && cs
== PPP_CONTROL_ESCAPED
)) {
548 } else if (ppp_state
== 4 && cs
== PPP_LCP_HI
) {
550 } else if (ppp_state
== 5 && cs
== PPP_LCP_LOW
) {
557 if (c
== EOT
|| c
== CTRL('d'))
559 if (c
== '\r' || c
== '\n' || np
>= &name
[sizeof name
-1]) {
567 else if (c
== ERASE
|| c
== '\b' || c
== 0177) {
570 if (cfgetospeed(&tmode
) >= 1200)
576 } else if (c
== KILL
|| c
== CTRL('u')) {
578 if (cfgetospeed(&tmode
) < 1200)
580 /* this is the way they do it down under ... */
586 } else if (isdigit(c
))
588 if (IG
&& (c
<= ' ' || c
> 0176))
593 signal(SIGINT
, SIG_IGN
);
597 if ((upper
&& !lower
&& !LC
) || UC
)
598 for (np
= name
; *np
; np
++)
601 return (1 + ppp_connection
);
605 putpad(const char *s
)
610 ospeed
= cfgetospeed(&tmode
);
613 while (isdigit(*s
)) {
618 if (*s
== '.' && isdigit(s
[1])) {
626 * If no delay needed, or output speed is
627 * not comprehensible, then don't try to delay.
629 if (pad
== 0 || ospeed
<= 0)
633 * Round up by a half a character frame, and then do the delay.
634 * Too bad there are no user program accessible programmed delays.
635 * Transmitting pad characters slows many terminals down and also
638 pad
= (pad
* ospeed
+ 50000) / 100000;
650 char outbuf
[OBUFSIZ
];
660 c
|= partab
[c
&0177] & 0200;
665 outbuf
[obufcnt
++] = c
;
666 if (obufcnt
>= OBUFSIZ
)
669 write(STDOUT_FILENO
, &c
, 1);
676 write(STDOUT_FILENO
, outbuf
, obufcnt
);
693 static char linebuf
[512];
696 * This is certainly slow, but it avoids having to include
697 * stdio.h unnecessarily. Issue files should be small anyway.
699 while (i
< (sizeof linebuf
- 3) && read(fd
, linebuf
+i
, 1)==1) {
700 if (linebuf
[i
] == '\n') {
701 /* Don't rely on newline mode, assume raw */
710 return i
? linebuf
: 0;
716 extern char editedhost
[];
718 char *slash
, db
[100];
720 static struct utsname kerninfo
;
722 if (!*kerninfo
.sysname
)
733 slash
= strrchr(ttyn
, '/');
748 (void)setlocale(LC_TIME
, Lo
);
749 (void)strftime(db
, sizeof(db
), DF
, localtime(&t
));
754 puts(kerninfo
.sysname
);
758 puts(kerninfo
.machine
);
762 puts(kerninfo
.release
);
766 puts(kerninfo
.version
);