main.c revision 8870
1139823Simp/*-
21541Srgrimes * Copyright (c) 1980 The Regents of the University of California.
31541Srgrimes * All rights reserved.
4137668Smlaier *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 3. All advertising materials mentioning features or use of this software
141541Srgrimes *    must display the following acknowledgement:
151541Srgrimes *	This product includes software developed by the University of
161541Srgrimes *	California, Berkeley and its contributors.
171541Srgrimes * 4. Neither the name of the University nor the names of its contributors
181541Srgrimes *    may be used to endorse or promote products derived from this software
191541Srgrimes *    without specific prior written permission.
201541Srgrimes *
211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3010939Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311541Srgrimes * SUCH DAMAGE.
321541Srgrimes */
33172467Ssilby
34172467Ssilby#ifndef lint
35172467Ssilbychar copyright[] =
36204902Sqingli"@(#) Copyright (c) 1980 The Regents of the University of California.\n\
37143868Sglebius All rights reserved.\n";
381541Srgrimes#endif /* not lint */
391549Srgrimes
4024204Sbde#ifndef lint
411541Srgrimesstatic char sccsid[] = "@(#)main.c	5.16 (Berkeley) 3/27/91";
42164033Srwatson#endif /* not lint */
431541Srgrimes
44186948Sbz#define USE_OLD_TTY
4512704Sphk
46186948Sbz#include <sys/param.h>
4712704Sphk#include <sys/stat.h>
48192011Sqingli#include <signal.h>
491541Srgrimes#include <fcntl.h>
501541Srgrimes#include <sgtty.h>
51195914Sqingli#include <time.h>
52215207Sgnn#include <ctype.h>
53192011Sqingli#include <setjmp.h>
54186119Sqingli#include <syslog.h>
5555009Sshin#include <unistd.h>
561541Srgrimes#include <ctype.h>
57192011Sqingli#include <stdlib.h>
581541Srgrimes#include <string.h>
59228571Sglebius#include "gettytab.h"
601541Srgrimes#include "pathnames.h"
611541Srgrimes
6281127Sumestruct	sgttyb tmode = {
63170613Sbms	0, 0, CERASE, CKILL, 0
64228571Sglebius};
65189592Sbmsstruct	tchars tc = {
66195699Srwatson	CINTR, CQUIT, CSTART,
67195699Srwatson	CSTOP, CEOF, CBRK,
681541Srgrimes};
6992723Salfredstruct	ltchars ltc = {
7092723Salfred	CSUSP, CDSUSP, CRPRNT,
7192723Salfred	CFLUSH, CWERASE, CLNEXT
7292723Salfred};
7355009Sshin
7492723Salfredint crmod, digit, lower, upper;
75228571Sglebius
76228571Sglebiuschar	hostname[MAXHOSTNAMELEN];
77167729Sbmschar	name[16];
781541Srgrimeschar	dev[] = _PATH_DEV;
79228571Sglebiuschar	ttyn[32];
80228571Sglebiuschar	*portselector();
81228571Sglebiuschar	*ttyname();
82228571Sglebius
83149221Sglebius#define	OBUFSIZ		128
8421666Swollman#define	TABBUFSIZ	512
85207369Sbz
86207369Sbzchar	defent[TABBUFSIZ];
87207369Sbzchar	defstrs[TABBUFSIZ];
88215207Sgnnchar	tabent[TABBUFSIZ];
89215207Sgnnchar	tabstrs[TABBUFSIZ];
90215207Sgnn
911541Srgrimeschar	*env[128];
921541Srgrimes
93226401Sglebiuschar partab[] = {
941541Srgrimes	0001,0201,0201,0001,0201,0001,0001,0201,
951549Srgrimes	0202,0004,0003,0205,0005,0206,0201,0001,
96169454Srwatson	0201,0001,0001,0201,0001,0201,0201,0001,
971541Srgrimes	0001,0201,0201,0001,0201,0001,0001,0201,
981541Srgrimes	0200,0000,0000,0200,0000,0200,0200,0000,
991541Srgrimes	0000,0200,0200,0000,0200,0000,0000,0200,
1001541Srgrimes	0000,0200,0200,0000,0200,0000,0000,0200,
101194951Srwatson	0200,0000,0000,0200,0000,0200,0200,0000,
102226401Sglebius	0200,0000,0000,0200,0000,0200,0200,0000,
103226401Sglebius	0000,0200,0200,0000,0200,0000,0000,0200,
104226401Sglebius	0000,0200,0200,0000,0200,0000,0000,0200,
105226401Sglebius	0200,0000,0000,0200,0000,0200,0200,0000,
106194951Srwatson	0000,0200,0200,0000,0200,0000,0000,0200,
1071541Srgrimes	0200,0000,0000,0200,0000,0200,0200,0000,
108194951Srwatson	0200,0000,0000,0200,0000,0200,0200,0000,
1091541Srgrimes	0000,0200,0200,0000,0200,0000,0000,0201
1101541Srgrimes};
1111541Srgrimes
1121541Srgrimes#define	ERASE	tmode.sg_erase
113133486Sandre#define	KILL	tmode.sg_kill
114133486Sandre#define	EOT	tc.t_eofc
115133486Sandre
116133486Sandrejmp_buf timeout;
117169454Srwatson
118133486Sandrestatic void
119133486Sandredingdong()
120133486Sandre{
121194951Srwatson
122133486Sandre	alarm(0);
123194951Srwatson	signal(SIGALRM, SIG_DFL);
124194951Srwatson	longjmp(timeout, 1);
125184295Sbz}
126194951Srwatson
127133486Sandrejmp_buf	intrupt;
128194951Srwatson
129184295Sbzstatic void
130133486Sandreinterrupt()
131133486Sandre{
132133486Sandre
1331541Srgrimes	signal(SIGINT, interrupt);
1341541Srgrimes	longjmp(intrupt, 1);
1351541Srgrimes}
1361541Srgrimes
1371549Srgrimesmain(argc, argv)
138169454Srwatson	int argc;
1391541Srgrimes	char **argv;
1401541Srgrimes{
1411541Srgrimes	extern	char **environ;
1421541Srgrimes	char *tname;
143166450Sbms	int repcnt = 0;
1441541Srgrimes
1451541Srgrimes	signal(SIGINT, SIG_IGN);
1461541Srgrimes	signal(SIGQUIT, SIG_IGN);
1471541Srgrimes
1481541Srgrimes	openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
1491541Srgrimes	gethostname(hostname, sizeof(hostname));
1501541Srgrimes	if (hostname[0] == '\0')
1511541Srgrimes		strcpy(hostname, "Amnesiac");
1521541Srgrimes	/*
1531541Srgrimes	 * The following is a work around for vhangup interactions
1541541Srgrimes	 * which cause great problems getting window systems started.
1551541Srgrimes	 * If the tty line is "-", we do the old style getty presuming
15612296Sphk	 * that the file descriptors are already set up for us.
157169454Srwatson	 * J. Gettys - MIT Project Athena.
1581541Srgrimes	 */
1591541Srgrimes	if (argc <= 2 || strcmp(argv[2], "-") == 0)
1601541Srgrimes	    strcpy(ttyn, ttyname(0));
1611541Srgrimes	else {
1621541Srgrimes	    int i;
1634127Swollman
164133874Srwatson	    strcpy(ttyn, dev);
1651541Srgrimes	    strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
1661541Srgrimes	    if (strcmp(argv[0], "+") != 0) {
1671541Srgrimes		chown(ttyn, 0, 0);
1681541Srgrimes		chmod(ttyn, 0600);
1691541Srgrimes		revoke(ttyn);
17055009Sshin		while ((i = open(ttyn, O_RDWR)) == -1) {
17155009Sshin			if (repcnt % 10 == 0) {
17255009Sshin				syslog(LOG_ERR, "%s: %m", ttyn);
17355009Sshin				closelog();
17455009Sshin			}
17555009Sshin			repcnt++;
17655009Sshin			sleep(60);
17755009Sshin		}
17855009Sshin		login_tty(i);
17955009Sshin	    }
18055009Sshin	}
18155009Sshin
18255009Sshin	gettable("default", defent, defstrs);
18355009Sshin	gendefaults();
18455009Sshin	tname = "default";
18555009Sshin	if (argc > 1)
18655009Sshin		tname = argv[1];
18755009Sshin	for (;;) {
18855009Sshin		int off = 0;
189184295Sbz		int flushboth = 0;
19055009Sshin		struct sgttyb fake;
19155009Sshin
19255009Sshin		gettable(tname, tabent, tabstrs);
193169454Srwatson		if (OPset || EPset || APset)
19455009Sshin			APset++, OPset++, EPset++;
19555009Sshin		setdefaults();
19655009Sshin		ioctl(0, TIOCFLUSH, &flushboth);         /* clear out the crap */
19755009Sshin		ioctl(0, FIONBIO, &off);	/* turn off non-blocking mode */
19855009Sshin		ioctl(0, FIOASYNC, &off);	/* ditto for async mode */
19955009Sshin		ioctl(0, TIOCGETP, &fake);      /* initialize kernel termios */
20055009Sshin		if (IS)
20155009Sshin			tmode.sg_ispeed = speed(IS);
20255009Sshin		else if (SP)
20355009Sshin			tmode.sg_ispeed = speed(SP);
20455009Sshin		if (OS)
20555009Sshin			tmode.sg_ospeed = speed(OS);
2061541Srgrimes		else if (SP)
2071541Srgrimes			tmode.sg_ospeed = speed(SP);
208191443Srwatson		set_tmode(0);
209191443Srwatson		setchars();
2101541Srgrimes		ioctl(0, TIOCSETC, &tc);
2111541Srgrimes		if (HC)
2121549Srgrimes			ioctl(0, TIOCHPCL, 0);
213169454Srwatson		if (AB) {
214169454Srwatson			extern char *autobaud();
2151541Srgrimes
2161541Srgrimes			tname = autobaud();
217184295Sbz			continue;
2181541Srgrimes		}
219168032Sbms		if (PS) {
22084102Sjlemon			tname = portselector();
221189592Sbms			continue;
2221541Srgrimes		}
2231541Srgrimes		if (CL && *CL)
224194951Srwatson			putpad(CL);
225168032Sbms		edithost(HE);
226228768Sglebius		if (IM && *IM)
2271541Srgrimes			putf(IM);
228228768Sglebius		if (setjmp(timeout)) {
229228768Sglebius			tmode.sg_ispeed = tmode.sg_ospeed = 0;
230228768Sglebius			ioctl(0, TIOCSETP, &tmode);
231228768Sglebius			exit(1);
232228768Sglebius		}
233228768Sglebius		if (TO) {
234228768Sglebius			signal(SIGALRM, dingdong);
235184295Sbz			alarm(TO);
236168032Sbms		}
23787124Sbrian		if (getname()) {
238168032Sbms			register int i;
23987124Sbrian
240191443Srwatson			alarm(0);
241191443Srwatson			signal(SIGALRM, SIG_DFL);
242191443Srwatson			oflush();
243191443Srwatson			if (name[0] == '-') {
24455009Sshin				puts("user names may not start with '-'.");
245191443Srwatson				continue;
246191443Srwatson			}
247191443Srwatson			if (!(upper || lower || digit))
248191443Srwatson				continue;
249227791Sglebius			set_tmode(2);
250227791Sglebius			ioctl(0, TIOCSLTC, &ltc);
251227791Sglebius			for (i = 0; environ[i] != (char *)0; i++)
252227791Sglebius				env[i] = environ[i];
253227791Sglebius			makeenv(&env[i]);
254227791Sglebius
255227791Sglebius			execle(LO, "login", "-p", name, (char *) 0, env);
256227791Sglebius			syslog(LOG_ERR, "%s: %m", LO);
257227791Sglebius			exit(1);
258227791Sglebius		}
259227791Sglebius		signal(SIGINT, SIG_IGN);
260227831Sglebius		alarm(0);
261227831Sglebius		signal(SIGALRM, SIG_DFL);
262227791Sglebius		if (NX && *NX)
263227791Sglebius			tname = NX;
264228768Sglebius	}
265228768Sglebius}
266228768Sglebius
267228768Sglebiusgetname()
268228768Sglebius{
269228768Sglebius	register int c;
270228768Sglebius	register char *np;
271227791Sglebius	char cs;
272227791Sglebius	int flushin = 1 /*FREAD*/;
273227791Sglebius
274227791Sglebius	/*
275228768Sglebius	 * Interrupt may happen if we use CBREAK mode
276227791Sglebius	 */
277191443Srwatson	if (setjmp(intrupt)) {
278191443Srwatson		signal(SIGINT, SIG_IGN);
279191443Srwatson		return (0);
280191443Srwatson	}
281227791Sglebius	signal(SIGINT, interrupt);
282227791Sglebius	ioctl(0, TIOCFLUSH, &flushin);         /* purge any input */
283227791Sglebius	prompt();
284191443Srwatson	oflush();
285191443Srwatson	if (PF > 0) {
28655009Sshin		sleep(PF);
287164033Srwatson		PF = 0;
288164033Srwatson	}
289164033Srwatson	set_tmode(1);
290164033Srwatson	crmod = digit = lower = upper = 0;
291164033Srwatson	np = name;
292184295Sbz	for (;;) {
293184295Sbz		oflush();
294164033Srwatson		if (read(STDIN_FILENO, &cs, 1) <= 0)
295164033Srwatson			exit(0);
29655009Sshin		if ((c = cs&0177) == 0)
297164033Srwatson			return (0);
298164033Srwatson		if (c == EOT || c == 4 /*^D*/)
299164033Srwatson			exit(1);
300164033Srwatson		if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
301164033Srwatson			putf("\r\n");
302184295Sbz			break;
303184295Sbz		}
304164033Srwatson		if (islower(c))
305164033Srwatson			lower = 1;
30655009Sshin		else if (isupper(c))
307184295Sbz			upper = 1;
308184295Sbz		else if (c == ERASE || c == '\b' || c == 0177) {
30983366Sjulian			if (np > name) {
310191443Srwatson				np--;
311191443Srwatson				if (tmode.sg_ospeed >= B1200)
312191443Srwatson					puts("\b \b");
313191443Srwatson				else
314191443Srwatson					putchr(cs);
31555009Sshin			}
31655009Sshin			continue;
317191443Srwatson		} else if (c == KILL || c == 025 /*^U*/) {
318191443Srwatson			putchr('\r');
319191443Srwatson			if (tmode.sg_ospeed < B1200)
3201541Srgrimes				putchr('\n');
321191456Srwatson			/* this is the way they do it down under ... */
322191456Srwatson			else if (np > name)
323191456Srwatson				puts("                                     \r");
324191456Srwatson			prompt();
325191456Srwatson			np = name;
326191456Srwatson			continue;
327191456Srwatson		} else if (isdigit(c))
328191456Srwatson			digit++;
329191456Srwatson		if (IG && (c <= ' ' || c > 0176))
330191456Srwatson			continue;
331191456Srwatson		*np++ = c;
332191456Srwatson		putchr(cs);
333191456Srwatson	}
334191456Srwatson	signal(SIGINT, SIG_IGN);
335191456Srwatson	*np = 0;
336191456Srwatson	if (c == '\r')
337191456Srwatson		crmod = 1;
338191456Srwatson	if (upper && !lower && !LC || UC)
339191456Srwatson		for (np = name; *np; np++)
340191456Srwatson			if (isupper(*np))
341191456Srwatson				*np = tolower(*np);
342191456Srwatson	return (1);
343191456Srwatson}
344191456Srwatson
345191456Srwatsonstatic
3461541Srgrimesshort	tmspc10[] = {
34714632Sfenner	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
348191443Srwatson};
349191443Srwatson
3501541Srgrimesputpad(s)
351191443Srwatson	register char *s;
352194951Srwatson{
353191443Srwatson	register pad = 0;
354191443Srwatson	register mspc10;
355191443Srwatson
356191443Srwatson	if (isdigit(*s)) {
357191443Srwatson		while (isdigit(*s)) {
358191443Srwatson			pad *= 10;
359191443Srwatson			pad += *s++ - '0';
360191443Srwatson		}
361191443Srwatson		pad *= 10;
362194760Srwatson		if (*s == '.' && isdigit(s[1])) {
363194760Srwatson			pad += s[1] - '0';
364194951Srwatson			s += 2;
365191443Srwatson		}
366194760Srwatson	}
367191443Srwatson
368191443Srwatson	puts(s);
369191443Srwatson	/*
370191443Srwatson	 * If no delay needed, or output speed is
371191443Srwatson	 * not comprehensible, then don't try to delay.
372191443Srwatson	 */
373191443Srwatson	if (pad == 0)
374191443Srwatson		return;
37584102Sjlemon	if (tmode.sg_ospeed <= 0 ||
37684102Sjlemon	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
377191443Srwatson		return;
378194760Srwatson
379194760Srwatson	/*
380194760Srwatson	 * Round up by a half a character frame, and then do the delay.
38184102Sjlemon	 * Too bad there are no user program accessible programmed delays.
382191443Srwatson	 * Transmitting pad characters slows many terminals down and also
383191443Srwatson	 * loads the system.
3841541Srgrimes	 */
385191500Srwatson	mspc10 = tmspc10[tmode.sg_ospeed];
3861541Srgrimes	pad += mspc10 / 2;
3871541Srgrimes	for (pad /= mspc10; pad > 0; pad--)
3881541Srgrimes		putchr(*PC);
389227958Sglebius}
390194760Srwatson
391194760Srwatsonputs(s)
392194951Srwatson	register char *s;
39371999Sphk{
3948071Swollman	while (*s)
3958071Swollman		putchr(*s++);
3968071Swollman}
3978071Swollman
3988071Swollmanchar	outbuf[OBUFSIZ];
399194760Srwatsonint	obufcnt = 0;
400194760Srwatson
401194760Srwatsonputchr(cc)
402194760Srwatson{
403194951Srwatson	char c;
4048876Srgrimes
4058071Swollman	c = cc;
4068071Swollman	if (!NP) {
4078071Swollman		c |= partab[c&0177] & 0200;
408191500Srwatson		if (OP)
409194760Srwatson			c ^= 0200;
4108071Swollman	}
4111541Srgrimes	if (!UB) {
412191500Srwatson		outbuf[obufcnt++] = c;
413191500Srwatson		if (obufcnt >= OBUFSIZ)
414194760Srwatson			oflush();
415191500Srwatson	} else
4161541Srgrimes		write(STDOUT_FILENO, &c, 1);
4171541Srgrimes}
4181541Srgrimes
4191541Srgrimesoflush()
420184295Sbz{
42120407Swollman	if (obufcnt)
422191500Srwatson		write(STDOUT_FILENO, outbuf, obufcnt);
423191500Srwatson	obufcnt = 0;
424191500Srwatson}
425191500Srwatson
426194760Srwatsonprompt()
427191500Srwatson{
428191500Srwatson
42920407Swollman	putf(LM);
430194602Srwatson	if (CO)
43120407Swollman		putchr('\n');
43220407Swollman}
43320407Swollman
434108033Shsuputf(cp)
4351541Srgrimes	register char *cp;
43685740Sdes{
4371541Srgrimes	extern char editedhost[];
4381541Srgrimes	time_t t;
4391541Srgrimes	char *slash, db[100];
4401541Srgrimes
4411541Srgrimes	while (*cp) {
442151824Sglebius		if (*cp != '%') {
443194760Srwatson			putchr(*cp++);
444194760Srwatson			continue;
445191285Srwatson		}
446194760Srwatson		switch (*++cp) {
447194760Srwatson
448194951Srwatson		case 't':
449181803Sbz			slash = rindex(ttyn, '/');
450194951Srwatson			if (slash == (char *) 0)
45187124Sbrian				puts(ttyn);
4521541Srgrimes			else
4531541Srgrimes				puts(&slash[1]);
4541541Srgrimes			break;
4551541Srgrimes
4561541Srgrimes		case 'h':
4571541Srgrimes			puts(editedhost);
4581541Srgrimes			break;
4591541Srgrimes
460191500Srwatson		case 'd': {
461191500Srwatson			static char fmt[] = "%l:% %p on %A, %d %B %Y";
462194760Srwatson
463191500Srwatson			fmt[4] = 'M';		/* I *hate* SCCS... */
4641541Srgrimes			(void)time(&t);
4651541Srgrimes			(void)strftime(db, sizeof(db), fmt, localtime(&t));
466191500Srwatson			puts(db);
467191500Srwatson			break;
468194760Srwatson		}
469194760Srwatson
470191500Srwatson		case '%':
4711541Srgrimes			putchr('%');
4721541Srgrimes			break;
4731541Srgrimes		}
474194760Srwatson		cp++;
4751541Srgrimes	}
4761541Srgrimes}
477191500Srwatson
478191500Srwatson/*
479194760Srwatson * The conversions from sgttyb to termios make LITOUT and PASS8 affect
480191500Srwatson * the parity.  So every TIOCSETP ioctl has to be paired with a TIOCLSET
4811541Srgrimes * ioctl (at least if LITOUT or PASS8 has changed, and PASS8 may vary
482194760Srwatson * with 'n').
4831541Srgrimes */
4841541Srgrimesset_tmode(n)
485191500Srwatson	int n;
486191500Srwatson{
487194760Srwatson	long allflags;
488191500Srwatson
4891541Srgrimes	allflags = setflags(n);
490194760Srwatson	tmode.sg_flags = allflags & 0xffff;
4911541Srgrimes	allflags >>= 16;
4921541Srgrimes	if (n == 2) {
4931541Srgrimes		if (crmod || NL)
494194760Srwatson			tmode.sg_flags |= CRMOD;
4951541Srgrimes		if (upper || UC)
4961541Srgrimes			tmode.sg_flags |= LCASE;
497191500Srwatson		if (lower || LC)
498191500Srwatson			tmode.sg_flags &= ~LCASE;
499194760Srwatson	}
500191500Srwatson	ioctl(0, TIOCSETP, &tmode);
5011541Srgrimes	ioctl(0, TIOCLSET, &allflags);
5021541Srgrimes}
503184295Sbz