xref: /csrg-svn/libexec/getty/main.c (revision 13885)
1 #ifndef lint
2 static char sccsid[] = "@(#)main.c	4.4 (Berkeley) 83/07/09";
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 		sleep(PF);
201 		PF = 0;
202 	}
203 	ioctl(0, TIOCSETP, &tmode);
204 	crmod = 0;
205 	upper = 0;
206 	lower = 0;
207 	digit = 0;
208 	np = name;
209 	for (;;) {
210 		oflush();
211 		if (read(0, &cs, 1) <= 0)
212 			exit(0);
213 		if ((c = cs&0177) == 0)
214 			return (0);
215 		if (c == EOT)
216 			exit(1);
217 		if (c == '\r' || c == '\n' || np >= &name[16])
218 			break;
219 
220 		if (c >= 'a' && c <= 'z')
221 			lower++;
222 		else if (c >= 'A' && c <= 'Z') {
223 			upper++;
224 		} else if (c == ERASE || c == '#' || c == '\b') {
225 			if (np > name) {
226 				np--;
227 				if (tmode.sg_ospeed >= B1200)
228 					puts("\b \b");
229 				else
230 					putchr(cs);
231 			}
232 			continue;
233 		} else if (c == KILL || c == '@') {
234 			putchr(cs);
235 			putchr('\r');
236 			if (tmode.sg_ospeed < B1200)
237 				putchr('\n');
238 			/* this is the way they do it down under ... */
239 			else if (np > name)
240 				puts("                                     \r");
241 			prompt();
242 			np = name;
243 			continue;
244 		} else if (c == ' ')
245 			c = '_';
246 		else if (c >= '0' && c <= '9')
247 			digit++;
248 		if (IG && (c < ' ' || c > 0176))
249 			continue;
250 		*np++ = c;
251 		putchr(cs);
252 	}
253 	signal(SIGINT, SIG_IGN);
254 	*np = 0;
255 	if (c == '\r')
256 		crmod++;
257 	if (upper && !lower && !LC || UC)
258 		for (np = name; *np; np++)
259 			if (isupper(*np))
260 				*np = tolower(*np);
261 	return (1);
262 }
263 
264 static
265 short	tmspc10[] = {
266 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
267 };
268 
269 putpad(s)
270 	register char *s;
271 {
272 	register pad = 0;
273 	register mspc10;
274 
275 	if (isdigit(*s)) {
276 		while (isdigit(*s)) {
277 			pad *= 10;
278 			pad += *s++ - '0';
279 		}
280 		pad *= 10;
281 		if (*s == '.' && isdigit(s[1])) {
282 			pad += s[1] - '0';
283 			s += 2;
284 		}
285 	}
286 
287 	puts(s);
288 	/*
289 	 * If no delay needed, or output speed is
290 	 * not comprehensible, then don't try to delay.
291 	 */
292 	if (pad == 0)
293 		return;
294 	if (tmode.sg_ospeed <= 0 ||
295 	    tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
296 		return;
297 
298 	/*
299 	 * Round up by a half a character frame,
300 	 * and then do the delay.
301 	 * Too bad there are no user program accessible programmed delays.
302 	 * Transmitting pad characters slows many
303 	 * terminals down and also loads the system.
304 	 */
305 	mspc10 = tmspc10[tmode.sg_ospeed];
306 	pad += mspc10 / 2;
307 	for (pad /= mspc10; pad > 0; pad--)
308 		putchr(*PC);
309 }
310 
311 puts(s)
312 	register char *s;
313 {
314 
315 	while (*s)
316 		putchr(*s++);
317 }
318 
319 char	outbuf[OBUFSIZ];
320 int	obufcnt = 0;
321 
322 putchr(cc)
323 {
324 	char c;
325 
326 	c = cc;
327 	c |= partab[c&0177] & 0200;
328 	if (OP)
329 		c ^= 0200;
330 	if (!UB) {
331 		outbuf[obufcnt++] = c;
332 		if (obufcnt >= OBUFSIZ)
333 			oflush();
334 	} else
335 		write(1, &c, 1);
336 }
337 
338 oflush()
339 {
340 	if (obufcnt)
341 		write(1, outbuf, obufcnt);
342 	obufcnt = 0;
343 }
344 
345 prompt()
346 {
347 
348 	putf(LM);
349 	if (CO)
350 		putchr('\n');
351 }
352 
353 putf(cp)
354 	register char *cp;
355 {
356 	extern char editedhost[];
357 
358 	while (*cp) {
359 		if (*cp != '%') {
360 			putchr(*cp++);
361 			continue;
362 		}
363 		switch (*++cp) {
364 
365 		case 'h':
366 			puts(editedhost);
367 			break;
368 
369 		case '%':
370 			putchr('%');
371 			break;
372 		}
373 		cp++;
374 	}
375 }
376