xref: /minix3/libexec/getty/main.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
184d9c625SLionel Sambuc /*	$NetBSD: main.c,v 1.64 2013/08/12 13:54:33 joerg Exp $	*/
2a06e2ab3SBen Gras 
3a06e2ab3SBen Gras /*-
4a06e2ab3SBen Gras  * Copyright (c) 1980, 1993
5a06e2ab3SBen Gras  *	The Regents of the University of California.  All rights reserved.
6a06e2ab3SBen Gras  *
7a06e2ab3SBen Gras  * Redistribution and use in source and binary forms, with or without
8a06e2ab3SBen Gras  * modification, are permitted provided that the following conditions
9a06e2ab3SBen Gras  * are met:
10a06e2ab3SBen Gras  * 1. Redistributions of source code must retain the above copyright
11a06e2ab3SBen Gras  *    notice, this list of conditions and the following disclaimer.
12a06e2ab3SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
13a06e2ab3SBen Gras  *    notice, this list of conditions and the following disclaimer in the
14a06e2ab3SBen Gras  *    documentation and/or other materials provided with the distribution.
15a06e2ab3SBen Gras  * 3. Neither the name of the University nor the names of its contributors
16a06e2ab3SBen Gras  *    may be used to endorse or promote products derived from this software
17a06e2ab3SBen Gras  *    without specific prior written permission.
18a06e2ab3SBen Gras  *
19a06e2ab3SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20a06e2ab3SBen Gras  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21a06e2ab3SBen Gras  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22a06e2ab3SBen Gras  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23a06e2ab3SBen Gras  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24a06e2ab3SBen Gras  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25a06e2ab3SBen Gras  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26a06e2ab3SBen Gras  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27a06e2ab3SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28a06e2ab3SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29a06e2ab3SBen Gras  * SUCH DAMAGE.
30a06e2ab3SBen Gras  */
31a06e2ab3SBen Gras 
32a06e2ab3SBen Gras #include <sys/cdefs.h>
33a06e2ab3SBen Gras 
34a06e2ab3SBen Gras #ifndef lint
35a06e2ab3SBen Gras __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
36a06e2ab3SBen Gras  The Regents of the University of California.  All rights reserved.");
37a06e2ab3SBen Gras #endif /* not lint */
38a06e2ab3SBen Gras 
39a06e2ab3SBen Gras #ifndef lint
40a06e2ab3SBen Gras #if 0
41a06e2ab3SBen Gras static char sccsid[] = "from: @(#)main.c	8.1 (Berkeley) 6/20/93";
42a06e2ab3SBen Gras #else
4384d9c625SLionel Sambuc __RCSID("$NetBSD: main.c,v 1.64 2013/08/12 13:54:33 joerg Exp $");
44a06e2ab3SBen Gras #endif
45a06e2ab3SBen Gras #endif /* not lint */
46a06e2ab3SBen Gras 
47a06e2ab3SBen Gras #include <sys/param.h>
48a06e2ab3SBen Gras #include <sys/ioctl.h>
49a06e2ab3SBen Gras #include <sys/resource.h>
50a06e2ab3SBen Gras #include <sys/utsname.h>
51a06e2ab3SBen Gras 
52a06e2ab3SBen Gras #include <ctype.h>
53a06e2ab3SBen Gras #include <errno.h>
54a06e2ab3SBen Gras #include <fcntl.h>
55a06e2ab3SBen Gras #include <limits.h>
56a06e2ab3SBen Gras #include <pwd.h>
57a06e2ab3SBen Gras #include <setjmp.h>
58a06e2ab3SBen Gras #include <signal.h>
5984d9c625SLionel Sambuc #include <stdio.h>
60a06e2ab3SBen Gras #include <stdlib.h>
61a06e2ab3SBen Gras #include <string.h>
62a06e2ab3SBen Gras #include <syslog.h>
63a06e2ab3SBen Gras #include <term.h>
6484d9c625SLionel Sambuc #include <termios.h>
65a06e2ab3SBen Gras #include <time.h>
66a06e2ab3SBen Gras #include <ttyent.h>
67a06e2ab3SBen Gras #include <unistd.h>
68a06e2ab3SBen Gras #include <util.h>
69a06e2ab3SBen Gras 
70a06e2ab3SBen Gras #include "gettytab.h"
71a06e2ab3SBen Gras #include "pathnames.h"
72a06e2ab3SBen Gras #include "extern.h"
73a06e2ab3SBen Gras 
74a06e2ab3SBen Gras extern char editedhost[];
75a06e2ab3SBen Gras 
76a06e2ab3SBen Gras /*
77a06e2ab3SBen Gras  * Set the amount of running time that getty should accumulate
78a06e2ab3SBen Gras  * before deciding that something is wrong and exit.
79a06e2ab3SBen Gras  */
80a06e2ab3SBen Gras #define GETTY_TIMEOUT	60 /* seconds */
81a06e2ab3SBen Gras 
82a06e2ab3SBen Gras /* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
83a06e2ab3SBen Gras 
84a06e2ab3SBen Gras #define PPP_FRAME           0x7e  /* PPP Framing character */
85a06e2ab3SBen Gras #define PPP_STATION         0xff  /* "All Station" character */
86a06e2ab3SBen Gras #define PPP_ESCAPE          0x7d  /* Escape Character */
87a06e2ab3SBen Gras #define PPP_CONTROL         0x03  /* PPP Control Field */
88a06e2ab3SBen Gras #define PPP_CONTROL_ESCAPED 0x23  /* PPP Control Field, escaped */
89a06e2ab3SBen Gras #define PPP_LCP_HI          0xc0  /* LCP protocol - high byte */
90a06e2ab3SBen Gras #define PPP_LCP_LOW         0x21  /* LCP protocol - low byte */
91a06e2ab3SBen Gras 
92a06e2ab3SBen Gras struct termios tmode, omode;
93a06e2ab3SBen Gras 
94a06e2ab3SBen Gras int crmod, digit_or_punc, lower, upper;
95a06e2ab3SBen Gras 
96a06e2ab3SBen Gras char	hostname[MAXHOSTNAMELEN + 1];
97a06e2ab3SBen Gras struct	utsname kerninfo;
98a06e2ab3SBen Gras char	name[LOGIN_NAME_MAX];
99a06e2ab3SBen Gras char	dev[] = _PATH_DEV;
100a06e2ab3SBen Gras char	ttyn[32];
101a06e2ab3SBen Gras char	lockfile[512];
102a06e2ab3SBen Gras uid_t	ttyowner;
103a06e2ab3SBen Gras char	*rawttyn;
104a06e2ab3SBen Gras 
105a06e2ab3SBen Gras #define	OBUFSIZ		128
106a06e2ab3SBen Gras #define	TABBUFSIZ	512
107a06e2ab3SBen Gras 
108a06e2ab3SBen Gras char	defent[TABBUFSIZ];
109a06e2ab3SBen Gras char	tabent[TABBUFSIZ];
110a06e2ab3SBen Gras 
111a06e2ab3SBen Gras char	*env[128];
112a06e2ab3SBen Gras 
113a06e2ab3SBen Gras const unsigned char partab[] = {
114a06e2ab3SBen Gras 	0001,0201,0201,0001,0201,0001,0001,0201,
115a06e2ab3SBen Gras 	0202,0004,0003,0205,0005,0206,0201,0001,
116a06e2ab3SBen Gras 	0201,0001,0001,0201,0001,0201,0201,0001,
117a06e2ab3SBen Gras 	0001,0201,0201,0001,0201,0001,0001,0201,
118a06e2ab3SBen Gras 	0200,0000,0000,0200,0000,0200,0200,0000,
119a06e2ab3SBen Gras 	0000,0200,0200,0000,0200,0000,0000,0200,
120a06e2ab3SBen Gras 	0000,0200,0200,0000,0200,0000,0000,0200,
121a06e2ab3SBen Gras 	0200,0000,0000,0200,0000,0200,0200,0000,
122a06e2ab3SBen Gras 	0200,0000,0000,0200,0000,0200,0200,0000,
123a06e2ab3SBen Gras 	0000,0200,0200,0000,0200,0000,0000,0200,
124a06e2ab3SBen Gras 	0000,0200,0200,0000,0200,0000,0000,0200,
125a06e2ab3SBen Gras 	0200,0000,0000,0200,0000,0200,0200,0000,
126a06e2ab3SBen Gras 	0000,0200,0200,0000,0200,0000,0000,0200,
127a06e2ab3SBen Gras 	0200,0000,0000,0200,0000,0200,0200,0000,
128a06e2ab3SBen Gras 	0200,0000,0000,0200,0000,0200,0200,0000,
129a06e2ab3SBen Gras 	0000,0200,0200,0000,0200,0000,0000,0201
130a06e2ab3SBen Gras };
131a06e2ab3SBen Gras 
132a06e2ab3SBen Gras #define	ERASE	tmode.c_cc[VERASE]
133a06e2ab3SBen Gras #define	KILL	tmode.c_cc[VKILL]
134a06e2ab3SBen Gras #define	EOT	tmode.c_cc[VEOF]
135a06e2ab3SBen Gras 
136a06e2ab3SBen Gras static void	clearscreen(void);
137a06e2ab3SBen Gras 
13884d9c625SLionel Sambuc sigjmp_buf timeout;
139a06e2ab3SBen Gras 
14084d9c625SLionel Sambuc __dead static void
141a06e2ab3SBen Gras /*ARGSUSED*/
dingdong(int signo)142a06e2ab3SBen Gras dingdong(int signo)
143a06e2ab3SBen Gras {
144a06e2ab3SBen Gras 
145a06e2ab3SBen Gras 	(void)alarm(0);
146a06e2ab3SBen Gras 	(void)signal(SIGALRM, SIG_DFL);
14784d9c625SLionel Sambuc 	siglongjmp(timeout, 1);
148a06e2ab3SBen Gras }
149a06e2ab3SBen Gras 
15084d9c625SLionel Sambuc sigjmp_buf intrupt;
151a06e2ab3SBen Gras 
15284d9c625SLionel Sambuc __dead static void
153a06e2ab3SBen Gras /*ARGSUSED*/
interrupt(int signo)154a06e2ab3SBen Gras interrupt(int signo)
155a06e2ab3SBen Gras {
156a06e2ab3SBen Gras 
157a06e2ab3SBen Gras 	(void)signal(SIGINT, interrupt);
15884d9c625SLionel Sambuc 	siglongjmp(intrupt, 1);
159a06e2ab3SBen Gras }
160a06e2ab3SBen Gras 
16184d9c625SLionel Sambuc #if !defined(__minix)
162a06e2ab3SBen Gras /*
163a06e2ab3SBen Gras  * Action to take when getty is running too long.
164a06e2ab3SBen Gras  */
16584d9c625SLionel Sambuc __dead static void
166a06e2ab3SBen Gras /*ARGSUSED*/
timeoverrun(int signo)167a06e2ab3SBen Gras timeoverrun(int signo)
168a06e2ab3SBen Gras {
169a06e2ab3SBen Gras 
170a06e2ab3SBen Gras 	syslog(LOG_ERR, "getty exiting due to excessive running time");
171a06e2ab3SBen Gras 	exit(1);
172a06e2ab3SBen Gras }
17384d9c625SLionel Sambuc #endif /* !defined(__minix) */
174a06e2ab3SBen Gras 
175a06e2ab3SBen Gras static int	getname(void);
176a06e2ab3SBen Gras static void	oflush(void);
177a06e2ab3SBen Gras static void	prompt(void);
178a06e2ab3SBen Gras static int	putchr(int);
179a06e2ab3SBen Gras static void	putf(const char *);
180a06e2ab3SBen Gras static void	xputs(const char *);
181a06e2ab3SBen Gras 
182a06e2ab3SBen Gras #define putpad(s) tputs(s, 1, putchr)
183a06e2ab3SBen Gras 
184a06e2ab3SBen Gras int
main(int argc,char * argv[],char * envp[])185a06e2ab3SBen Gras main(int argc, char *argv[], char *envp[])
186a06e2ab3SBen Gras {
187a06e2ab3SBen Gras 	const char *progname;
18884d9c625SLionel Sambuc 	int repcnt = 0, failopenlogged = 0, first_time = 1;
189a06e2ab3SBen Gras 	struct rlimit limit;
190a06e2ab3SBen Gras 	struct passwd *pw;
191a06e2ab3SBen Gras 	int rval;
19284d9c625SLionel Sambuc 	/* this is used past the siglongjmp, so make sure it is not cached
19384d9c625SLionel Sambuc 	   in registers that might become invalid. */
19484d9c625SLionel Sambuc 	volatile int uugetty = 0;
19584d9c625SLionel Sambuc 	const char * volatile tname = "default";
196a06e2ab3SBen Gras 
197a06e2ab3SBen Gras 	(void)signal(SIGINT, SIG_IGN);
198a06e2ab3SBen Gras 	openlog("getty", LOG_PID, LOG_AUTH);
199a06e2ab3SBen Gras 	(void)gethostname(hostname, sizeof(hostname));
200a06e2ab3SBen Gras 	hostname[sizeof(hostname) - 1] = '\0';
201a06e2ab3SBen Gras 	if (hostname[0] == '\0')
202a06e2ab3SBen Gras 		(void)strlcpy(hostname, "Amnesiac", sizeof(hostname));
203a06e2ab3SBen Gras 	(void)uname(&kerninfo);
204a06e2ab3SBen Gras 
205a06e2ab3SBen Gras 	progname = getprogname();
206a06e2ab3SBen Gras 	if (progname[0] == 'u' && progname[1] == 'u')
207a06e2ab3SBen Gras 		uugetty = 1;
208a06e2ab3SBen Gras 
209a06e2ab3SBen Gras 	/*
210a06e2ab3SBen Gras 	 * Find id of uucp login (if present) so we can chown tty properly.
211a06e2ab3SBen Gras 	 */
212a06e2ab3SBen Gras 	if (uugetty && (pw = getpwnam("uucp")))
213a06e2ab3SBen Gras 		ttyowner = pw->pw_uid;
214a06e2ab3SBen Gras 	else
215a06e2ab3SBen Gras 		ttyowner = 0;
216a06e2ab3SBen Gras 
217a06e2ab3SBen Gras 	/*
218a06e2ab3SBen Gras 	 * Limit running time to deal with broken or dead lines.
219a06e2ab3SBen Gras 	 */
22084d9c625SLionel Sambuc #if !defined(__minix)
221a06e2ab3SBen Gras 	(void)signal(SIGXCPU, timeoverrun);
222ac5b3e53SLionel Sambuc #endif /* !defined(__minix) */
223a06e2ab3SBen Gras 	limit.rlim_max = RLIM_INFINITY;
224a06e2ab3SBen Gras 	limit.rlim_cur = GETTY_TIMEOUT;
225a06e2ab3SBen Gras 	(void)setrlimit(RLIMIT_CPU, &limit);
226a06e2ab3SBen Gras 
227a06e2ab3SBen Gras 	/*
228a06e2ab3SBen Gras 	 * The following is a work around for vhangup interactions
229a06e2ab3SBen Gras 	 * which cause great problems getting window systems started.
230a06e2ab3SBen Gras 	 * If the tty line is "-", we do the old style getty presuming
231a06e2ab3SBen Gras 	 * that the file descriptors are already set up for us.
232a06e2ab3SBen Gras 	 * J. Gettys - MIT Project Athena.
233a06e2ab3SBen Gras 	 */
234a06e2ab3SBen Gras 	if (argc <= 2 || strcmp(argv[2], "-") == 0) {
235a06e2ab3SBen Gras 		(void)strlcpy(ttyn, ttyname(0), sizeof(ttyn));
236a06e2ab3SBen Gras 	}
237a06e2ab3SBen Gras 	else {
238a06e2ab3SBen Gras 		int i;
239a06e2ab3SBen Gras 
240a06e2ab3SBen Gras 		rawttyn = argv[2];
241a06e2ab3SBen Gras 		(void)strlcpy(ttyn, dev, sizeof(ttyn));
242a06e2ab3SBen Gras 		(void)strlcat(ttyn, argv[2], sizeof(ttyn));
243a06e2ab3SBen Gras 		if (uugetty)  {
244a06e2ab3SBen Gras 			(void)chown(ttyn, ttyowner, 0);
245a06e2ab3SBen Gras 			(void)strlcpy(lockfile, _PATH_LOCK,
246a06e2ab3SBen Gras 				sizeof(lockfile));
247a06e2ab3SBen Gras 			(void)strlcat(lockfile, argv[2],
248a06e2ab3SBen Gras 				sizeof(lockfile));
249a06e2ab3SBen Gras 			/*
250a06e2ab3SBen Gras 			 * wait for lockfiles to go away before we try
251a06e2ab3SBen Gras 			 * to open
252a06e2ab3SBen Gras 			 */
253a06e2ab3SBen Gras 			if (pidlock(lockfile, 0, 0, 0) != 0)  {
254a06e2ab3SBen Gras 				syslog(LOG_ERR,
255a06e2ab3SBen Gras 					"%s: can't create lockfile", ttyn);
256a06e2ab3SBen Gras 				exit(1);
257a06e2ab3SBen Gras 			}
258a06e2ab3SBen Gras 			(void)unlink(lockfile);
259a06e2ab3SBen Gras 		}
260a06e2ab3SBen Gras 		if (strcmp(argv[0], "+") != 0) {
261a06e2ab3SBen Gras 			(void)chown(ttyn, ttyowner, 0);
262a06e2ab3SBen Gras 			(void)chmod(ttyn, 0600);
26384d9c625SLionel Sambuc #if !defined(__minix)
264a06e2ab3SBen Gras 			(void)revoke(ttyn);
26584d9c625SLionel Sambuc #endif /* !defined(__minix) */
266a06e2ab3SBen Gras 			if (ttyaction(ttyn, "getty", "root"))
267a06e2ab3SBen Gras 				syslog(LOG_WARNING, "%s: ttyaction failed",
268a06e2ab3SBen Gras 					ttyn);
269a06e2ab3SBen Gras 			/*
270a06e2ab3SBen Gras 			 * Delay the open so DTR stays down long enough
271a06e2ab3SBen Gras 			 * to be detected.
272a06e2ab3SBen Gras 			 */
273a06e2ab3SBen Gras 			(void)sleep(2);
274a06e2ab3SBen Gras 			while ((i = open(ttyn, O_RDWR)) == -1) {
275a06e2ab3SBen Gras 				if ((repcnt % 10 == 0) &&
276a06e2ab3SBen Gras 				    (errno != ENXIO || !failopenlogged)) {
277a06e2ab3SBen Gras 					syslog(LOG_WARNING, "%s: %m", ttyn);
278a06e2ab3SBen Gras 					closelog();
279a06e2ab3SBen Gras 					failopenlogged = 1;
280a06e2ab3SBen Gras 				}
281a06e2ab3SBen Gras 				repcnt++;
282a06e2ab3SBen Gras 				(void)sleep(60);
283a06e2ab3SBen Gras 			}
284a06e2ab3SBen Gras 			if (uugetty && pidlock(lockfile, 0, 0, 0) != 0)  {
285a06e2ab3SBen Gras 				syslog(LOG_ERR, "%s: can't create lockfile",
286a06e2ab3SBen Gras 					ttyn);
287a06e2ab3SBen Gras 				exit(1);
288a06e2ab3SBen Gras 			}
289a06e2ab3SBen Gras 			if (uugetty)
290a06e2ab3SBen Gras 				(void)chown(lockfile, ttyowner, 0);
291a06e2ab3SBen Gras 			(void)login_tty(i);
292a06e2ab3SBen Gras 		}
293a06e2ab3SBen Gras 	}
294a06e2ab3SBen Gras 
295a06e2ab3SBen Gras 	/* Start with default tty settings */
296a06e2ab3SBen Gras 	if (tcgetattr(0, &tmode) < 0) {
297a06e2ab3SBen Gras 		syslog(LOG_ERR, "%s: %m", ttyn);
298a06e2ab3SBen Gras 		exit(1);
299a06e2ab3SBen Gras 	}
300a06e2ab3SBen Gras 	omode = tmode;
301a06e2ab3SBen Gras 
302a06e2ab3SBen Gras 	gettable("default", defent);
303a06e2ab3SBen Gras 	gendefaults();
304a06e2ab3SBen Gras 	if (argc > 1)
305a06e2ab3SBen Gras 		tname = argv[1];
306a06e2ab3SBen Gras 	for (;;) {
307*0a6a1f1dSLionel Sambuc #if !defined(__minix)
308a06e2ab3SBen Gras 		int off;
309*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
310a06e2ab3SBen Gras 
311a06e2ab3SBen Gras 		rval = 0;
312a06e2ab3SBen Gras 		gettable(tname, tabent);
313a06e2ab3SBen Gras 		if (OPset || EPset || APset)
314a06e2ab3SBen Gras 			APset++, OPset++, EPset++;
315a06e2ab3SBen Gras 		setdefaults();
316*0a6a1f1dSLionel Sambuc #if !defined(__minix)
317a06e2ab3SBen Gras 		off = 0;
318*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
319a06e2ab3SBen Gras 		(void)tcflush(0, TCIOFLUSH);	/* clear out the crap */
320*0a6a1f1dSLionel Sambuc #if !defined(__minix)
321a06e2ab3SBen Gras 		(void)ioctl(0, FIONBIO, &off);	/* turn off non-blocking mode */
322a06e2ab3SBen Gras 		(void)ioctl(0, FIOASYNC, &off);	/* ditto for async mode */
32384d9c625SLionel Sambuc #endif /* !defined(__minix) */
324a06e2ab3SBen Gras 
325a06e2ab3SBen Gras 		if (IS)
326a06e2ab3SBen Gras 			(void)cfsetispeed(&tmode, (speed_t)IS);
327a06e2ab3SBen Gras 		else if (SP)
328a06e2ab3SBen Gras 			(void)cfsetispeed(&tmode, (speed_t)SP);
329a06e2ab3SBen Gras 		if (OS)
330a06e2ab3SBen Gras 			(void)cfsetospeed(&tmode, (speed_t)OS);
331a06e2ab3SBen Gras 		else if (SP)
332a06e2ab3SBen Gras 			(void)cfsetospeed(&tmode, (speed_t)SP);
333a06e2ab3SBen Gras 		setflags(0);
334a06e2ab3SBen Gras 		setchars();
335a06e2ab3SBen Gras 		if (tcsetattr(0, TCSANOW, &tmode) < 0) {
336a06e2ab3SBen Gras 			syslog(LOG_ERR, "%s: %m", ttyn);
337a06e2ab3SBen Gras 			exit(1);
338a06e2ab3SBen Gras 		}
339a06e2ab3SBen Gras 		if (AB) {
340a06e2ab3SBen Gras 			tname = autobaud();
341a06e2ab3SBen Gras 			continue;
342a06e2ab3SBen Gras 		}
343a06e2ab3SBen Gras 		if (PS) {
344a06e2ab3SBen Gras 			tname = portselector();
345a06e2ab3SBen Gras 			continue;
346a06e2ab3SBen Gras 		}
347a06e2ab3SBen Gras 		if (CS)
348a06e2ab3SBen Gras 			clearscreen();
349a06e2ab3SBen Gras 		if (CL && *CL)
350a06e2ab3SBen Gras 			putpad(CL);
351a06e2ab3SBen Gras 		edithost(HE);
352a06e2ab3SBen Gras 
353a06e2ab3SBen Gras 		/*
354a06e2ab3SBen Gras 		 * If this is the first time through this, and an
355a06e2ab3SBen Gras 		 * issue file has been given, then send it.
356a06e2ab3SBen Gras 		 */
357a06e2ab3SBen Gras 		if (first_time != 0 && IF != NULL) {
358a06e2ab3SBen Gras 			char buf[_POSIX2_LINE_MAX];
359a06e2ab3SBen Gras 			FILE *fp;
360a06e2ab3SBen Gras 
361a06e2ab3SBen Gras 			if ((fp = fopen(IF, "r")) != NULL) {
362a06e2ab3SBen Gras 				while (fgets(buf, sizeof(buf) - 1, fp) != NULL)
363a06e2ab3SBen Gras 					putf(buf);
364a06e2ab3SBen Gras 				(void)fclose(fp);
365a06e2ab3SBen Gras 			}
366a06e2ab3SBen Gras 		}
367a06e2ab3SBen Gras 		first_time = 0;
368a06e2ab3SBen Gras 
369a06e2ab3SBen Gras 		if (IM && *IM)
370a06e2ab3SBen Gras 			putf(IM);
371a06e2ab3SBen Gras 		oflush();
37284d9c625SLionel Sambuc 		if (sigsetjmp(timeout, 1)) {
373a06e2ab3SBen Gras 			tmode.c_ispeed = tmode.c_ospeed = 0;
374a06e2ab3SBen Gras 			(void)tcsetattr(0, TCSANOW, &tmode);
375a06e2ab3SBen Gras 			exit(1);
376a06e2ab3SBen Gras 		}
377a06e2ab3SBen Gras 		if (TO) {
378a06e2ab3SBen Gras 			(void)signal(SIGALRM, dingdong);
379a06e2ab3SBen Gras 			(void)alarm((unsigned int)TO);
380a06e2ab3SBen Gras 		}
381a06e2ab3SBen Gras 		if (NN) {
382a06e2ab3SBen Gras 			name[0] = '\0';
383a06e2ab3SBen Gras 			lower = 1;
384a06e2ab3SBen Gras 			upper = digit_or_punc = 0;
385a06e2ab3SBen Gras 		} else if (AL) {
386a06e2ab3SBen Gras 			const char *p = AL;
387a06e2ab3SBen Gras 			char *q = name;
388a06e2ab3SBen Gras 
389a06e2ab3SBen Gras 			while (*p && q < &name[sizeof name - 1]) {
390a06e2ab3SBen Gras 				if (isupper((unsigned char)*p))
391a06e2ab3SBen Gras 					upper = 1;
392a06e2ab3SBen Gras 				else if (islower((unsigned char)*p))
393a06e2ab3SBen Gras 					lower = 1;
394a06e2ab3SBen Gras 				else if (isdigit((unsigned char)*p))
395a06e2ab3SBen Gras 					digit_or_punc = 1;
396a06e2ab3SBen Gras 				*q++ = *p++;
397a06e2ab3SBen Gras 			}
398a06e2ab3SBen Gras 		} else if ((rval = getname()) == 2) {
399a06e2ab3SBen Gras 			setflags(2);
400a06e2ab3SBen Gras 			(void)execle(PP, "ppplogin", ttyn, (char *) 0, env);
401a06e2ab3SBen Gras 			syslog(LOG_ERR, "%s: %m", PP);
402a06e2ab3SBen Gras 			exit(1);
403a06e2ab3SBen Gras 		}
404a06e2ab3SBen Gras 
405a06e2ab3SBen Gras 		if (rval || AL || NN) {
406a06e2ab3SBen Gras 			int i;
407a06e2ab3SBen Gras 
408a06e2ab3SBen Gras 			oflush();
409a06e2ab3SBen Gras 			(void)alarm(0);
410a06e2ab3SBen Gras 			(void)signal(SIGALRM, SIG_DFL);
411a06e2ab3SBen Gras 			if (name[0] == '-') {
412a06e2ab3SBen Gras 				xputs("user names may not start with '-'.");
413a06e2ab3SBen Gras 				continue;
414a06e2ab3SBen Gras 			}
415a06e2ab3SBen Gras 			if (!(upper || lower || digit_or_punc))
416a06e2ab3SBen Gras 				continue;
417a06e2ab3SBen Gras 			setflags(2);
418a06e2ab3SBen Gras 			if (crmod) {
419a06e2ab3SBen Gras 				tmode.c_iflag |= ICRNL;
420a06e2ab3SBen Gras 				tmode.c_oflag |= ONLCR;
421a06e2ab3SBen Gras 			}
422a06e2ab3SBen Gras #if XXX
423a06e2ab3SBen Gras 			if (upper || UC)
424a06e2ab3SBen Gras 				tmode.sg_flags |= LCASE;
425a06e2ab3SBen Gras 			if (lower || LC)
426a06e2ab3SBen Gras 				tmode.sg_flags &= ~LCASE;
427a06e2ab3SBen Gras #endif
428a06e2ab3SBen Gras 			if (tcsetattr(0, TCSANOW, &tmode) < 0) {
429a06e2ab3SBen Gras 				syslog(LOG_ERR, "%s: %m", ttyn);
430a06e2ab3SBen Gras 				exit(1);
431a06e2ab3SBen Gras 			}
432a06e2ab3SBen Gras 			(void)signal(SIGINT, SIG_DFL);
433a06e2ab3SBen Gras 			for (i = 0; envp[i] != NULL; i++)
434a06e2ab3SBen Gras 				env[i] = envp[i];
435a06e2ab3SBen Gras 			makeenv(&env[i]);
436a06e2ab3SBen Gras 
437a06e2ab3SBen Gras 			limit.rlim_max = RLIM_INFINITY;
438a06e2ab3SBen Gras 			limit.rlim_cur = RLIM_INFINITY;
439a06e2ab3SBen Gras 			(void)setrlimit(RLIMIT_CPU, &limit);
440a06e2ab3SBen Gras 			if (NN)
441a06e2ab3SBen Gras 				(void)execle(LO, "login", AL ? "-fp" : "-p",
442a06e2ab3SBen Gras 				    NULL, env);
443a06e2ab3SBen Gras 			else
444a06e2ab3SBen Gras 				(void)execle(LO, "login", AL ? "-fp" : "-p",
445a06e2ab3SBen Gras 				    "--", name, NULL, env);
446a06e2ab3SBen Gras 			syslog(LOG_ERR, "%s: %m", LO);
447a06e2ab3SBen Gras 			exit(1);
448a06e2ab3SBen Gras 		}
449a06e2ab3SBen Gras 		(void)alarm(0);
450a06e2ab3SBen Gras 		(void)signal(SIGALRM, SIG_DFL);
451a06e2ab3SBen Gras 		(void)signal(SIGINT, SIG_IGN);
452a06e2ab3SBen Gras 		if (NX && *NX)
453a06e2ab3SBen Gras 			tname = NX;
454a06e2ab3SBen Gras 		if (uugetty)
455a06e2ab3SBen Gras 			(void)unlink(lockfile);
456a06e2ab3SBen Gras 	}
457a06e2ab3SBen Gras }
458a06e2ab3SBen Gras 
459a06e2ab3SBen Gras static int
getname(void)460a06e2ab3SBen Gras getname(void)
461a06e2ab3SBen Gras {
462a06e2ab3SBen Gras 	int c;
463a06e2ab3SBen Gras 	char *np;
464a06e2ab3SBen Gras 	unsigned char cs;
465a06e2ab3SBen Gras 	int ppp_state, ppp_connection;
466a06e2ab3SBen Gras 
467a06e2ab3SBen Gras 	/*
468a06e2ab3SBen Gras 	 * Interrupt may happen if we use CBREAK mode
469a06e2ab3SBen Gras 	 */
47084d9c625SLionel Sambuc 	if (sigsetjmp(intrupt, 1)) {
471a06e2ab3SBen Gras 		(void)signal(SIGINT, SIG_IGN);
472a06e2ab3SBen Gras 		return (0);
473a06e2ab3SBen Gras 	}
474a06e2ab3SBen Gras 	(void)signal(SIGINT, interrupt);
475a06e2ab3SBen Gras 	setflags(1);
476a06e2ab3SBen Gras 	prompt();
477a06e2ab3SBen Gras 	if (PF > 0) {
478a06e2ab3SBen Gras 		oflush();
479a06e2ab3SBen Gras 		(void)sleep((unsigned int)PF);
480a06e2ab3SBen Gras 		PF = 0;
481a06e2ab3SBen Gras 	}
482a06e2ab3SBen Gras 	if (tcsetattr(0, TCSANOW, &tmode) < 0) {
483a06e2ab3SBen Gras 		syslog(LOG_ERR, "%s: %m", ttyn);
484a06e2ab3SBen Gras 		exit(1);
485a06e2ab3SBen Gras 	}
486a06e2ab3SBen Gras 	crmod = digit_or_punc = lower = upper = 0;
487a06e2ab3SBen Gras 	ppp_state = ppp_connection = 0;
488a06e2ab3SBen Gras 	np = name;
489a06e2ab3SBen Gras 	for (;;) {
490a06e2ab3SBen Gras 		oflush();
491a06e2ab3SBen Gras 		if (read(STDIN_FILENO, &cs, 1) <= 0)
492a06e2ab3SBen Gras 			exit(0);
493a06e2ab3SBen Gras 		if ((c = cs&0177) == 0)
494a06e2ab3SBen Gras 			return (0);
495a06e2ab3SBen Gras 
496a06e2ab3SBen Gras 		/*
497a06e2ab3SBen Gras 		 * PPP detection state machine..
498a06e2ab3SBen Gras 		 * Look for sequences:
499a06e2ab3SBen Gras 		 * PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
500a06e2ab3SBen Gras 		 * PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
501a06e2ab3SBen Gras 		 * See RFC1662.
502a06e2ab3SBen Gras 		 * Derived from code from Michael Hancock <michaelh@cet.co.jp>
503a06e2ab3SBen Gras 		 * and Erik 'PPP' Olson <eriko@wrq.com>
504a06e2ab3SBen Gras 		 */
505a06e2ab3SBen Gras 		if (PP && cs == PPP_FRAME) {
506a06e2ab3SBen Gras 			ppp_state = 1;
507a06e2ab3SBen Gras 		} else if (ppp_state == 1 && cs == PPP_STATION) {
508a06e2ab3SBen Gras 			ppp_state = 2;
509a06e2ab3SBen Gras 		} else if (ppp_state == 2 && cs == PPP_ESCAPE) {
510a06e2ab3SBen Gras 			ppp_state = 3;
511a06e2ab3SBen Gras 		} else if ((ppp_state == 2 && cs == PPP_CONTROL) ||
512a06e2ab3SBen Gras 		    (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
513a06e2ab3SBen Gras 			ppp_state = 4;
514a06e2ab3SBen Gras 		} else if (ppp_state == 4 && cs == PPP_LCP_HI) {
515a06e2ab3SBen Gras 			ppp_state = 5;
516a06e2ab3SBen Gras 		} else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
517a06e2ab3SBen Gras 			ppp_connection = 1;
518a06e2ab3SBen Gras 			break;
519a06e2ab3SBen Gras 		} else {
520a06e2ab3SBen Gras 			ppp_state = 0;
521a06e2ab3SBen Gras 		}
522a06e2ab3SBen Gras 
523a06e2ab3SBen Gras 		if (c == EOT)
524a06e2ab3SBen Gras 			exit(1);
525a06e2ab3SBen Gras 		if (c == '\r' || c == '\n' ||
526a06e2ab3SBen Gras 		    np >= &name[LOGIN_NAME_MAX - 1]) {
527a06e2ab3SBen Gras 			*np = '\0';
528a06e2ab3SBen Gras 			putf("\r\n");
529a06e2ab3SBen Gras 			break;
530a06e2ab3SBen Gras 		}
531a06e2ab3SBen Gras 		if (islower(c))
532a06e2ab3SBen Gras 			lower = 1;
533a06e2ab3SBen Gras 		else if (isupper(c))
534a06e2ab3SBen Gras 			upper = 1;
535a06e2ab3SBen Gras 		else if (c == ERASE || c == '#' || c == '\b') {
536a06e2ab3SBen Gras 			if (np > name) {
537a06e2ab3SBen Gras 				np--;
538a06e2ab3SBen Gras 				if (cfgetospeed(&tmode) >= 1200)
539a06e2ab3SBen Gras 					xputs("\b \b");
540a06e2ab3SBen Gras 				else
541a06e2ab3SBen Gras 					putchr(cs);
542a06e2ab3SBen Gras 			}
543a06e2ab3SBen Gras 			continue;
544a06e2ab3SBen Gras 		} else if (c == KILL || c == '@') {
545a06e2ab3SBen Gras 			putchr(cs);
546a06e2ab3SBen Gras 			putchr('\r');
547a06e2ab3SBen Gras 			if (cfgetospeed(&tmode) < 1200)
548a06e2ab3SBen Gras 				putchr('\n');
549a06e2ab3SBen Gras 			/* this is the way they do it down under ... */
550a06e2ab3SBen Gras 			else if (np > name)
551a06e2ab3SBen Gras 				xputs(
552a06e2ab3SBen Gras 				    "                                     \r");
553a06e2ab3SBen Gras 			prompt();
554a06e2ab3SBen Gras 			np = name;
555a06e2ab3SBen Gras 			continue;
556a06e2ab3SBen Gras 		} else if (isdigit(c) || c == '_')
557a06e2ab3SBen Gras 			digit_or_punc = 1;
558a06e2ab3SBen Gras 		if (IG && (c <= ' ' || c > 0176))
559a06e2ab3SBen Gras 			continue;
560a06e2ab3SBen Gras 		*np++ = c;
561a06e2ab3SBen Gras 		putchr(cs);
562a06e2ab3SBen Gras 
563a06e2ab3SBen Gras 		/*
564a06e2ab3SBen Gras 		 * An MS-Windows direct connect PPP "client" won't send its
565a06e2ab3SBen Gras 		 * first PPP packet until we respond to its "CLIENT" poll
566a06e2ab3SBen Gras 		 * with a CRLF sequence.  We cater to yet another broken
567a06e2ab3SBen Gras 		 * implementation of a previously-standard protocol...
568a06e2ab3SBen Gras 		 */
569a06e2ab3SBen Gras 		*np = '\0';
570a06e2ab3SBen Gras 		if (strstr(name, "CLIENT"))
571a06e2ab3SBen Gras 			putf("\r\n");
572a06e2ab3SBen Gras 	}
573a06e2ab3SBen Gras 	(void)signal(SIGINT, SIG_IGN);
574a06e2ab3SBen Gras 	*np = 0;
575a06e2ab3SBen Gras 	if (c == '\r')
576a06e2ab3SBen Gras 		crmod = 1;
577a06e2ab3SBen Gras 	if ((upper && !lower && !LC) || UC)
578a06e2ab3SBen Gras 		for (np = name; *np; np++)
579a06e2ab3SBen Gras 			*np = tolower((unsigned char)*np);
580a06e2ab3SBen Gras 	return (1 + ppp_connection);
581a06e2ab3SBen Gras }
582a06e2ab3SBen Gras 
583a06e2ab3SBen Gras static void
xputs(const char * s)584a06e2ab3SBen Gras xputs(const char *s)
585a06e2ab3SBen Gras {
586a06e2ab3SBen Gras 	while (*s)
587a06e2ab3SBen Gras 		putchr(*s++);
588a06e2ab3SBen Gras }
589a06e2ab3SBen Gras 
590a06e2ab3SBen Gras char	outbuf[OBUFSIZ];
591a06e2ab3SBen Gras size_t	obufcnt = 0;
592a06e2ab3SBen Gras 
593a06e2ab3SBen Gras static int
putchr(int cc)594a06e2ab3SBen Gras putchr(int cc)
595a06e2ab3SBen Gras {
596a06e2ab3SBen Gras 	unsigned char c;
597a06e2ab3SBen Gras 
598a06e2ab3SBen Gras 	c = cc;
599a06e2ab3SBen Gras 	if (!NP) {
600a06e2ab3SBen Gras 		c |= partab[c&0177] & 0200;
601a06e2ab3SBen Gras 		if (OP)
602a06e2ab3SBen Gras 			c ^= 0200;
603a06e2ab3SBen Gras 	}
604a06e2ab3SBen Gras 	if (!UB) {
605a06e2ab3SBen Gras 		outbuf[obufcnt++] = c;
606a06e2ab3SBen Gras 		if (obufcnt >= OBUFSIZ)
607a06e2ab3SBen Gras 			oflush();
608a06e2ab3SBen Gras 		return 1;
609a06e2ab3SBen Gras 	}
610a06e2ab3SBen Gras 	return write(STDOUT_FILENO, &c, 1);
611a06e2ab3SBen Gras }
612a06e2ab3SBen Gras 
613a06e2ab3SBen Gras static void
oflush(void)614a06e2ab3SBen Gras oflush(void)
615a06e2ab3SBen Gras {
616a06e2ab3SBen Gras 	if (obufcnt)
617a06e2ab3SBen Gras 		(void)write(STDOUT_FILENO, outbuf, obufcnt);
618a06e2ab3SBen Gras 	obufcnt = 0;
619a06e2ab3SBen Gras }
620a06e2ab3SBen Gras 
621a06e2ab3SBen Gras static void
prompt(void)622a06e2ab3SBen Gras prompt(void)
623a06e2ab3SBen Gras {
624a06e2ab3SBen Gras 
625a06e2ab3SBen Gras 	putf(LM);
626a06e2ab3SBen Gras 	if (CO)
627a06e2ab3SBen Gras 		putchr('\n');
628a06e2ab3SBen Gras }
629a06e2ab3SBen Gras 
630a06e2ab3SBen Gras static void
putf(const char * cp)631a06e2ab3SBen Gras putf(const char *cp)
632a06e2ab3SBen Gras {
633a06e2ab3SBen Gras 	time_t t;
634a06e2ab3SBen Gras 	char *slash, db[100];
635a06e2ab3SBen Gras 
636a06e2ab3SBen Gras 	while (*cp) {
637a06e2ab3SBen Gras 		if (*cp != '%') {
638a06e2ab3SBen Gras 			putchr(*cp++);
639a06e2ab3SBen Gras 			continue;
640a06e2ab3SBen Gras 		}
641a06e2ab3SBen Gras 		switch (*++cp) {
642a06e2ab3SBen Gras 
643a06e2ab3SBen Gras 		case 't':
644a06e2ab3SBen Gras 			if ((slash = strstr(ttyn, "/pts/")) == NULL)
645a06e2ab3SBen Gras 				slash = strrchr(ttyn, '/');
646a06e2ab3SBen Gras 			if (slash == NULL)
647a06e2ab3SBen Gras 				xputs(ttyn);
648a06e2ab3SBen Gras 			else
649a06e2ab3SBen Gras 				xputs(&slash[1]);
650a06e2ab3SBen Gras 			break;
651a06e2ab3SBen Gras 
652a06e2ab3SBen Gras 		case 'h':
653a06e2ab3SBen Gras 			xputs(editedhost);
654a06e2ab3SBen Gras 			break;
655a06e2ab3SBen Gras 
656a06e2ab3SBen Gras 		case 'd':
657a06e2ab3SBen Gras 			(void)time(&t);
658a06e2ab3SBen Gras 			(void)strftime(db, sizeof(db),
659a06e2ab3SBen Gras 			    "%l:%M%p on %A, %d %B %Y", localtime(&t));
660a06e2ab3SBen Gras 			xputs(db);
661a06e2ab3SBen Gras 			break;
662a06e2ab3SBen Gras 
663a06e2ab3SBen Gras 		case 's':
664a06e2ab3SBen Gras 			xputs(kerninfo.sysname);
665a06e2ab3SBen Gras 			break;
666a06e2ab3SBen Gras 
667a06e2ab3SBen Gras 		case 'm':
668a06e2ab3SBen Gras 			xputs(kerninfo.machine);
669a06e2ab3SBen Gras 			break;
670a06e2ab3SBen Gras 
671a06e2ab3SBen Gras 		case 'r':
672a06e2ab3SBen Gras 			xputs(kerninfo.release);
673a06e2ab3SBen Gras 			break;
674a06e2ab3SBen Gras 
675a06e2ab3SBen Gras 		case 'v':
676a06e2ab3SBen Gras 			xputs(kerninfo.version);
677a06e2ab3SBen Gras 			break;
678a06e2ab3SBen Gras 
679a06e2ab3SBen Gras 		case '%':
680a06e2ab3SBen Gras 			putchr('%');
681a06e2ab3SBen Gras 			break;
682a06e2ab3SBen Gras 		}
683a06e2ab3SBen Gras 		if (*cp)
684a06e2ab3SBen Gras 			cp++;
685a06e2ab3SBen Gras 	}
686a06e2ab3SBen Gras }
687a06e2ab3SBen Gras 
688a06e2ab3SBen Gras static void
clearscreen(void)689a06e2ab3SBen Gras clearscreen(void)
690a06e2ab3SBen Gras {
691a06e2ab3SBen Gras 	struct ttyent *typ;
692a06e2ab3SBen Gras 	int err;
693a06e2ab3SBen Gras 
694a06e2ab3SBen Gras 	if (rawttyn == NULL)
695a06e2ab3SBen Gras 		return;
696a06e2ab3SBen Gras 
697a06e2ab3SBen Gras 	typ = getttynam(rawttyn);
698a06e2ab3SBen Gras 
699a06e2ab3SBen Gras 	if ((typ == NULL) || (typ->ty_type == NULL) ||
700a06e2ab3SBen Gras 	    (typ->ty_type[0] == 0))
701a06e2ab3SBen Gras 		return;
702a06e2ab3SBen Gras 
703a06e2ab3SBen Gras 	if (setupterm(typ->ty_type, 0, &err) == ERR)
704a06e2ab3SBen Gras 		return;
705a06e2ab3SBen Gras 
706a06e2ab3SBen Gras 	if (clear_screen)
707a06e2ab3SBen Gras 		putpad(clear_screen);
708a06e2ab3SBen Gras 
709a06e2ab3SBen Gras 	del_curterm(cur_term);
710a06e2ab3SBen Gras 	cur_term = NULL;
711a06e2ab3SBen Gras }
712