xref: /csrg-svn/libexec/getty/main.c (revision 60091)
146043Sbostic /*-
246043Sbostic  * Copyright (c) 1980 The Regents of the University of California.
346043Sbostic  * All rights reserved.
446043Sbostic  *
546043Sbostic  * %sccs.include.redist.c%
619054Sdist  */
719054Sdist 
813795Ssam #ifndef lint
919054Sdist char copyright[] =
1046043Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
1119054Sdist  All rights reserved.\n";
1246043Sbostic #endif /* not lint */
1313795Ssam 
1419054Sdist #ifndef lint
15*60091Sbostic static char sccsid[] = "@(#)main.c	5.19 (Berkeley) 05/17/93";
1646043Sbostic #endif /* not lint */
1719054Sdist 
1846043Sbostic #define USE_OLD_TTY
1913795Ssam 
2042459Smarc #include <sys/param.h>
2146670Sbostic #include <sys/stat.h>
22*60091Sbostic 
23*60091Sbostic #include <ctype.h>
24*60091Sbostic #include <ctype.h>
2546670Sbostic #include <fcntl.h>
26*60091Sbostic #include <setjmp.h>
2713795Ssam #include <sgtty.h>
28*60091Sbostic #include <signal.h>
29*60091Sbostic #include <stdlib.h>
30*60091Sbostic #include <string.h>
31*60091Sbostic #include <syslog.h>
3246670Sbostic #include <time.h>
3346043Sbostic #include <unistd.h>
34*60091Sbostic 
3513795Ssam #include "gettytab.h"
3642459Smarc #include "pathnames.h"
37*60091Sbostic #include "extern.h"
3813795Ssam 
3913795Ssam struct	sgttyb tmode = {
4013795Ssam 	0, 0, CERASE, CKILL, 0
4113795Ssam };
4213795Ssam struct	tchars tc = {
4313795Ssam 	CINTR, CQUIT, CSTART,
4413795Ssam 	CSTOP, CEOF, CBRK,
4513795Ssam };
4613795Ssam struct	ltchars ltc = {
4713795Ssam 	CSUSP, CDSUSP, CRPRNT,
4813795Ssam 	CFLUSH, CWERASE, CLNEXT
4913795Ssam };
5013795Ssam 
5146043Sbostic int crmod, digit, lower, upper;
5213795Ssam 
5342459Smarc char	hostname[MAXHOSTNAMELEN];
5413795Ssam char	name[16];
5542459Smarc char	dev[] = _PATH_DEV;
5618543Sralph char	ttyn[32];
5713795Ssam char	*portselector();
5818543Sralph char	*ttyname();
5913795Ssam 
6013828Skre #define	OBUFSIZ		128
6113795Ssam #define	TABBUFSIZ	512
6213795Ssam 
6313795Ssam char	defent[TABBUFSIZ];
6413795Ssam char	defstrs[TABBUFSIZ];
6513795Ssam char	tabent[TABBUFSIZ];
6613795Ssam char	tabstrs[TABBUFSIZ];
6713795Ssam 
6813795Ssam char	*env[128];
6913795Ssam 
7013795Ssam char partab[] = {
7113795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
7213795Ssam 	0202,0004,0003,0205,0005,0206,0201,0001,
7313795Ssam 	0201,0001,0001,0201,0001,0201,0201,0001,
7413795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
7513795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
7613795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
7713795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
7813795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
7913795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8013795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8113795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8213795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8313795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
8413795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8513795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
8613795Ssam 	0000,0200,0200,0000,0200,0000,0000,0201
8713795Ssam };
8813795Ssam 
8913795Ssam #define	ERASE	tmode.sg_erase
9013795Ssam #define	KILL	tmode.sg_kill
9113795Ssam #define	EOT	tc.t_eofc
9213795Ssam 
9313795Ssam jmp_buf timeout;
9413795Ssam 
9546670Sbostic static void
9613795Ssam dingdong()
9713795Ssam {
9813795Ssam 
9913795Ssam 	alarm(0);
10013795Ssam 	signal(SIGALRM, SIG_DFL);
10113795Ssam 	longjmp(timeout, 1);
10213795Ssam }
10313795Ssam 
10413828Skre jmp_buf	intrupt;
10513828Skre 
10646670Sbostic static void
10713828Skre interrupt()
10813828Skre {
10913828Skre 
11013828Skre 	signal(SIGINT, interrupt);
11113828Skre 	longjmp(intrupt, 1);
11213828Skre }
11313828Skre 
114*60091Sbostic static int	getname __P((void));
115*60091Sbostic static void	oflush __P((void));
116*60091Sbostic static void	prompt __P((void));
117*60091Sbostic static void	putchr __P((int));
118*60091Sbostic static void	putf __P((char *));
119*60091Sbostic static void	putpad __P((char *));
120*60091Sbostic static void	puts __P((char *));
121*60091Sbostic 
122*60091Sbostic int
12313795Ssam main(argc, argv)
12446043Sbostic 	int argc;
125*60091Sbostic 	char *argv[];
12613795Ssam {
127*60091Sbostic 	extern char **environ;
12813795Ssam 	char *tname;
12913795Ssam 	long allflags;
13018543Sralph 	int repcnt = 0;
13113795Ssam 
13213828Skre 	signal(SIGINT, SIG_IGN);
13313795Ssam /*
13413795Ssam 	signal(SIGQUIT, SIG_DFL);
13513795Ssam */
13624890Seric 	openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
13713795Ssam 	gethostname(hostname, sizeof(hostname));
13813795Ssam 	if (hostname[0] == '\0')
13913795Ssam 		strcpy(hostname, "Amnesiac");
14018543Sralph 	/*
14118543Sralph 	 * The following is a work around for vhangup interactions
14218543Sralph 	 * which cause great problems getting window systems started.
14318543Sralph 	 * If the tty line is "-", we do the old style getty presuming
14418543Sralph 	 * that the file descriptors are already set up for us.
14518543Sralph 	 * J. Gettys - MIT Project Athena.
14618543Sralph 	 */
14718543Sralph 	if (argc <= 2 || strcmp(argv[2], "-") == 0)
14825954Sbloom 	    strcpy(ttyn, ttyname(0));
14918543Sralph 	else {
15044567Smarc 	    int i;
15144567Smarc 
15225954Sbloom 	    strcpy(ttyn, dev);
15325954Sbloom 	    strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
15425954Sbloom 	    if (strcmp(argv[0], "+") != 0) {
15518543Sralph 		chown(ttyn, 0, 0);
15644567Smarc 		chmod(ttyn, 0600);
15744567Smarc 		revoke(ttyn);
15825553Smckusick 		/*
15925553Smckusick 		 * Delay the open so DTR stays down long enough to be detected.
16025553Smckusick 		 */
16125553Smckusick 		sleep(2);
16244567Smarc 		while ((i = open(ttyn, O_RDWR)) == -1) {
16318543Sralph 			if (repcnt % 10 == 0) {
16424895Seric 				syslog(LOG_ERR, "%s: %m", ttyn);
16518543Sralph 				closelog();
16618543Sralph 			}
16718543Sralph 			repcnt++;
16818543Sralph 			sleep(60);
16918543Sralph 		}
17044567Smarc 		login_tty(i);
17125954Sbloom 	    }
17218543Sralph 	}
17318543Sralph 
17413795Ssam 	gettable("default", defent, defstrs);
17513795Ssam 	gendefaults();
17613795Ssam 	tname = "default";
17713795Ssam 	if (argc > 1)
17813795Ssam 		tname = argv[1];
17913795Ssam 	for (;;) {
18053076Sbostic 		int off;
18113795Ssam 
18213795Ssam 		gettable(tname, tabent, tabstrs);
18313828Skre 		if (OPset || EPset || APset)
18413828Skre 			APset++, OPset++, EPset++;
18513795Ssam 		setdefaults();
18653076Sbostic 		off = 0;
18753076Sbostic 		ioctl(0, TIOCFLUSH, &off);	/* clear out the crap */
18832209Sbostic 		ioctl(0, FIONBIO, &off);	/* turn off non-blocking mode */
18946043Sbostic 		ioctl(0, FIOASYNC, &off);	/* ditto for async mode */
19013795Ssam 		if (IS)
19113795Ssam 			tmode.sg_ispeed = speed(IS);
19213795Ssam 		else if (SP)
19313795Ssam 			tmode.sg_ispeed = speed(SP);
19413795Ssam 		if (OS)
19513795Ssam 			tmode.sg_ospeed = speed(OS);
19613795Ssam 		else if (SP)
19713795Ssam 			tmode.sg_ospeed = speed(SP);
19813795Ssam 		tmode.sg_flags = setflags(0);
19913795Ssam 		ioctl(0, TIOCSETP, &tmode);
20013795Ssam 		setchars();
20113795Ssam 		ioctl(0, TIOCSETC, &tc);
20213795Ssam 		if (HC)
20313795Ssam 			ioctl(0, TIOCHPCL, 0);
20418543Sralph 		if (AB) {
20518543Sralph 			extern char *autobaud();
20618543Sralph 
20718543Sralph 			tname = autobaud();
20818543Sralph 			continue;
20918543Sralph 		}
21013795Ssam 		if (PS) {
21113795Ssam 			tname = portselector();
21213795Ssam 			continue;
21313795Ssam 		}
21413795Ssam 		if (CL && *CL)
21513795Ssam 			putpad(CL);
21613795Ssam 		edithost(HE);
21713795Ssam 		if (IM && *IM)
21813795Ssam 			putf(IM);
21913795Ssam 		if (setjmp(timeout)) {
22013795Ssam 			tmode.sg_ispeed = tmode.sg_ospeed = 0;
22113795Ssam 			ioctl(0, TIOCSETP, &tmode);
22213795Ssam 			exit(1);
22313795Ssam 		}
22413795Ssam 		if (TO) {
22513795Ssam 			signal(SIGALRM, dingdong);
22613795Ssam 			alarm(TO);
22713795Ssam 		}
22813795Ssam 		if (getname()) {
22918543Sralph 			register int i;
23018543Sralph 
23118543Sralph 			oflush();
23213795Ssam 			alarm(0);
23313795Ssam 			signal(SIGALRM, SIG_DFL);
23432308Sbostic 			if (name[0] == '-') {
23542459Smarc 				puts("user names may not start with '-'.");
23632308Sbostic 				continue;
23732308Sbostic 			}
23813831Ssam 			if (!(upper || lower || digit))
23913795Ssam 				continue;
24013795Ssam 			allflags = setflags(2);
24113795Ssam 			tmode.sg_flags = allflags & 0xffff;
24213795Ssam 			allflags >>= 16;
24313795Ssam 			if (crmod || NL)
24413795Ssam 				tmode.sg_flags |= CRMOD;
24513795Ssam 			if (upper || UC)
24613795Ssam 				tmode.sg_flags |= LCASE;
24713795Ssam 			if (lower || LC)
24813795Ssam 				tmode.sg_flags &= ~LCASE;
24913795Ssam 			ioctl(0, TIOCSETP, &tmode);
25013795Ssam 			ioctl(0, TIOCSLTC, &ltc);
25113795Ssam 			ioctl(0, TIOCLSET, &allflags);
25213828Skre 			signal(SIGINT, SIG_DFL);
25318543Sralph 			for (i = 0; environ[i] != (char *)0; i++)
25418543Sralph 				env[i] = environ[i];
25518543Sralph 			makeenv(&env[i]);
25644640Smarc 
25744640Smarc 			/*
25844640Smarc 			 * this is what login was doing anyway.
25944640Smarc 			 * soon we rewrite getty completely.
26044640Smarc 			 */
26144640Smarc 			set_ttydefaults(0);
26218543Sralph 			execle(LO, "login", "-p", name, (char *) 0, env);
26332209Sbostic 			syslog(LOG_ERR, "%s: %m", LO);
26413795Ssam 			exit(1);
26513795Ssam 		}
26613795Ssam 		alarm(0);
26713795Ssam 		signal(SIGALRM, SIG_DFL);
26813828Skre 		signal(SIGINT, SIG_IGN);
26913795Ssam 		if (NX && *NX)
27013795Ssam 			tname = NX;
27113795Ssam 	}
27213795Ssam }
27313795Ssam 
274*60091Sbostic static int
27513795Ssam getname()
27613795Ssam {
27746043Sbostic 	register int c;
27813795Ssam 	register char *np;
27913795Ssam 	char cs;
28013795Ssam 
28113828Skre 	/*
28213831Ssam 	 * Interrupt may happen if we use CBREAK mode
28313828Skre 	 */
28413828Skre 	if (setjmp(intrupt)) {
28513828Skre 		signal(SIGINT, SIG_IGN);
28613828Skre 		return (0);
28713828Skre 	}
28813828Skre 	signal(SIGINT, interrupt);
28913795Ssam 	tmode.sg_flags = setflags(0);
29013795Ssam 	ioctl(0, TIOCSETP, &tmode);
29113795Ssam 	tmode.sg_flags = setflags(1);
29213795Ssam 	prompt();
29313885Ssam 	if (PF > 0) {
29414322Ssam 		oflush();
29513885Ssam 		sleep(PF);
29613885Ssam 		PF = 0;
29713885Ssam 	}
29813795Ssam 	ioctl(0, TIOCSETP, &tmode);
29946043Sbostic 	crmod = digit = lower = upper = 0;
30013795Ssam 	np = name;
30113795Ssam 	for (;;) {
30213828Skre 		oflush();
30346043Sbostic 		if (read(STDIN_FILENO, &cs, 1) <= 0)
30413795Ssam 			exit(0);
30513795Ssam 		if ((c = cs&0177) == 0)
30613795Ssam 			return (0);
30713831Ssam 		if (c == EOT)
30813795Ssam 			exit(1);
30918543Sralph 		if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
31018543Sralph 			putf("\r\n");
31113795Ssam 			break;
31218543Sralph 		}
31342459Smarc 		if (islower(c))
31446043Sbostic 			lower = 1;
31542459Smarc 		else if (isupper(c))
31646043Sbostic 			upper = 1;
31718543Sralph 		else if (c == ERASE || c == '#' || c == '\b') {
31813795Ssam 			if (np > name) {
31913795Ssam 				np--;
32013795Ssam 				if (tmode.sg_ospeed >= B1200)
32113795Ssam 					puts("\b \b");
32213795Ssam 				else
32313795Ssam 					putchr(cs);
32413795Ssam 			}
32513795Ssam 			continue;
32613831Ssam 		} else if (c == KILL || c == '@') {
32713795Ssam 			putchr(cs);
32813795Ssam 			putchr('\r');
32913795Ssam 			if (tmode.sg_ospeed < B1200)
33013795Ssam 				putchr('\n');
33113795Ssam 			/* this is the way they do it down under ... */
33213795Ssam 			else if (np > name)
33313795Ssam 				puts("                                     \r");
33413795Ssam 			prompt();
33513795Ssam 			np = name;
33613795Ssam 			continue;
33742459Smarc 		} else if (isdigit(c))
33813795Ssam 			digit++;
33918543Sralph 		if (IG && (c <= ' ' || c > 0176))
34013795Ssam 			continue;
34113795Ssam 		*np++ = c;
34213795Ssam 		putchr(cs);
34313795Ssam 	}
34413828Skre 	signal(SIGINT, SIG_IGN);
34513795Ssam 	*np = 0;
34613795Ssam 	if (c == '\r')
34746043Sbostic 		crmod = 1;
34813795Ssam 	if (upper && !lower && !LC || UC)
34913795Ssam 		for (np = name; *np; np++)
35013795Ssam 			if (isupper(*np))
35113795Ssam 				*np = tolower(*np);
35213795Ssam 	return (1);
35313795Ssam }
35413795Ssam 
35513795Ssam static
35613795Ssam short	tmspc10[] = {
35713795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
35813795Ssam };
35913795Ssam 
360*60091Sbostic static void
36113795Ssam putpad(s)
36213795Ssam 	register char *s;
36313795Ssam {
36413795Ssam 	register pad = 0;
36513795Ssam 	register mspc10;
36613795Ssam 
36713795Ssam 	if (isdigit(*s)) {
36813795Ssam 		while (isdigit(*s)) {
36913795Ssam 			pad *= 10;
37013795Ssam 			pad += *s++ - '0';
37113795Ssam 		}
37213795Ssam 		pad *= 10;
37313795Ssam 		if (*s == '.' && isdigit(s[1])) {
37413795Ssam 			pad += s[1] - '0';
37513795Ssam 			s += 2;
37613795Ssam 		}
37713795Ssam 	}
37813795Ssam 
37913795Ssam 	puts(s);
38013795Ssam 	/*
38113795Ssam 	 * If no delay needed, or output speed is
38213795Ssam 	 * not comprehensible, then don't try to delay.
38313795Ssam 	 */
38413795Ssam 	if (pad == 0)
38513795Ssam 		return;
38613795Ssam 	if (tmode.sg_ospeed <= 0 ||
38713795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
38813795Ssam 		return;
38913795Ssam 
39013795Ssam 	/*
39146043Sbostic 	 * Round up by a half a character frame, and then do the delay.
39213795Ssam 	 * Too bad there are no user program accessible programmed delays.
39346043Sbostic 	 * Transmitting pad characters slows many terminals down and also
39446043Sbostic 	 * loads the system.
39513795Ssam 	 */
39613795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
39713795Ssam 	pad += mspc10 / 2;
39813795Ssam 	for (pad /= mspc10; pad > 0; pad--)
39913795Ssam 		putchr(*PC);
40013795Ssam }
40113795Ssam 
402*60091Sbostic static void
40313795Ssam puts(s)
40413795Ssam 	register char *s;
40513795Ssam {
40613795Ssam 	while (*s)
40713795Ssam 		putchr(*s++);
40813795Ssam }
40913795Ssam 
41013828Skre char	outbuf[OBUFSIZ];
41113828Skre int	obufcnt = 0;
41213828Skre 
413*60091Sbostic static void
41413795Ssam putchr(cc)
415*60091Sbostic 	int cc;
41613795Ssam {
41713795Ssam 	char c;
41813795Ssam 
41913795Ssam 	c = cc;
42047664Swilliam 	if (!NP) {
42147664Swilliam 		c |= partab[c&0177] & 0200;
42247664Swilliam 		if (OP)
42347664Swilliam 			c ^= 0200;
42447664Swilliam 	}
42513828Skre 	if (!UB) {
42613828Skre 		outbuf[obufcnt++] = c;
42713828Skre 		if (obufcnt >= OBUFSIZ)
42813828Skre 			oflush();
42913828Skre 	} else
43046043Sbostic 		write(STDOUT_FILENO, &c, 1);
43113795Ssam }
43213795Ssam 
433*60091Sbostic static void
43413828Skre oflush()
43513828Skre {
43613828Skre 	if (obufcnt)
43746043Sbostic 		write(STDOUT_FILENO, outbuf, obufcnt);
43813828Skre 	obufcnt = 0;
43913828Skre }
44013828Skre 
441*60091Sbostic static void
44213795Ssam prompt()
44313795Ssam {
44413795Ssam 
44513795Ssam 	putf(LM);
44613795Ssam 	if (CO)
44713795Ssam 		putchr('\n');
44813795Ssam }
44913795Ssam 
450*60091Sbostic static void
45113795Ssam putf(cp)
45213795Ssam 	register char *cp;
45313795Ssam {
45413795Ssam 	extern char editedhost[];
45546043Sbostic 	time_t t;
45646670Sbostic 	char *slash, db[100];
45713795Ssam 
45813795Ssam 	while (*cp) {
45913795Ssam 		if (*cp != '%') {
46013795Ssam 			putchr(*cp++);
46113795Ssam 			continue;
46213795Ssam 		}
46313795Ssam 		switch (*++cp) {
46413795Ssam 
46518543Sralph 		case 't':
466*60091Sbostic 			slash = strrchr(ttyn, '/');
46718543Sralph 			if (slash == (char *) 0)
46818543Sralph 				puts(ttyn);
46918543Sralph 			else
47018543Sralph 				puts(&slash[1]);
47118543Sralph 			break;
47218543Sralph 
47313795Ssam 		case 'h':
47413795Ssam 			puts(editedhost);
47513795Ssam 			break;
47613795Ssam 
47746670Sbostic 		case 'd': {
47846967Sbostic 			static char fmt[] = "%l:% %P on %A, %d %B %Y";
47946670Sbostic 
48046670Sbostic 			fmt[4] = 'M';		/* I *hate* SCCS... */
48146043Sbostic 			(void)time(&t);
48246670Sbostic 			(void)strftime(db, sizeof(db), fmt, localtime(&t));
48346043Sbostic 			puts(db);
48415713Sralph 			break;
48546670Sbostic 		}
48615713Sralph 
48713795Ssam 		case '%':
48813795Ssam 			putchr('%');
48913795Ssam 			break;
49013795Ssam 		}
49113795Ssam 		cp++;
49213795Ssam 	}
49313795Ssam }
494