xref: /csrg-svn/libexec/getty/main.c (revision 13828)
113795Ssam #ifndef lint
2*13828Skre static char sccsid[] = "@(#)main.c	4.2 (Berkeley) 83/07/07";
313795Ssam #endif
413795Ssam 
513795Ssam /*
613795Ssam  * getty -- adapt to terminal speed on dialup, and call login
713795Ssam  *
813795Ssam  * Melbourne getty, June 83, kre.
913795Ssam  */
1013795Ssam 
1113795Ssam #include <sgtty.h>
1213795Ssam #include <signal.h>
1313795Ssam #include <ctype.h>
1413795Ssam #include <setjmp.h>
1513795Ssam #include "gettytab.h"
1613795Ssam 
1713795Ssam struct	sgttyb tmode = {
1813795Ssam 	0, 0, CERASE, CKILL, 0
1913795Ssam };
2013795Ssam struct	tchars tc = {
2113795Ssam 	CINTR, CQUIT, CSTART,
2213795Ssam 	CSTOP, CEOF, CBRK,
2313795Ssam };
2413795Ssam struct	ltchars ltc = {
2513795Ssam 	CSUSP, CDSUSP, CRPRNT,
2613795Ssam 	CFLUSH, CWERASE, CLNEXT
2713795Ssam };
2813795Ssam 
2913795Ssam int	crmod;
3013795Ssam int	upper;
3113795Ssam int	lower;
3213795Ssam int	digit;
3313795Ssam 
3413795Ssam char	hostname[32];
3513795Ssam char	name[16];
3613795Ssam char	*portselector();
3713795Ssam 
38*13828Skre #define	OBUFSIZ		128
3913795Ssam #define	TABBUFSIZ	512
4013795Ssam 
4113795Ssam char	defent[TABBUFSIZ];
4213795Ssam char	defstrs[TABBUFSIZ];
4313795Ssam char	tabent[TABBUFSIZ];
4413795Ssam char	tabstrs[TABBUFSIZ];
4513795Ssam 
4613795Ssam char	*env[128];
4713795Ssam 
4813795Ssam char partab[] = {
4913795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
5013795Ssam 	0202,0004,0003,0205,0005,0206,0201,0001,
5113795Ssam 	0201,0001,0001,0201,0001,0201,0201,0001,
5213795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
5313795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
5413795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
5513795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
5613795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
5713795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
5813795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
5913795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
6013795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
6113795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
6213795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
6313795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
6413795Ssam 	0000,0200,0200,0000,0200,0000,0000,0201
6513795Ssam };
6613795Ssam 
6713795Ssam #define	ERASE	tmode.sg_erase
6813795Ssam #define	KILL	tmode.sg_kill
6913795Ssam #define	EOT	tc.t_eofc
7013795Ssam 
7113795Ssam jmp_buf timeout;
7213795Ssam 
7313795Ssam dingdong()
7413795Ssam {
7513795Ssam 
7613795Ssam 	alarm(0);
7713795Ssam 	signal(SIGALRM, SIG_DFL);
7813795Ssam 	longjmp(timeout, 1);
7913795Ssam }
8013795Ssam 
81*13828Skre jmp_buf	intrupt;
82*13828Skre 
83*13828Skre interrupt()
84*13828Skre {
85*13828Skre 
86*13828Skre 	signal(SIGINT, interrupt);
87*13828Skre 	longjmp(intrupt, 1);
88*13828Skre }
89*13828Skre 
9013795Ssam main(argc, argv)
9113795Ssam 	char *argv[];
9213795Ssam {
9313795Ssam 	char *tname;
9413795Ssam 	long allflags;
9513795Ssam 
96*13828Skre 	signal(SIGINT, SIG_IGN);
9713795Ssam /*
9813795Ssam 	signal(SIGQUIT, SIG_DFL);
9913795Ssam */
10013795Ssam 	gethostname(hostname, sizeof(hostname));
10113795Ssam 	if (hostname[0] == '\0')
10213795Ssam 		strcpy(hostname, "Amnesiac");
10313795Ssam 	gettable("default", defent, defstrs);
10413795Ssam 	gendefaults();
10513795Ssam 	tname = "default";
10613795Ssam 	if (argc > 1)
10713795Ssam 		tname = argv[1];
10813795Ssam 	for (;;) {
10913795Ssam 		int ldisp = OTTYDISC;
11013795Ssam 
11113795Ssam 		gettable(tname, tabent, tabstrs);
112*13828Skre 		if (OPset || EPset || APset)
113*13828Skre 			APset++, OPset++, EPset++;
11413795Ssam 		setdefaults();
11513795Ssam 		ioctl(0, TIOCFLUSH, 0);		/* clear out the crap */
11613795Ssam 		if (IS)
11713795Ssam 			tmode.sg_ispeed = speed(IS);
11813795Ssam 		else if (SP)
11913795Ssam 			tmode.sg_ispeed = speed(SP);
12013795Ssam 		if (OS)
12113795Ssam 			tmode.sg_ospeed = speed(OS);
12213795Ssam 		else if (SP)
12313795Ssam 			tmode.sg_ospeed = speed(SP);
12413795Ssam 		tmode.sg_flags = setflags(0);
12513795Ssam 		ioctl(0, TIOCSETP, &tmode);
12613795Ssam 		setchars();
12713795Ssam 		ioctl(0, TIOCSETC, &tc);
12813795Ssam 		ioctl(0, TIOCSETD, &ldisp);
12913795Ssam 		if (HC)
13013795Ssam 			ioctl(0, TIOCHPCL, 0);
13113795Ssam 		if (PS) {
13213795Ssam 			tname = portselector();
13313795Ssam 			continue;
13413795Ssam 		}
13513795Ssam 		if (CL && *CL)
13613795Ssam 			putpad(CL);
13713795Ssam 		edithost(HE);
13813795Ssam 		if (IM && *IM)
13913795Ssam 			putf(IM);
14013795Ssam 		if (setjmp(timeout)) {
14113795Ssam 			tmode.sg_ispeed = tmode.sg_ospeed = 0;
14213795Ssam 			ioctl(0, TIOCSETP, &tmode);
14313795Ssam 			exit(1);
14413795Ssam 		}
14513795Ssam 		if (TO) {
14613795Ssam 			signal(SIGALRM, dingdong);
14713795Ssam 			alarm(TO);
14813795Ssam 		}
14913795Ssam 		if (getname()) {
15013795Ssam 			alarm(0);
15113795Ssam 			signal(SIGALRM, SIG_DFL);
15213795Ssam 			if (!(upper||lower||digit))
15313795Ssam 				continue;
15413795Ssam 			allflags = setflags(2);
15513795Ssam 			tmode.sg_flags = allflags & 0xffff;
15613795Ssam 			allflags >>= 16;
15713795Ssam 			if (crmod || NL)
15813795Ssam 				tmode.sg_flags |= CRMOD;
15913795Ssam 			if (upper || UC)
16013795Ssam 				tmode.sg_flags |= LCASE;
16113795Ssam 			if (lower || LC)
16213795Ssam 				tmode.sg_flags &= ~LCASE;
16313795Ssam 			ioctl(0, TIOCSETP, &tmode);
16413795Ssam 			ioctl(0, TIOCSLTC, &ltc);
16513795Ssam 			ioctl(0, TIOCLSET, &allflags);
16613795Ssam 			putchr('\n');
16713795Ssam 			makeenv(env);
168*13828Skre 			signal(SIGINT, SIG_DFL);
16913795Ssam 			execle(LO, "login", name, (char *)0, env);
17013795Ssam 			exit(1);
17113795Ssam 		}
17213795Ssam 		alarm(0);
17313795Ssam 		signal(SIGALRM, SIG_DFL);
174*13828Skre 		signal(SIGINT, SIG_IGN);
17513795Ssam 		if (NX && *NX)
17613795Ssam 			tname = NX;
17713795Ssam 	}
17813795Ssam }
17913795Ssam 
18013795Ssam getname()
18113795Ssam {
18213795Ssam 	register char *np;
18313795Ssam 	register c;
18413795Ssam 	char cs;
18513795Ssam 
186*13828Skre 	/*
187*13828Skre 	 * interrupt may happen if we use CBREAK mode
188*13828Skre 	 */
189*13828Skre 	if (setjmp(intrupt)) {
190*13828Skre 		signal(SIGINT, SIG_IGN);
191*13828Skre 		return (0);
192*13828Skre 	}
193*13828Skre 	signal(SIGINT, interrupt);
19413795Ssam 	tmode.sg_flags = setflags(0);
19513795Ssam 	ioctl(0, TIOCSETP, &tmode);
19613795Ssam 	tmode.sg_flags = setflags(1);
19713795Ssam 	prompt();
19813795Ssam 	ioctl(0, TIOCSETP, &tmode);
19913795Ssam 	crmod = 0;
20013795Ssam 	upper = 0;
20113795Ssam 	lower = 0;
20213795Ssam 	digit = 0;
20313795Ssam 	np = name;
20413795Ssam 	for (;;) {
205*13828Skre 		oflush();
20613795Ssam 		if (read(0, &cs, 1) <= 0)
20713795Ssam 			exit(0);
20813795Ssam 		if ((c = cs&0177) == 0)
20913795Ssam 			return (0);
21013795Ssam 		if (c==EOT)
21113795Ssam 			exit(1);
21213795Ssam 		if (c=='\r' || c=='\n' || np >= &name[16])
21313795Ssam 			break;
21413795Ssam 
21513795Ssam 		if (c>='a' && c <='z')
21613795Ssam 			lower++;
21713795Ssam 		else if (c>='A' && c<='Z') {
21813795Ssam 			upper++;
219*13828Skre 		} else if (c==ERASE || c=='#' || c=='\b') {
22013795Ssam 			if (np > name) {
22113795Ssam 				np--;
22213795Ssam 				if (tmode.sg_ospeed >= B1200)
22313795Ssam 					puts("\b \b");
22413795Ssam 				else
22513795Ssam 					putchr(cs);
22613795Ssam 			}
22713795Ssam 			continue;
228*13828Skre 		} else if (c==KILL || c=='@') {
22913795Ssam 			putchr(cs);
23013795Ssam 			putchr('\r');
23113795Ssam 			if (tmode.sg_ospeed < B1200)
23213795Ssam 				putchr('\n');
23313795Ssam 			/* this is the way they do it down under ... */
23413795Ssam 			else if (np > name)
23513795Ssam 				puts("                                     \r");
23613795Ssam 			prompt();
23713795Ssam 			np = name;
23813795Ssam 			continue;
23913795Ssam 		} else if (c == ' ')
24013795Ssam 			c = '_';
24113795Ssam 		else if (c >= '0' && c <= '9')
24213795Ssam 			digit++;
24313795Ssam 		if (IG && (c < ' ' || c > 0176))
24413795Ssam 			continue;
24513795Ssam 		*np++ = c;
24613795Ssam 		putchr(cs);
24713795Ssam 	}
248*13828Skre 	signal(SIGINT, SIG_IGN);
24913795Ssam 	*np = 0;
25013795Ssam 	if (c == '\r')
25113795Ssam 		crmod++;
25213795Ssam 	if (upper && !lower && !LC || UC)
25313795Ssam 		for (np = name; *np; np++)
25413795Ssam 			if (isupper(*np))
25513795Ssam 				*np = tolower(*np);
25613795Ssam 	return (1);
25713795Ssam }
25813795Ssam 
25913795Ssam static
26013795Ssam short	tmspc10[] = {
26113795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
26213795Ssam };
26313795Ssam 
26413795Ssam putpad(s)
26513795Ssam 	register char *s;
26613795Ssam {
26713795Ssam 	register pad = 0;
26813795Ssam 	register mspc10;
26913795Ssam 
27013795Ssam 	if (isdigit(*s)) {
27113795Ssam 		while (isdigit(*s)) {
27213795Ssam 			pad *= 10;
27313795Ssam 			pad += *s++ - '0';
27413795Ssam 		}
27513795Ssam 		pad *= 10;
27613795Ssam 		if (*s == '.' && isdigit(s[1])) {
27713795Ssam 			pad += s[1] - '0';
27813795Ssam 			s += 2;
27913795Ssam 		}
28013795Ssam 	}
28113795Ssam 
28213795Ssam 	puts(s);
28313795Ssam 	/*
28413795Ssam 	 * If no delay needed, or output speed is
28513795Ssam 	 * not comprehensible, then don't try to delay.
28613795Ssam 	 */
28713795Ssam 	if (pad == 0)
28813795Ssam 		return;
28913795Ssam 	if (tmode.sg_ospeed <= 0 ||
29013795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
29113795Ssam 		return;
29213795Ssam 
29313795Ssam 	/*
29413795Ssam 	 * Round up by a half a character frame,
29513795Ssam 	 * and then do the delay.
29613795Ssam 	 * Too bad there are no user program accessible programmed delays.
29713795Ssam 	 * Transmitting pad characters slows many
29813795Ssam 	 * terminals down and also loads the system.
29913795Ssam 	 */
30013795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
30113795Ssam 	pad += mspc10 / 2;
30213795Ssam 	for (pad /= mspc10; pad > 0; pad--)
30313795Ssam 		putchr(*PC);
30413795Ssam }
30513795Ssam 
30613795Ssam puts(s)
30713795Ssam 	register char *s;
30813795Ssam {
30913795Ssam 
31013795Ssam 	while (*s)
31113795Ssam 		putchr(*s++);
31213795Ssam }
31313795Ssam 
314*13828Skre char	outbuf[OBUFSIZ];
315*13828Skre int	obufcnt = 0;
316*13828Skre 
31713795Ssam putchr(cc)
31813795Ssam {
31913795Ssam 	char c;
32013795Ssam 
32113795Ssam 	c = cc;
32213795Ssam 	c |= partab[c&0177] & 0200;
32313795Ssam 	if (OP)
32413795Ssam 		c ^= 0200;
325*13828Skre 	if (!UB) {
326*13828Skre 		outbuf[obufcnt++] = c;
327*13828Skre 		if (obufcnt >= OBUFSIZ)
328*13828Skre 			oflush();
329*13828Skre 	} else
330*13828Skre 		write(1, &c, 1);
33113795Ssam }
33213795Ssam 
333*13828Skre oflush()
334*13828Skre {
335*13828Skre 	if (obufcnt)
336*13828Skre 		write(1, outbuf, obufcnt);
337*13828Skre 	obufcnt = 0;
338*13828Skre }
339*13828Skre 
34013795Ssam prompt()
34113795Ssam {
34213795Ssam 
34313795Ssam 	putf(LM);
34413795Ssam 	if (CO)
34513795Ssam 		putchr('\n');
34613795Ssam }
34713795Ssam 
34813795Ssam putf(cp)
34913795Ssam 	register char *cp;
35013795Ssam {
35113795Ssam 	extern char editedhost[];
35213795Ssam 
35313795Ssam 	while (*cp) {
35413795Ssam 		if (*cp != '%') {
35513795Ssam 			putchr(*cp++);
35613795Ssam 			continue;
35713795Ssam 		}
35813795Ssam 		switch (*++cp) {
35913795Ssam 
36013795Ssam 		case 'h':
36113795Ssam 			puts(editedhost);
36213795Ssam 			break;
36313795Ssam 
36413795Ssam 		case '%':
36513795Ssam 			putchr('%');
36613795Ssam 			break;
36713795Ssam 		}
36813795Ssam 		cp++;
36913795Ssam 	}
37013795Ssam }
371