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 *get_line(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
= get_line(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
);