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