xref: /csrg-svn/libexec/getty/main.c (revision 14322)
113795Ssam #ifndef lint
2*14322Ssam static char sccsid[] = "@(#)main.c	4.5 (Berkeley) 83/08/01";
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 
3813828Skre #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 
8113828Skre jmp_buf	intrupt;
8213828Skre 
8313828Skre interrupt()
8413828Skre {
8513828Skre 
8613828Skre 	signal(SIGINT, interrupt);
8713828Skre 	longjmp(intrupt, 1);
8813828Skre }
8913828Skre 
9013795Ssam main(argc, argv)
9113795Ssam 	char *argv[];
9213795Ssam {
9313795Ssam 	char *tname;
9413795Ssam 	long allflags;
9513795Ssam 
9613828Skre 	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);
11213828Skre 		if (OPset || EPset || APset)
11313828Skre 			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);
15213831Ssam 			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');
16713831Ssam 			oflush();
16813795Ssam 			makeenv(env);
16913828Skre 			signal(SIGINT, SIG_DFL);
17013795Ssam 			execle(LO, "login", name, (char *)0, env);
17113795Ssam 			exit(1);
17213795Ssam 		}
17313795Ssam 		alarm(0);
17413795Ssam 		signal(SIGALRM, SIG_DFL);
17513828Skre 		signal(SIGINT, SIG_IGN);
17613795Ssam 		if (NX && *NX)
17713795Ssam 			tname = NX;
17813795Ssam 	}
17913795Ssam }
18013795Ssam 
18113795Ssam getname()
18213795Ssam {
18313795Ssam 	register char *np;
18413795Ssam 	register c;
18513795Ssam 	char cs;
18613795Ssam 
18713828Skre 	/*
18813831Ssam 	 * Interrupt may happen if we use CBREAK mode
18913828Skre 	 */
19013828Skre 	if (setjmp(intrupt)) {
19113828Skre 		signal(SIGINT, SIG_IGN);
19213828Skre 		return (0);
19313828Skre 	}
19413828Skre 	signal(SIGINT, interrupt);
19513795Ssam 	tmode.sg_flags = setflags(0);
19613795Ssam 	ioctl(0, TIOCSETP, &tmode);
19713795Ssam 	tmode.sg_flags = setflags(1);
19813795Ssam 	prompt();
19913885Ssam 	if (PF > 0) {
200*14322Ssam 		oflush();
20113885Ssam 		sleep(PF);
20213885Ssam 		PF = 0;
20313885Ssam 	}
20413795Ssam 	ioctl(0, TIOCSETP, &tmode);
20513795Ssam 	crmod = 0;
20613795Ssam 	upper = 0;
20713795Ssam 	lower = 0;
20813795Ssam 	digit = 0;
20913795Ssam 	np = name;
21013795Ssam 	for (;;) {
21113828Skre 		oflush();
21213795Ssam 		if (read(0, &cs, 1) <= 0)
21313795Ssam 			exit(0);
21413795Ssam 		if ((c = cs&0177) == 0)
21513795Ssam 			return (0);
21613831Ssam 		if (c == EOT)
21713795Ssam 			exit(1);
21813831Ssam 		if (c == '\r' || c == '\n' || np >= &name[16])
21913795Ssam 			break;
22013795Ssam 
22113831Ssam 		if (c >= 'a' && c <= 'z')
22213795Ssam 			lower++;
22313831Ssam 		else if (c >= 'A' && c <= 'Z') {
22413795Ssam 			upper++;
22513831Ssam 		} else if (c == ERASE || c == '#' || c == '\b') {
22613795Ssam 			if (np > name) {
22713795Ssam 				np--;
22813795Ssam 				if (tmode.sg_ospeed >= B1200)
22913795Ssam 					puts("\b \b");
23013795Ssam 				else
23113795Ssam 					putchr(cs);
23213795Ssam 			}
23313795Ssam 			continue;
23413831Ssam 		} else if (c == KILL || c == '@') {
23513795Ssam 			putchr(cs);
23613795Ssam 			putchr('\r');
23713795Ssam 			if (tmode.sg_ospeed < B1200)
23813795Ssam 				putchr('\n');
23913795Ssam 			/* this is the way they do it down under ... */
24013795Ssam 			else if (np > name)
24113795Ssam 				puts("                                     \r");
24213795Ssam 			prompt();
24313795Ssam 			np = name;
24413795Ssam 			continue;
24513795Ssam 		} else if (c == ' ')
24613795Ssam 			c = '_';
24713795Ssam 		else if (c >= '0' && c <= '9')
24813795Ssam 			digit++;
24913795Ssam 		if (IG && (c < ' ' || c > 0176))
25013795Ssam 			continue;
25113795Ssam 		*np++ = c;
25213795Ssam 		putchr(cs);
25313795Ssam 	}
25413828Skre 	signal(SIGINT, SIG_IGN);
25513795Ssam 	*np = 0;
25613795Ssam 	if (c == '\r')
25713795Ssam 		crmod++;
25813795Ssam 	if (upper && !lower && !LC || UC)
25913795Ssam 		for (np = name; *np; np++)
26013795Ssam 			if (isupper(*np))
26113795Ssam 				*np = tolower(*np);
26213795Ssam 	return (1);
26313795Ssam }
26413795Ssam 
26513795Ssam static
26613795Ssam short	tmspc10[] = {
26713795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
26813795Ssam };
26913795Ssam 
27013795Ssam putpad(s)
27113795Ssam 	register char *s;
27213795Ssam {
27313795Ssam 	register pad = 0;
27413795Ssam 	register mspc10;
27513795Ssam 
27613795Ssam 	if (isdigit(*s)) {
27713795Ssam 		while (isdigit(*s)) {
27813795Ssam 			pad *= 10;
27913795Ssam 			pad += *s++ - '0';
28013795Ssam 		}
28113795Ssam 		pad *= 10;
28213795Ssam 		if (*s == '.' && isdigit(s[1])) {
28313795Ssam 			pad += s[1] - '0';
28413795Ssam 			s += 2;
28513795Ssam 		}
28613795Ssam 	}
28713795Ssam 
28813795Ssam 	puts(s);
28913795Ssam 	/*
29013795Ssam 	 * If no delay needed, or output speed is
29113795Ssam 	 * not comprehensible, then don't try to delay.
29213795Ssam 	 */
29313795Ssam 	if (pad == 0)
29413795Ssam 		return;
29513795Ssam 	if (tmode.sg_ospeed <= 0 ||
29613795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
29713795Ssam 		return;
29813795Ssam 
29913795Ssam 	/*
30013795Ssam 	 * Round up by a half a character frame,
30113795Ssam 	 * and then do the delay.
30213795Ssam 	 * Too bad there are no user program accessible programmed delays.
30313795Ssam 	 * Transmitting pad characters slows many
30413795Ssam 	 * terminals down and also loads the system.
30513795Ssam 	 */
30613795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
30713795Ssam 	pad += mspc10 / 2;
30813795Ssam 	for (pad /= mspc10; pad > 0; pad--)
30913795Ssam 		putchr(*PC);
31013795Ssam }
31113795Ssam 
31213795Ssam puts(s)
31313795Ssam 	register char *s;
31413795Ssam {
31513795Ssam 
31613795Ssam 	while (*s)
31713795Ssam 		putchr(*s++);
31813795Ssam }
31913795Ssam 
32013828Skre char	outbuf[OBUFSIZ];
32113828Skre int	obufcnt = 0;
32213828Skre 
32313795Ssam putchr(cc)
32413795Ssam {
32513795Ssam 	char c;
32613795Ssam 
32713795Ssam 	c = cc;
32813795Ssam 	c |= partab[c&0177] & 0200;
32913795Ssam 	if (OP)
33013795Ssam 		c ^= 0200;
33113828Skre 	if (!UB) {
33213828Skre 		outbuf[obufcnt++] = c;
33313828Skre 		if (obufcnt >= OBUFSIZ)
33413828Skre 			oflush();
33513828Skre 	} else
33613828Skre 		write(1, &c, 1);
33713795Ssam }
33813795Ssam 
33913828Skre oflush()
34013828Skre {
34113828Skre 	if (obufcnt)
34213828Skre 		write(1, outbuf, obufcnt);
34313828Skre 	obufcnt = 0;
34413828Skre }
34513828Skre 
34613795Ssam prompt()
34713795Ssam {
34813795Ssam 
34913795Ssam 	putf(LM);
35013795Ssam 	if (CO)
35113795Ssam 		putchr('\n');
35213795Ssam }
35313795Ssam 
35413795Ssam putf(cp)
35513795Ssam 	register char *cp;
35613795Ssam {
35713795Ssam 	extern char editedhost[];
35813795Ssam 
35913795Ssam 	while (*cp) {
36013795Ssam 		if (*cp != '%') {
36113795Ssam 			putchr(*cp++);
36213795Ssam 			continue;
36313795Ssam 		}
36413795Ssam 		switch (*++cp) {
36513795Ssam 
36613795Ssam 		case 'h':
36713795Ssam 			puts(editedhost);
36813795Ssam 			break;
36913795Ssam 
37013795Ssam 		case '%':
37113795Ssam 			putchr('%');
37213795Ssam 			break;
37313795Ssam 		}
37413795Ssam 		cp++;
37513795Ssam 	}
37613795Ssam }
377