xref: /csrg-svn/libexec/getty/main.c (revision 13885)
113795Ssam #ifndef lint
2*13885Ssam static char sccsid[] = "@(#)main.c	4.4 (Berkeley) 83/07/09";
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();
199*13885Ssam 	if (PF > 0) {
200*13885Ssam 		sleep(PF);
201*13885Ssam 		PF = 0;
202*13885Ssam 	}
20313795Ssam 	ioctl(0, TIOCSETP, &tmode);
20413795Ssam 	crmod = 0;
20513795Ssam 	upper = 0;
20613795Ssam 	lower = 0;
20713795Ssam 	digit = 0;
20813795Ssam 	np = name;
20913795Ssam 	for (;;) {
21013828Skre 		oflush();
21113795Ssam 		if (read(0, &cs, 1) <= 0)
21213795Ssam 			exit(0);
21313795Ssam 		if ((c = cs&0177) == 0)
21413795Ssam 			return (0);
21513831Ssam 		if (c == EOT)
21613795Ssam 			exit(1);
21713831Ssam 		if (c == '\r' || c == '\n' || np >= &name[16])
21813795Ssam 			break;
21913795Ssam 
22013831Ssam 		if (c >= 'a' && c <= 'z')
22113795Ssam 			lower++;
22213831Ssam 		else if (c >= 'A' && c <= 'Z') {
22313795Ssam 			upper++;
22413831Ssam 		} else if (c == ERASE || c == '#' || c == '\b') {
22513795Ssam 			if (np > name) {
22613795Ssam 				np--;
22713795Ssam 				if (tmode.sg_ospeed >= B1200)
22813795Ssam 					puts("\b \b");
22913795Ssam 				else
23013795Ssam 					putchr(cs);
23113795Ssam 			}
23213795Ssam 			continue;
23313831Ssam 		} else if (c == KILL || c == '@') {
23413795Ssam 			putchr(cs);
23513795Ssam 			putchr('\r');
23613795Ssam 			if (tmode.sg_ospeed < B1200)
23713795Ssam 				putchr('\n');
23813795Ssam 			/* this is the way they do it down under ... */
23913795Ssam 			else if (np > name)
24013795Ssam 				puts("                                     \r");
24113795Ssam 			prompt();
24213795Ssam 			np = name;
24313795Ssam 			continue;
24413795Ssam 		} else if (c == ' ')
24513795Ssam 			c = '_';
24613795Ssam 		else if (c >= '0' && c <= '9')
24713795Ssam 			digit++;
24813795Ssam 		if (IG && (c < ' ' || c > 0176))
24913795Ssam 			continue;
25013795Ssam 		*np++ = c;
25113795Ssam 		putchr(cs);
25213795Ssam 	}
25313828Skre 	signal(SIGINT, SIG_IGN);
25413795Ssam 	*np = 0;
25513795Ssam 	if (c == '\r')
25613795Ssam 		crmod++;
25713795Ssam 	if (upper && !lower && !LC || UC)
25813795Ssam 		for (np = name; *np; np++)
25913795Ssam 			if (isupper(*np))
26013795Ssam 				*np = tolower(*np);
26113795Ssam 	return (1);
26213795Ssam }
26313795Ssam 
26413795Ssam static
26513795Ssam short	tmspc10[] = {
26613795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
26713795Ssam };
26813795Ssam 
26913795Ssam putpad(s)
27013795Ssam 	register char *s;
27113795Ssam {
27213795Ssam 	register pad = 0;
27313795Ssam 	register mspc10;
27413795Ssam 
27513795Ssam 	if (isdigit(*s)) {
27613795Ssam 		while (isdigit(*s)) {
27713795Ssam 			pad *= 10;
27813795Ssam 			pad += *s++ - '0';
27913795Ssam 		}
28013795Ssam 		pad *= 10;
28113795Ssam 		if (*s == '.' && isdigit(s[1])) {
28213795Ssam 			pad += s[1] - '0';
28313795Ssam 			s += 2;
28413795Ssam 		}
28513795Ssam 	}
28613795Ssam 
28713795Ssam 	puts(s);
28813795Ssam 	/*
28913795Ssam 	 * If no delay needed, or output speed is
29013795Ssam 	 * not comprehensible, then don't try to delay.
29113795Ssam 	 */
29213795Ssam 	if (pad == 0)
29313795Ssam 		return;
29413795Ssam 	if (tmode.sg_ospeed <= 0 ||
29513795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
29613795Ssam 		return;
29713795Ssam 
29813795Ssam 	/*
29913795Ssam 	 * Round up by a half a character frame,
30013795Ssam 	 * and then do the delay.
30113795Ssam 	 * Too bad there are no user program accessible programmed delays.
30213795Ssam 	 * Transmitting pad characters slows many
30313795Ssam 	 * terminals down and also loads the system.
30413795Ssam 	 */
30513795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
30613795Ssam 	pad += mspc10 / 2;
30713795Ssam 	for (pad /= mspc10; pad > 0; pad--)
30813795Ssam 		putchr(*PC);
30913795Ssam }
31013795Ssam 
31113795Ssam puts(s)
31213795Ssam 	register char *s;
31313795Ssam {
31413795Ssam 
31513795Ssam 	while (*s)
31613795Ssam 		putchr(*s++);
31713795Ssam }
31813795Ssam 
31913828Skre char	outbuf[OBUFSIZ];
32013828Skre int	obufcnt = 0;
32113828Skre 
32213795Ssam putchr(cc)
32313795Ssam {
32413795Ssam 	char c;
32513795Ssam 
32613795Ssam 	c = cc;
32713795Ssam 	c |= partab[c&0177] & 0200;
32813795Ssam 	if (OP)
32913795Ssam 		c ^= 0200;
33013828Skre 	if (!UB) {
33113828Skre 		outbuf[obufcnt++] = c;
33213828Skre 		if (obufcnt >= OBUFSIZ)
33313828Skre 			oflush();
33413828Skre 	} else
33513828Skre 		write(1, &c, 1);
33613795Ssam }
33713795Ssam 
33813828Skre oflush()
33913828Skre {
34013828Skre 	if (obufcnt)
34113828Skre 		write(1, outbuf, obufcnt);
34213828Skre 	obufcnt = 0;
34313828Skre }
34413828Skre 
34513795Ssam prompt()
34613795Ssam {
34713795Ssam 
34813795Ssam 	putf(LM);
34913795Ssam 	if (CO)
35013795Ssam 		putchr('\n');
35113795Ssam }
35213795Ssam 
35313795Ssam putf(cp)
35413795Ssam 	register char *cp;
35513795Ssam {
35613795Ssam 	extern char editedhost[];
35713795Ssam 
35813795Ssam 	while (*cp) {
35913795Ssam 		if (*cp != '%') {
36013795Ssam 			putchr(*cp++);
36113795Ssam 			continue;
36213795Ssam 		}
36313795Ssam 		switch (*++cp) {
36413795Ssam 
36513795Ssam 		case 'h':
36613795Ssam 			puts(editedhost);
36713795Ssam 			break;
36813795Ssam 
36913795Ssam 		case '%':
37013795Ssam 			putchr('%');
37113795Ssam 			break;
37213795Ssam 		}
37313795Ssam 		cp++;
37413795Ssam 	}
37513795Ssam }
376