xref: /csrg-svn/libexec/getty/main.c (revision 13795)
1*13795Ssam #ifndef lint
2*13795Ssam static char sccsid[] = "@(#)main.c	4.1 (Berkeley) 83/07/06";
3*13795Ssam #endif
4*13795Ssam 
5*13795Ssam /*
6*13795Ssam  * getty -- adapt to terminal speed on dialup, and call login
7*13795Ssam  *
8*13795Ssam  * Melbourne getty, June 83, kre.
9*13795Ssam  */
10*13795Ssam 
11*13795Ssam #include <sgtty.h>
12*13795Ssam #include <signal.h>
13*13795Ssam #include <ctype.h>
14*13795Ssam #include <setjmp.h>
15*13795Ssam #include "gettytab.h"
16*13795Ssam 
17*13795Ssam struct	sgttyb tmode = {
18*13795Ssam 	0, 0, CERASE, CKILL, 0
19*13795Ssam };
20*13795Ssam struct	tchars tc = {
21*13795Ssam 	CINTR, CQUIT, CSTART,
22*13795Ssam 	CSTOP, CEOF, CBRK,
23*13795Ssam };
24*13795Ssam struct	ltchars ltc = {
25*13795Ssam 	CSUSP, CDSUSP, CRPRNT,
26*13795Ssam 	CFLUSH, CWERASE, CLNEXT
27*13795Ssam };
28*13795Ssam 
29*13795Ssam int	crmod;
30*13795Ssam int	upper;
31*13795Ssam int	lower;
32*13795Ssam int	digit;
33*13795Ssam 
34*13795Ssam char	hostname[32];
35*13795Ssam char	name[16];
36*13795Ssam char	*portselector();
37*13795Ssam 
38*13795Ssam #define	TABBUFSIZ	512
39*13795Ssam 
40*13795Ssam char	defent[TABBUFSIZ];
41*13795Ssam char	defstrs[TABBUFSIZ];
42*13795Ssam char	tabent[TABBUFSIZ];
43*13795Ssam char	tabstrs[TABBUFSIZ];
44*13795Ssam 
45*13795Ssam char	*env[128];
46*13795Ssam 
47*13795Ssam char partab[] = {
48*13795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
49*13795Ssam 	0202,0004,0003,0205,0005,0206,0201,0001,
50*13795Ssam 	0201,0001,0001,0201,0001,0201,0201,0001,
51*13795Ssam 	0001,0201,0201,0001,0201,0001,0001,0201,
52*13795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
53*13795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
54*13795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
55*13795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
56*13795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
57*13795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
58*13795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
59*13795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
60*13795Ssam 	0000,0200,0200,0000,0200,0000,0000,0200,
61*13795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
62*13795Ssam 	0200,0000,0000,0200,0000,0200,0200,0000,
63*13795Ssam 	0000,0200,0200,0000,0200,0000,0000,0201
64*13795Ssam };
65*13795Ssam 
66*13795Ssam #define	ERASE	tmode.sg_erase
67*13795Ssam #define	KILL	tmode.sg_kill
68*13795Ssam #define	EOT	tc.t_eofc
69*13795Ssam 
70*13795Ssam jmp_buf timeout;
71*13795Ssam 
72*13795Ssam dingdong()
73*13795Ssam {
74*13795Ssam 
75*13795Ssam 	alarm(0);
76*13795Ssam 	signal(SIGALRM, SIG_DFL);
77*13795Ssam 	longjmp(timeout, 1);
78*13795Ssam }
79*13795Ssam 
80*13795Ssam main(argc, argv)
81*13795Ssam 	char *argv[];
82*13795Ssam {
83*13795Ssam 	char *tname;
84*13795Ssam 	long allflags;
85*13795Ssam 
86*13795Ssam /*
87*13795Ssam 	signal(SIGINT, SIG_IGN);
88*13795Ssam 	signal(SIGQUIT, SIG_DFL);
89*13795Ssam */
90*13795Ssam 	gethostname(hostname, sizeof(hostname));
91*13795Ssam 	if (hostname[0] == '\0')
92*13795Ssam 		strcpy(hostname, "Amnesiac");
93*13795Ssam 	gettable("default", defent, defstrs);
94*13795Ssam 	gendefaults();
95*13795Ssam 	tname = "default";
96*13795Ssam 	if (argc > 1)
97*13795Ssam 		tname = argv[1];
98*13795Ssam 	for (;;) {
99*13795Ssam 		int ldisp = OTTYDISC;
100*13795Ssam 
101*13795Ssam 		gettable(tname, tabent, tabstrs);
102*13795Ssam 		setdefaults();
103*13795Ssam 		ioctl(0, TIOCFLUSH, 0);		/* clear out the crap */
104*13795Ssam 		if (IS)
105*13795Ssam 			tmode.sg_ispeed = speed(IS);
106*13795Ssam 		else if (SP)
107*13795Ssam 			tmode.sg_ispeed = speed(SP);
108*13795Ssam 		if (OS)
109*13795Ssam 			tmode.sg_ospeed = speed(OS);
110*13795Ssam 		else if (SP)
111*13795Ssam 			tmode.sg_ospeed = speed(SP);
112*13795Ssam 		tmode.sg_flags = setflags(0);
113*13795Ssam 		ioctl(0, TIOCSETP, &tmode);
114*13795Ssam 		setchars();
115*13795Ssam 		ioctl(0, TIOCSETC, &tc);
116*13795Ssam 		ioctl(0, TIOCSETD, &ldisp);
117*13795Ssam 		if (HC)
118*13795Ssam 			ioctl(0, TIOCHPCL, 0);
119*13795Ssam 		if (PS) {
120*13795Ssam 			tname = portselector();
121*13795Ssam 			continue;
122*13795Ssam 		}
123*13795Ssam 		if (CL && *CL)
124*13795Ssam 			putpad(CL);
125*13795Ssam 		edithost(HE);
126*13795Ssam 		if (IM && *IM)
127*13795Ssam 			putf(IM);
128*13795Ssam 		if (setjmp(timeout)) {
129*13795Ssam 			tmode.sg_ispeed = tmode.sg_ospeed = 0;
130*13795Ssam 			ioctl(0, TIOCSETP, &tmode);
131*13795Ssam 			exit(1);
132*13795Ssam 		}
133*13795Ssam 		if (TO) {
134*13795Ssam 			signal(SIGALRM, dingdong);
135*13795Ssam 			alarm(TO);
136*13795Ssam 		}
137*13795Ssam 		if (getname()) {
138*13795Ssam 			alarm(0);
139*13795Ssam 			signal(SIGALRM, SIG_DFL);
140*13795Ssam 			if (!(upper||lower||digit))
141*13795Ssam 				continue;
142*13795Ssam 			allflags = setflags(2);
143*13795Ssam 			tmode.sg_flags = allflags & 0xffff;
144*13795Ssam 			allflags >>= 16;
145*13795Ssam 			if (crmod || NL)
146*13795Ssam 				tmode.sg_flags |= CRMOD;
147*13795Ssam 			if (upper || UC)
148*13795Ssam 				tmode.sg_flags |= LCASE;
149*13795Ssam 			if (lower || LC)
150*13795Ssam 				tmode.sg_flags &= ~LCASE;
151*13795Ssam 			ioctl(0, TIOCSETP, &tmode);
152*13795Ssam 			ioctl(0, TIOCSLTC, &ltc);
153*13795Ssam 			ioctl(0, TIOCLSET, &allflags);
154*13795Ssam 			putchr('\n');
155*13795Ssam 			makeenv(env);
156*13795Ssam 			execle(LO, "login", name, (char *)0, env);
157*13795Ssam 			exit(1);
158*13795Ssam 		}
159*13795Ssam 		alarm(0);
160*13795Ssam 		signal(SIGALRM, SIG_DFL);
161*13795Ssam 		if (NX && *NX)
162*13795Ssam 			tname = NX;
163*13795Ssam 	}
164*13795Ssam }
165*13795Ssam 
166*13795Ssam getname()
167*13795Ssam {
168*13795Ssam 	register char *np;
169*13795Ssam 	register c;
170*13795Ssam 	char cs;
171*13795Ssam 
172*13795Ssam 	tmode.sg_flags = setflags(0);
173*13795Ssam 	ioctl(0, TIOCSETP, &tmode);
174*13795Ssam 	tmode.sg_flags = setflags(1);
175*13795Ssam 	prompt();
176*13795Ssam 	ioctl(0, TIOCSETP, &tmode);
177*13795Ssam 	crmod = 0;
178*13795Ssam 	upper = 0;
179*13795Ssam 	lower = 0;
180*13795Ssam 	digit = 0;
181*13795Ssam 	np = name;
182*13795Ssam 	for (;;) {
183*13795Ssam 		if (read(0, &cs, 1) <= 0)
184*13795Ssam 			exit(0);
185*13795Ssam 		if ((c = cs&0177) == 0)
186*13795Ssam 			return (0);
187*13795Ssam 		if (c==EOT)
188*13795Ssam 			exit(1);
189*13795Ssam 		if (c=='\r' || c=='\n' || np >= &name[16])
190*13795Ssam 			break;
191*13795Ssam 
192*13795Ssam 		if (c>='a' && c <='z')
193*13795Ssam 			lower++;
194*13795Ssam 		else if (c>='A' && c<='Z') {
195*13795Ssam 			upper++;
196*13795Ssam 		} else if (c==ERASE) {
197*13795Ssam 			if (np > name) {
198*13795Ssam 				np--;
199*13795Ssam 				if (tmode.sg_ospeed >= B1200)
200*13795Ssam 					puts("\b \b");
201*13795Ssam 				else
202*13795Ssam 					putchr(cs);
203*13795Ssam 			}
204*13795Ssam 			continue;
205*13795Ssam 		} else if (c==KILL) {
206*13795Ssam 			putchr(cs);
207*13795Ssam 			putchr('\r');
208*13795Ssam 			if (tmode.sg_ospeed < B1200)
209*13795Ssam 				putchr('\n');
210*13795Ssam 			/* this is the way they do it down under ... */
211*13795Ssam 			else if (np > name)
212*13795Ssam 				puts("                                     \r");
213*13795Ssam 			prompt();
214*13795Ssam 			np = name;
215*13795Ssam 			continue;
216*13795Ssam 		} else if (c == ' ')
217*13795Ssam 			c = '_';
218*13795Ssam 		else if (c >= '0' && c <= '9')
219*13795Ssam 			digit++;
220*13795Ssam 		if (IG && (c < ' ' || c > 0176))
221*13795Ssam 			continue;
222*13795Ssam 		*np++ = c;
223*13795Ssam 		putchr(cs);
224*13795Ssam 	}
225*13795Ssam 	*np = 0;
226*13795Ssam 	if (c == '\r')
227*13795Ssam 		crmod++;
228*13795Ssam 	if (upper && !lower && !LC || UC)
229*13795Ssam 		for (np = name; *np; np++)
230*13795Ssam 			if (isupper(*np))
231*13795Ssam 				*np = tolower(*np);
232*13795Ssam 	return (1);
233*13795Ssam }
234*13795Ssam 
235*13795Ssam static
236*13795Ssam short	tmspc10[] = {
237*13795Ssam 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
238*13795Ssam };
239*13795Ssam 
240*13795Ssam putpad(s)
241*13795Ssam 	register char *s;
242*13795Ssam {
243*13795Ssam 	register pad = 0;
244*13795Ssam 	register mspc10;
245*13795Ssam 
246*13795Ssam 	if (isdigit(*s)) {
247*13795Ssam 		while (isdigit(*s)) {
248*13795Ssam 			pad *= 10;
249*13795Ssam 			pad += *s++ - '0';
250*13795Ssam 		}
251*13795Ssam 		pad *= 10;
252*13795Ssam 		if (*s == '.' && isdigit(s[1])) {
253*13795Ssam 			pad += s[1] - '0';
254*13795Ssam 			s += 2;
255*13795Ssam 		}
256*13795Ssam 	}
257*13795Ssam 
258*13795Ssam 	puts(s);
259*13795Ssam 	/*
260*13795Ssam 	 * If no delay needed, or output speed is
261*13795Ssam 	 * not comprehensible, then don't try to delay.
262*13795Ssam 	 */
263*13795Ssam 	if (pad == 0)
264*13795Ssam 		return;
265*13795Ssam 	if (tmode.sg_ospeed <= 0 ||
266*13795Ssam 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
267*13795Ssam 		return;
268*13795Ssam 
269*13795Ssam 	/*
270*13795Ssam 	 * Round up by a half a character frame,
271*13795Ssam 	 * and then do the delay.
272*13795Ssam 	 * Too bad there are no user program accessible programmed delays.
273*13795Ssam 	 * Transmitting pad characters slows many
274*13795Ssam 	 * terminals down and also loads the system.
275*13795Ssam 	 */
276*13795Ssam 	mspc10 = tmspc10[tmode.sg_ospeed];
277*13795Ssam 	pad += mspc10 / 2;
278*13795Ssam 	for (pad /= mspc10; pad > 0; pad--)
279*13795Ssam 		putchr(*PC);
280*13795Ssam }
281*13795Ssam 
282*13795Ssam puts(s)
283*13795Ssam 	register char *s;
284*13795Ssam {
285*13795Ssam 
286*13795Ssam 	while (*s)
287*13795Ssam 		putchr(*s++);
288*13795Ssam }
289*13795Ssam 
290*13795Ssam putchr(cc)
291*13795Ssam {
292*13795Ssam 	char c;
293*13795Ssam 
294*13795Ssam 	c = cc;
295*13795Ssam 	c |= partab[c&0177] & 0200;
296*13795Ssam 	if (OP)
297*13795Ssam 		c ^= 0200;
298*13795Ssam 	write(1, &c, 1);
299*13795Ssam }
300*13795Ssam 
301*13795Ssam prompt()
302*13795Ssam {
303*13795Ssam 
304*13795Ssam 	putf(LM);
305*13795Ssam 	if (CO)
306*13795Ssam 		putchr('\n');
307*13795Ssam }
308*13795Ssam 
309*13795Ssam putf(cp)
310*13795Ssam 	register char *cp;
311*13795Ssam {
312*13795Ssam 	extern char editedhost[];
313*13795Ssam 
314*13795Ssam 	while (*cp) {
315*13795Ssam 		if (*cp != '%') {
316*13795Ssam 			putchr(*cp++);
317*13795Ssam 			continue;
318*13795Ssam 		}
319*13795Ssam 		switch (*++cp) {
320*13795Ssam 
321*13795Ssam 		case 'h':
322*13795Ssam 			puts(editedhost);
323*13795Ssam 			break;
324*13795Ssam 
325*13795Ssam 		case '%':
326*13795Ssam 			putchr('%');
327*13795Ssam 			break;
328*13795Ssam 		}
329*13795Ssam 		cp++;
330*13795Ssam 	}
331*13795Ssam }
332