]>
git.saurik.com Git - apple/system_cmds.git/blob - getty.tproj/main.c
ee1361d1fbdac979ac9b0e5bdee4d0d815c6d3c0
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Portions copyright (c) 2007 Apple Inc. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
37 static const char copyright
[] =
38 "@(#) Copyright (c) 1980, 1993\n\
39 The Regents of the University of California. All rights reserved.\n";
44 static char sccsid
[] = "@(#)from: main.c 8.1 (Berkeley) 6/20/93";
46 static const char rcsid
[] =
47 "$FreeBSD: src/libexec/getty/main.c,v 1.47 2005/04/06 17:42:24 stefanf Exp $";
50 #include <sys/param.h>
51 #include <sys/ioctl.h>
53 #include <sys/resource.h>
55 #include <sys/ttydefaults.h>
56 #include <sys/utsname.h>
73 #include <TargetConditionals.h>
78 #include "pathnames.h"
81 * Set the amount of running time that getty should accumulate
82 * before deciding that something is wrong and exit.
84 #define GETTY_TIMEOUT 60 /* seconds */
87 #define CTRL(x) (x&037)
89 /* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
91 #define PPP_FRAME 0x7e /* PPP Framing character */
92 #define PPP_STATION 0xff /* "All Station" character */
93 #define PPP_ESCAPE 0x7d /* Escape Character */
94 #define PPP_CONTROL 0x03 /* PPP Control Field */
95 #define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */
96 #define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */
97 #define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */
99 /* original mode; flags've been reset using values from <sys/ttydefaults.h> */
100 struct termios omode
;
102 struct termios tmode
;
104 int crmod
, digit
, lower
, upper
;
106 char hostname
[MAXHOSTNAMELEN
];
107 char name
[MAXLOGNAME
*3];
108 char dev
[] = _PATH_DEV
;
112 #define TABBUFSIZ 512
119 0001,0201,0201,0001,0201,0001,0001,0201,
120 0202,0004,0003,0205,0005,0206,0201,0001,
121 0201,0001,0001,0201,0001,0201,0201,0001,
122 0001,0201,0201,0001,0201,0001,0001,0201,
123 0200,0000,0000,0200,0000,0200,0200,0000,
124 0000,0200,0200,0000,0200,0000,0000,0200,
125 0000,0200,0200,0000,0200,0000,0000,0200,
126 0200,0000,0000,0200,0000,0200,0200,0000,
127 0200,0000,0000,0200,0000,0200,0200,0000,
128 0000,0200,0200,0000,0200,0000,0000,0200,
129 0000,0200,0200,0000,0200,0000,0000,0200,
130 0200,0000,0000,0200,0000,0200,0200,0000,
131 0000,0200,0200,0000,0200,0000,0000,0200,
132 0200,0000,0000,0200,0000,0200,0200,0000,
133 0200,0000,0000,0200,0000,0200,0200,0000,
134 0000,0200,0200,0000,0200,0000,0000,0201
137 #define ERASE tmode.c_cc[VERASE]
138 #define KILL tmode.c_cc[VKILL]
139 #define EOT tmode.c_cc[VEOF]
143 static void defttymode(void);
144 static void dingdong(int);
145 static void dogettytab(void);
146 static int getname(void);
147 static void interrupt(int);
148 static void oflush(void);
149 static void prompt(void);
150 static void putchr(int);
151 static void putf(const char *);
152 static void putpad(const char *);
153 static void puts(const char *);
154 static void timeoverrun(int);
155 static char *getline(int);
156 static void setttymode(int);
157 static int opentty(const char *, int);
162 dingdong(int signo __unused
)
171 interrupt(int signo __unused
)
177 * Action to take when getty is running too long.
180 timeoverrun(int signo __unused
)
183 syslog(LOG_ERR
, "getty exiting due to excessive running time");
188 main(int argc
, char *argv
[])
190 extern char **environ
;
191 int first_sleep
= 1, first_time
= 1;
195 int ttyopenmode
= O_RDWR
;
198 signal(SIGINT
, SIG_IGN
);
199 signal(SIGQUIT
, SIG_IGN
);
201 openlog("getty", LOG_ODELAY
|LOG_CONS
|LOG_PID
, LOG_AUTH
);
202 gethostname(hostname
, sizeof(hostname
) - 1);
203 hostname
[sizeof(hostname
) - 1] = '\0';
204 if (hostname
[0] == '\0')
205 strcpy(hostname
, "Amnesiac");
208 * Limit running time to deal with broken or dead lines.
210 (void)signal(SIGXCPU
, timeoverrun
);
211 limit
.rlim_max
= RLIM_INFINITY
;
212 limit
.rlim_cur
= GETTY_TIMEOUT
;
213 (void)setrlimit(RLIMIT_CPU
, &limit
);
222 * The following is a work around for vhangup interactions
223 * which cause great problems getting window systems started.
224 * If the tty line is "-", we do the old style getty presuming
225 * that the file descriptors are already set up for us.
226 * J. Gettys - MIT Project Athena.
228 if (argc
<= 2 || strcmp(argv
[2], "-") == 0)
231 // <rdar://problem/5178373>
232 char* n
= ttyname(STDIN_FILENO
);
234 strlcpy(ttyn
, n
, sizeof(ttyn
));
236 syslog(LOG_ERR
, "ttyname %m");
241 strcpy(ttyn
, ttyname(STDIN_FILENO
));
245 strncat(ttyn
, argv
[2], sizeof(ttyn
)-sizeof(dev
));
246 if (strcmp(argv
[0], "+") != 0) {
252 * Do the first scan through gettytab.
253 * Terminal mode parameters will be wrong until
254 * defttymode() called, but they're irrelevant for
255 * the initial setup of the terminal device.
259 #if defined(__APPLE__) && !TARGET_OS_EMBEDDED
260 if (strncmp(ttyn
, _PATH_CONSOLE
, sizeof(ttyn
)) == 0)
261 ttyopenmode
|= O_POPUP
;
264 * Init or answer modem sequence has been specified.
268 if (!opentty(ttyn
, ttyopenmode
))
270 if (!opentty(ttyn
, O_RDWR
|O_NONBLOCK
))
278 if (getty_chat(IC
, CT
, DC
) > 0) {
279 syslog(LOG_ERR
, "modem init problem on %s", ttyn
);
280 (void)tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
);
289 rfds
= 1 << 0; /* FD_SET */
292 i
= select(32, (fd_set
*)&rfds
, (fd_set
*)NULL
,
293 (fd_set
*)NULL
, RT
? &to
: NULL
);
295 syslog(LOG_ERR
, "select %s: %m", ttyn
);
297 syslog(LOG_NOTICE
, "recycle tty %s", ttyn
);
298 (void)tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
);
299 exit(0); /* recycle for init */
301 i
= getty_chat(AC
, CT
, DC
);
303 syslog(LOG_ERR
, "modem answer problem on %s", ttyn
);
304 (void)tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
);
307 } else { /* maybe blocking open */
309 if (!opentty(ttyn
, ttyopenmode
| (NC
? O_NONBLOCK
: 0 )))
311 if (!opentty(ttyn
, O_RDWR
| (NC
? O_NONBLOCK
: 0 )))
322 * if a delay was specified then sleep for that
323 * number of seconds before writing the initial prompt
325 if (first_sleep
&& DE
) {
327 /* remove any noise */
328 (void)tcflush(STDIN_FILENO
, TCIOFLUSH
);
339 tname
= portselector();
347 /* if this is the first time through this, and an
348 issue file has been given, then send it */
349 if (first_time
&& IF
) {
352 if ((fd
= open(IF
, O_RDONLY
)) != -1) {
355 while ((cp
= getline(fd
)) != NULL
) {
363 if (IM
&& *IM
&& !(PL
&& PP
))
365 if (setjmp(timeout
)) {
366 cfsetispeed(&tmode
, B0
);
367 cfsetospeed(&tmode
, B0
);
368 (void)tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
);
372 signal(SIGALRM
, dingdong
);
381 while (*p
&& q
< &name
[sizeof name
- 1]) {
384 else if (islower(*p
))
386 else if (isdigit(*p
))
390 } else if (!(PL
&& PP
))
392 if (rval
== 2 || (PL
&& PP
)) {
395 limit
.rlim_max
= RLIM_INFINITY
;
396 limit
.rlim_cur
= RLIM_INFINITY
;
397 (void)setrlimit(RLIMIT_CPU
, &limit
);
398 execle(PP
, "ppplogin", ttyn
, (char *) 0, env
);
399 syslog(LOG_ERR
, "%s: %m", PP
);
401 } else if (rval
|| AL
) {
406 signal(SIGALRM
, SIG_DFL
);
409 if (name
[0] == '-') {
410 puts("user names may not start with '-'.");
413 if (!(upper
|| lower
|| digit
)) {
416 "invalid auto-login name: %s", AL
);
423 tmode
.c_iflag
|= ICRNL
;
424 tmode
.c_oflag
|= ONLCR
;
428 tmode
.sg_flags
|= LCASE
;
430 tmode
.sg_flags
&= ~LCASE
;
432 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
) < 0) {
433 syslog(LOG_ERR
, "tcsetattr %s: %m", ttyn
);
436 signal(SIGINT
, SIG_DFL
);
437 for (i
= 0; environ
[i
] != (char *)0; i
++)
441 limit
.rlim_max
= RLIM_INFINITY
;
442 limit
.rlim_cur
= RLIM_INFINITY
;
443 (void)setrlimit(RLIMIT_CPU
, &limit
);
445 // <rdar://problem/3205179>
446 execle(LO
, "login", AL
? "-fp1" : "-p1", name
,
448 execle(LO
, "login", AL
? "-fp" : "-p", name
,
451 syslog(LOG_ERR
, "%s: %m", LO
);
455 signal(SIGALRM
, SIG_DFL
);
456 signal(SIGINT
, SIG_IGN
);
465 opentty(const char *tty
, int flags
)
468 int failopenlogged
= 0;
470 while ((i
= open(tty
, flags
)) == -1)
472 if (!failopenlogged
) {
473 syslog(LOG_ERR
, "open %s: %m", tty
);
478 if (login_tty(i
) < 0) {
480 if (daemon(0,0) < 0) {
481 syslog(LOG_ERR
,"daemon: %m");
486 if (login_tty(i
) < 0) {
487 syslog(LOG_ERR
, "login_tty %s: %m", tty
);
499 /* Start with default tty settings. */
500 if (tcgetattr(STDIN_FILENO
, &tmode
) < 0) {
501 syslog(LOG_ERR
, "tcgetattr %s: %m", ttyn
);
504 omode
= tmode
; /* fill c_cc for dogettytab() */
507 * Don't rely on the driver too much, and initialize crucial
508 * things according to <sys/ttydefaults.h>. Avoid clobbering
509 * the c_cc[] settings however, the console drivers might wish
510 * to leave their idea of the preferred VERASE key value
513 tmode
.c_iflag
= TTYDEF_IFLAG
;
514 tmode
.c_oflag
= TTYDEF_OFLAG
;
515 tmode
.c_lflag
= TTYDEF_LFLAG
;
516 tmode
.c_cflag
= TTYDEF_CFLAG
;
518 tmode
.c_cflag
|= CLOCAL
;
527 (void)tcflush(STDIN_FILENO
, TCIOFLUSH
); /* clear out the crap */
528 ioctl(STDIN_FILENO
, FIONBIO
, &off
); /* turn off non-blocking mode */
529 ioctl(STDIN_FILENO
, FIOASYNC
, &off
); /* ditto for async mode */
532 cfsetispeed(&tmode
, speed(IS
));
534 cfsetispeed(&tmode
, speed(SP
));
536 cfsetospeed(&tmode
, speed(OS
));
538 cfsetospeed(&tmode
, speed(SP
));
543 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
) < 0) {
544 syslog(LOG_ERR
, "tcsetattr %s: %m", ttyn
);
557 int ppp_connection
= 0;
560 * Interrupt may happen if we use CBREAK mode
562 if (setjmp(intrupt
)) {
563 signal(SIGINT
, SIG_IGN
);
566 signal(SIGINT
, interrupt
);
574 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tmode
) < 0) {
575 syslog(LOG_ERR
, "%s: %m", ttyn
);
578 crmod
= digit
= lower
= upper
= 0;
582 if (read(STDIN_FILENO
, &cs
, 1) <= 0)
584 if ((c
= cs
&0177) == 0)
587 /* PPP detection state machine..
589 PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
590 PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
592 Derived from code from Michael Hancock, <michaelh@cet.co.jp>
593 and Erik 'PPP' Olson, <eriko@wrq.com>
596 if (PP
&& (cs
== PPP_FRAME
)) {
598 } else if (ppp_state
== 1 && cs
== PPP_STATION
) {
600 } else if (ppp_state
== 2 && cs
== PPP_ESCAPE
) {
602 } else if ((ppp_state
== 2 && cs
== PPP_CONTROL
)
603 || (ppp_state
== 3 && cs
== PPP_CONTROL_ESCAPED
)) {
605 } else if (ppp_state
== 4 && cs
== PPP_LCP_HI
) {
607 } else if (ppp_state
== 5 && cs
== PPP_LCP_LOW
) {
614 if (c
== EOT
|| c
== CTRL('d'))
616 if (c
== '\r' || c
== '\n' || np
>= &name
[sizeof name
-1]) {
624 else if (c
== ERASE
|| c
== '\b' || c
== 0177) {
627 if (cfgetospeed(&tmode
) >= 1200)
633 } else if (c
== KILL
|| c
== CTRL('u')) {
635 if (cfgetospeed(&tmode
) < 1200)
637 /* this is the way they do it down under ... */
641 digit
= lower
= upper
= 0;
644 } else if (isdigit(c
))
646 if (IG
&& (c
<= ' ' || c
> 0176))
651 signal(SIGINT
, SIG_IGN
);
655 if ((upper
&& !lower
&& !LC
) || UC
)
656 for (np
= name
; *np
; np
++)
659 return (1 + ppp_connection
);
663 putpad(const char *s
)
666 speed_t ospeed
= cfgetospeed(&tmode
);
669 while (isdigit(*s
)) {
674 if (*s
== '.' && isdigit(s
[1])) {
682 * If no delay needed, or output speed is
683 * not comprehensible, then don't try to delay.
685 if (pad
== 0 || ospeed
<= 0)
689 * Round up by a half a character frame, and then do the delay.
690 * Too bad there are no user program accessible programmed delays.
691 * Transmitting pad characters slows many terminals down and also
694 pad
= (pad
* ospeed
+ 50000) / 100000;
706 char outbuf
[OBUFSIZ
];
716 c
|= partab
[c
&0177] & 0200;
721 outbuf
[obufcnt
++] = c
;
722 if (obufcnt
>= OBUFSIZ
)
725 write(STDOUT_FILENO
, &c
, 1);
732 write(STDOUT_FILENO
, outbuf
, obufcnt
);
750 static char linebuf
[512];
753 * This is certainly slow, but it avoids having to include
754 * stdio.h unnecessarily. Issue files should be small anyway.
756 while (i
< (sizeof linebuf
- 3) && read(fd
, linebuf
+i
, 1)==1) {
757 if (linebuf
[i
] == '\n') {
758 /* Don't rely on newline mode, assume raw */
767 return i
? linebuf
: 0;
773 extern char editedhost
[];
775 char *slash
, db
[100];
777 static struct utsname kerninfo
;
779 if (!*kerninfo
.sysname
)
790 slash
= strrchr(ttyn
, '/');
791 if (slash
== (char *) 0)
805 (void)setlocale(LC_TIME
, Lo
);
806 (void)strftime(db
, sizeof(db
), DF
, localtime(&t
));
811 puts(kerninfo
.sysname
);
815 puts(kerninfo
.machine
);
819 puts(kerninfo
.release
);
823 puts(kerninfo
.version
);
836 * Read a gettytab database entry and perform necessary quirks.
842 /* Read the database entry. */
846 * Avoid inheriting the parity values from the default entry
847 * if any of them is set in the current entry.
848 * Mixing different parity settings is unreasonable.
850 if (OPset
|| EPset
|| APset
|| NPset
)
851 OPset
= EPset
= APset
= NPset
= 1;
853 /* Fill in default values for unset capabilities. */