xref: /csrg-svn/libexec/getty/main.c (revision 44640)
119054Sdist /*
219054Sdist  * Copyright (c) 1980 Regents of the University of California.
319054Sdist  * All rights reserved.  The Berkeley software License Agreement
419054Sdist  * specifies the terms and conditions for redistribution.
519054Sdist  */
619054Sdist 
713795Ssam #ifndef lint
819054Sdist char copyright[] =
919054Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1019054Sdist  All rights reserved.\n";
1119054Sdist #endif not lint
1213795Ssam 
1319054Sdist #ifndef lint
14*44640Smarc static char sccsid[] = "@(#)main.c	5.11 (Berkeley) 06/29/90";
1519054Sdist #endif not lint
1619054Sdist 
1713795Ssam /*
1813795Ssam  * getty -- adapt to terminal speed on dialup, and call login
1913795Ssam  *
2013795Ssam  * Melbourne getty, June 83, kre.
2113795Ssam  */
2213795Ssam 
2342459Smarc #define USE_OLD_TTY
2442459Smarc #include <sys/param.h>
2542459Smarc #include <sys/signal.h>
2642459Smarc #include <sys/file.h>
2713795Ssam #include <sgtty.h>
2813795Ssam #include <ctype.h>
2913795Ssam #include <setjmp.h>
3018543Sralph #include <syslog.h>
3142459Smarc #include <ctype.h>
3213795Ssam #include "gettytab.h"
3342459Smarc #include "pathnames.h"
3413795Ssam 
3518543Sralph extern	char **environ;
3618543Sralph 
3713795Ssam struct	sgttyb tmode = {
3813795Ssam 	0, 0, CERASE, CKILL, 0
3913795Ssam };
4013795Ssam struct	tchars tc = {
4113795Ssam 	CINTR, CQUIT, CSTART,
4213795Ssam 	CSTOP, CEOF, CBRK,
4313795Ssam };
4413795Ssam struct	ltchars ltc = {
4513795Ssam 	CSUSP, CDSUSP, CRPRNT,
4613795Ssam 	CFLUSH, CWERASE, CLNEXT
4713795Ssam };
4813795Ssam 
4913795Ssam int	crmod;
5013795Ssam int	upper;
5113795Ssam int	lower;
5213795Ssam int	digit;
5313795Ssam 
5442459Smarc char	hostname[MAXHOSTNAMELEN];
5513795Ssam char	name[16];
5642459Smarc char	dev[] = _PATH_DEV;
5718543Sralph char	ttyn[32];
5813795Ssam char	*portselector();
5918543Sralph char	*ttyname();
6013795Ssam 
6113828Skre #define	OBUFSIZ		128
6213795Ssam #define	TABBUFSIZ	512
6313795Ssam 
6413795Ssam char	defent[TABBUFSIZ];
6513795Ssam char	defstrs[TABBUFSIZ];
6613795Ssam char	tabent[TABBUFSIZ];
6713795Ssam char	tabstrs[TABBUFSIZ];
6813795Ssam 
6913795Ssam char	*env[128];
7013795Ssam 
7113795Ssam char partab[] = {
7213795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
7313795Ssam 	0202,0004,0003,0205,0005,0206,0201,0001,
7413795Ssam 	0201,0001,0001,0201,0001,0201,0201,0001,
7513795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
7613795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
7713795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
7813795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
7913795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8013795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8113795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8213795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8313795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8413795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8513795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8613795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8713795Ssam 	0000,0200,0200,0000,0200,0000,0000,0201
8813795Ssam };
8913795Ssam 
9013795Ssam #define	ERASE	tmode.sg_erase
9113795Ssam #define	KILL	tmode.sg_kill
9213795Ssam #define	EOT	tc.t_eofc
9313795Ssam 
9413795Ssam jmp_buf timeout;
9513795Ssam 
9613795Ssam dingdong()
9713795Ssam {
9813795Ssam 
9913795Ssam 	alarm(0);
10013795Ssam 	signal(SIGALRM, SIG_DFL);
10113795Ssam 	longjmp(timeout, 1);
10213795Ssam }
10313795Ssam 
10413828Skre jmp_buf	intrupt;
10513828Skre 
10613828Skre interrupt()
10713828Skre {
10813828Skre 
10913828Skre 	signal(SIGINT, interrupt);
11013828Skre 	longjmp(intrupt, 1);
11113828Skre }
11213828Skre 
11313795Ssam main(argc, argv)
11413795Ssam 	char *argv[];
11513795Ssam {
11613795Ssam 	char *tname;
11713795Ssam 	long allflags;
11818543Sralph 	int repcnt = 0;
11913795Ssam 
12013828Skre 	signal(SIGINT, SIG_IGN);
12113795Ssam /*
12213795Ssam 	signal(SIGQUIT, SIG_DFL);
12313795Ssam */
12424890Seric 	openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
12513795Ssam 	gethostname(hostname, sizeof(hostname));
12613795Ssam 	if (hostname[0] == '\0')
12713795Ssam 		strcpy(hostname, "Amnesiac");
12818543Sralph 	/*
12918543Sralph 	 * The following is a work around for vhangup interactions
13018543Sralph 	 * which cause great problems getting window systems started.
13118543Sralph 	 * If the tty line is "-", we do the old style getty presuming
13218543Sralph 	 * that the file descriptors are already set up for us.
13318543Sralph 	 * J. Gettys - MIT Project Athena.
13418543Sralph 	 */
13518543Sralph 	if (argc <= 2 || strcmp(argv[2], "-") == 0)
13625954Sbloom 	    strcpy(ttyn, ttyname(0));
13718543Sralph 	else {
13844567Smarc 	    int i;
13944567Smarc 
14025954Sbloom 	    strcpy(ttyn, dev);
14125954Sbloom 	    strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
14225954Sbloom 	    if (strcmp(argv[0], "+") != 0) {
14318543Sralph 		chown(ttyn, 0, 0);
14444567Smarc 		chmod(ttyn, 0600);
14544567Smarc 		revoke(ttyn);
14625553Smckusick 		/*
14725553Smckusick 		 * Delay the open so DTR stays down long enough to be detected.
14825553Smckusick 		 */
14925553Smckusick 		sleep(2);
15044567Smarc 		while ((i = open(ttyn, O_RDWR)) == -1) {
15118543Sralph 			if (repcnt % 10 == 0) {
15224895Seric 				syslog(LOG_ERR, "%s: %m", ttyn);
15318543Sralph 				closelog();
15418543Sralph 			}
15518543Sralph 			repcnt++;
15618543Sralph 			sleep(60);
15718543Sralph 		}
15844567Smarc 		login_tty(i);
15925954Sbloom 	    }
16018543Sralph 	}
16118543Sralph 
16213795Ssam 	gettable("default", defent, defstrs);
16313795Ssam 	gendefaults();
16413795Ssam 	tname = "default";
16513795Ssam 	if (argc > 1)
16613795Ssam 		tname = argv[1];
16713795Ssam 	for (;;) {
16813795Ssam 		int ldisp = OTTYDISC;
16932209Sbostic 		int off = 0;
17013795Ssam 
17113795Ssam 		gettable(tname, tabent, tabstrs);
17213828Skre 		if (OPset || EPset || APset)
17313828Skre 			APset++, OPset++, EPset++;
17413795Ssam 		setdefaults();
17513795Ssam 		ioctl(0, TIOCFLUSH, 0);		/* clear out the crap */
17632209Sbostic 		ioctl(0, FIONBIO, &off);	/* turn off non-blocking mode */
17732209Sbostic 		ioctl(0, FIOASYNC, &off);	/* ditto for asynchronous mode */
17813795Ssam 		if (IS)
17913795Ssam 			tmode.sg_ispeed = speed(IS);
18013795Ssam 		else if (SP)
18113795Ssam 			tmode.sg_ispeed = speed(SP);
18213795Ssam 		if (OS)
18313795Ssam 			tmode.sg_ospeed = speed(OS);
18413795Ssam 		else if (SP)
18513795Ssam 			tmode.sg_ospeed = speed(SP);
18613795Ssam 		tmode.sg_flags = setflags(0);
18713795Ssam 		ioctl(0, TIOCSETP, &tmode);
18813795Ssam 		setchars();
18913795Ssam 		ioctl(0, TIOCSETC, &tc);
19013795Ssam 		if (HC)
19113795Ssam 			ioctl(0, TIOCHPCL, 0);
19218543Sralph 		if (AB) {
19318543Sralph 			extern char *autobaud();
19418543Sralph 
19518543Sralph 			tname = autobaud();
19618543Sralph 			continue;
19718543Sralph 		}
19813795Ssam 		if (PS) {
19913795Ssam 			tname = portselector();
20013795Ssam 			continue;
20113795Ssam 		}
20213795Ssam 		if (CL && *CL)
20313795Ssam 			putpad(CL);
20413795Ssam 		edithost(HE);
20513795Ssam 		if (IM && *IM)
20613795Ssam 			putf(IM);
20713795Ssam 		if (setjmp(timeout)) {
20813795Ssam 			tmode.sg_ispeed = tmode.sg_ospeed = 0;
20913795Ssam 			ioctl(0, TIOCSETP, &tmode);
21013795Ssam 			exit(1);
21113795Ssam 		}
21213795Ssam 		if (TO) {
21313795Ssam 			signal(SIGALRM, dingdong);
21413795Ssam 			alarm(TO);
21513795Ssam 		}
21613795Ssam 		if (getname()) {
21718543Sralph 			register int i;
21818543Sralph 
21918543Sralph 			oflush();
22013795Ssam 			alarm(0);
22113795Ssam 			signal(SIGALRM, SIG_DFL);
22232308Sbostic 			if (name[0] == '-') {
22342459Smarc 				puts("user names may not start with '-'.");
22432308Sbostic 				continue;
22532308Sbostic 			}
22613831Ssam 			if (!(upper || lower || digit))
22713795Ssam 				continue;
22813795Ssam 			allflags = setflags(2);
22913795Ssam 			tmode.sg_flags = allflags & 0xffff;
23013795Ssam 			allflags >>= 16;
23113795Ssam 			if (crmod || NL)
23213795Ssam 				tmode.sg_flags |= CRMOD;
23313795Ssam 			if (upper || UC)
23413795Ssam 				tmode.sg_flags |= LCASE;
23513795Ssam 			if (lower || LC)
23613795Ssam 				tmode.sg_flags &= ~LCASE;
23713795Ssam 			ioctl(0, TIOCSETP, &tmode);
23813795Ssam 			ioctl(0, TIOCSLTC, &ltc);
23913795Ssam 			ioctl(0, TIOCLSET, &allflags);
24013828Skre 			signal(SIGINT, SIG_DFL);
24118543Sralph 			for (i = 0; environ[i] != (char *)0; i++)
24218543Sralph 				env[i] = environ[i];
24318543Sralph 			makeenv(&env[i]);
244*44640Smarc 
245*44640Smarc 			/*
246*44640Smarc 			 * this is what login was doing anyway.
247*44640Smarc 			 * soon we rewrite getty completely.
248*44640Smarc 			 */
249*44640Smarc 			set_ttydefaults(0);
25018543Sralph 			execle(LO, "login", "-p", name, (char *) 0, env);
25132209Sbostic 			syslog(LOG_ERR, "%s: %m", LO);
25213795Ssam 			exit(1);
25313795Ssam 		}
25413795Ssam 		alarm(0);
25513795Ssam 		signal(SIGALRM, SIG_DFL);
25613828Skre 		signal(SIGINT, SIG_IGN);
25713795Ssam 		if (NX && *NX)
25813795Ssam 			tname = NX;
25913795Ssam 	}
26013795Ssam }
26113795Ssam 
26213795Ssam getname()
26313795Ssam {
26413795Ssam 	register char *np;
26513795Ssam 	register c;
26613795Ssam 	char cs;
26713795Ssam 
26813828Skre 	/*
26913831Ssam 	 * Interrupt may happen if we use CBREAK mode
27013828Skre 	 */
27113828Skre 	if (setjmp(intrupt)) {
27213828Skre 		signal(SIGINT, SIG_IGN);
27313828Skre 		return (0);
27413828Skre 	}
27513828Skre 	signal(SIGINT, interrupt);
27613795Ssam 	tmode.sg_flags = setflags(0);
27713795Ssam 	ioctl(0, TIOCSETP, &tmode);
27813795Ssam 	tmode.sg_flags = setflags(1);
27913795Ssam 	prompt();
28013885Ssam 	if (PF > 0) {
28114322Ssam 		oflush();
28213885Ssam 		sleep(PF);
28313885Ssam 		PF = 0;
28413885Ssam 	}
28513795Ssam 	ioctl(0, TIOCSETP, &tmode);
28613795Ssam 	crmod = 0;
28713795Ssam 	upper = 0;
28813795Ssam 	lower = 0;
28913795Ssam 	digit = 0;
29013795Ssam 	np = name;
29113795Ssam 	for (;;) {
29213828Skre 		oflush();
29313795Ssam 		if (read(0, &cs, 1) <= 0)
29413795Ssam 			exit(0);
29513795Ssam 		if ((c = cs&0177) == 0)
29613795Ssam 			return (0);
29713831Ssam 		if (c == EOT)
29813795Ssam 			exit(1);
29918543Sralph 		if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
30018543Sralph 			putf("\r\n");
30113795Ssam 			break;
30218543Sralph 		}
30342459Smarc 		if (islower(c))
30413795Ssam 			lower++;
30542459Smarc 		else if (isupper(c))
30613795Ssam 			upper++;
30718543Sralph 		else if (c == ERASE || c == '#' || c == '\b') {
30813795Ssam 			if (np > name) {
30913795Ssam 				np--;
31013795Ssam 				if (tmode.sg_ospeed >= B1200)
31113795Ssam 					puts("\b \b");
31213795Ssam 				else
31313795Ssam 					putchr(cs);
31413795Ssam 			}
31513795Ssam 			continue;
31613831Ssam 		} else if (c == KILL || c == '@') {
31713795Ssam 			putchr(cs);
31813795Ssam 			putchr('\r');
31913795Ssam 			if (tmode.sg_ospeed < B1200)
32013795Ssam 				putchr('\n');
32113795Ssam 			/* this is the way they do it down under ... */
32213795Ssam 			else if (np > name)
32313795Ssam 				puts("                                     \r");
32413795Ssam 			prompt();
32513795Ssam 			np = name;
32613795Ssam 			continue;
32742459Smarc 		} else if (isdigit(c))
32813795Ssam 			digit++;
32918543Sralph 		if (IG && (c <= ' ' || c > 0176))
33013795Ssam 			continue;
33113795Ssam 		*np++ = c;
33213795Ssam 		putchr(cs);
33313795Ssam 	}
33413828Skre 	signal(SIGINT, SIG_IGN);
33513795Ssam 	*np = 0;
33613795Ssam 	if (c == '\r')
33713795Ssam 		crmod++;
33813795Ssam 	if (upper && !lower && !LC || UC)
33913795Ssam 		for (np = name; *np; np++)
34013795Ssam 			if (isupper(*np))
34113795Ssam 				*np = tolower(*np);
34213795Ssam 	return (1);
34313795Ssam }
34413795Ssam 
34513795Ssam static
34613795Ssam short	tmspc10[] = {
34713795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
34813795Ssam };
34913795Ssam 
35013795Ssam putpad(s)
35113795Ssam 	register char *s;
35213795Ssam {
35313795Ssam 	register pad = 0;
35413795Ssam 	register mspc10;
35513795Ssam 
35613795Ssam 	if (isdigit(*s)) {
35713795Ssam 		while (isdigit(*s)) {
35813795Ssam 			pad *= 10;
35913795Ssam 			pad += *s++ - '0';
36013795Ssam 		}
36113795Ssam 		pad *= 10;
36213795Ssam 		if (*s == '.' && isdigit(s[1])) {
36313795Ssam 			pad += s[1] - '0';
36413795Ssam 			s += 2;
36513795Ssam 		}
36613795Ssam 	}
36713795Ssam 
36813795Ssam 	puts(s);
36913795Ssam 	/*
37013795Ssam 	 * If no delay needed, or output speed is
37113795Ssam 	 * not comprehensible, then don't try to delay.
37213795Ssam 	 */
37313795Ssam 	if (pad == 0)
37413795Ssam 		return;
37513795Ssam 	if (tmode.sg_ospeed <= 0 ||
37613795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
37713795Ssam 		return;
37813795Ssam 
37913795Ssam 	/*
38013795Ssam 	 * Round up by a half a character frame,
38113795Ssam 	 * and then do the delay.
38213795Ssam 	 * Too bad there are no user program accessible programmed delays.
38313795Ssam 	 * Transmitting pad characters slows many
38413795Ssam 	 * terminals down and also loads the system.
38513795Ssam 	 */
38613795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
38713795Ssam 	pad += mspc10 / 2;
38813795Ssam 	for (pad /= mspc10; pad > 0; pad--)
38913795Ssam 		putchr(*PC);
39013795Ssam }
39113795Ssam 
39213795Ssam puts(s)
39313795Ssam 	register char *s;
39413795Ssam {
39513795Ssam 
39613795Ssam 	while (*s)
39713795Ssam 		putchr(*s++);
39813795Ssam }
39913795Ssam 
40013828Skre char	outbuf[OBUFSIZ];
40113828Skre int	obufcnt = 0;
40213828Skre 
40313795Ssam putchr(cc)
40413795Ssam {
40513795Ssam 	char c;
40613795Ssam 
40713795Ssam 	c = cc;
40813795Ssam 	c |= partab[c&0177] & 0200;
40913795Ssam 	if (OP)
41013795Ssam 		c ^= 0200;
41113828Skre 	if (!UB) {
41213828Skre 		outbuf[obufcnt++] = c;
41313828Skre 		if (obufcnt >= OBUFSIZ)
41413828Skre 			oflush();
41513828Skre 	} else
41613828Skre 		write(1, &c, 1);
41713795Ssam }
41813795Ssam 
41913828Skre oflush()
42013828Skre {
42113828Skre 	if (obufcnt)
42213828Skre 		write(1, outbuf, obufcnt);
42313828Skre 	obufcnt = 0;
42413828Skre }
42513828Skre 
42613795Ssam prompt()
42713795Ssam {
42813795Ssam 
42913795Ssam 	putf(LM);
43013795Ssam 	if (CO)
43113795Ssam 		putchr('\n');
43213795Ssam }
43313795Ssam 
43413795Ssam putf(cp)
43513795Ssam 	register char *cp;
43613795Ssam {
43742460Smckusick 	char *slash;
43818543Sralph 	char datebuffer[60];
43913795Ssam 	extern char editedhost[];
44042460Smckusick 	extern char *rindex();
44113795Ssam 
44213795Ssam 	while (*cp) {
44313795Ssam 		if (*cp != '%') {
44413795Ssam 			putchr(*cp++);
44513795Ssam 			continue;
44613795Ssam 		}
44713795Ssam 		switch (*++cp) {
44813795Ssam 
44918543Sralph 		case 't':
45018543Sralph 			slash = rindex(ttyn, '/');
45118543Sralph 			if (slash == (char *) 0)
45218543Sralph 				puts(ttyn);
45318543Sralph 			else
45418543Sralph 				puts(&slash[1]);
45518543Sralph 			break;
45618543Sralph 
45713795Ssam 		case 'h':
45813795Ssam 			puts(editedhost);
45913795Ssam 			break;
46013795Ssam 
46118543Sralph 		case 'd':
46218543Sralph 			get_date(datebuffer);
46318543Sralph 			puts(datebuffer);
46415713Sralph 			break;
46515713Sralph 
46613795Ssam 		case '%':
46713795Ssam 			putchr('%');
46813795Ssam 			break;
46913795Ssam 		}
47013795Ssam 		cp++;
47113795Ssam 	}
47213795Ssam }
473