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