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