xref: /csrg-svn/libexec/getty/subr.c (revision 42668)
1 /*
2  * Copyright (c) 1983 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)subr.c	5.6 (Berkeley) 06/01/90";
20 #endif /* not lint */
21 
22 /*
23  * Melbourne getty.
24  */
25 #define USE_OLD_TTY
26 #include <sgtty.h>
27 #include "gettytab.h"
28 
29 extern	struct sgttyb tmode;
30 extern	struct tchars tc;
31 extern	struct ltchars ltc;
32 
33 /*
34  * Get a table entry.
35  */
36 gettable(name, buf, area)
37 	char *name, *buf, *area;
38 {
39 	register struct gettystrs *sp;
40 	register struct gettynums *np;
41 	register struct gettyflags *fp;
42 	register n;
43 
44 	hopcount = 0;		/* new lookup, start fresh */
45 	if (getent(buf, name) != 1)
46 		return;
47 
48 	for (sp = gettystrs; sp->field; sp++)
49 		sp->value = getstr(sp->field, &area);
50 	for (np = gettynums; np->field; np++) {
51 		n = getnum(np->field);
52 		if (n == -1)
53 			np->set = 0;
54 		else {
55 			np->set = 1;
56 			np->value = n;
57 		}
58 	}
59 	for (fp = gettyflags; fp->field; fp++) {
60 		n = getflag(fp->field);
61 		if (n == -1)
62 			fp->set = 0;
63 		else {
64 			fp->set = 1;
65 			fp->value = n ^ fp->invrt;
66 		}
67 	}
68 }
69 
70 gendefaults()
71 {
72 	register struct gettystrs *sp;
73 	register struct gettynums *np;
74 	register struct gettyflags *fp;
75 
76 	for (sp = gettystrs; sp->field; sp++)
77 		if (sp->value)
78 			sp->defalt = sp->value;
79 	for (np = gettynums; np->field; np++)
80 		if (np->set)
81 			np->defalt = np->value;
82 	for (fp = gettyflags; fp->field; fp++)
83 		if (fp->set)
84 			fp->defalt = fp->value;
85 		else
86 			fp->defalt = fp->invrt;
87 }
88 
89 setdefaults()
90 {
91 	register struct gettystrs *sp;
92 	register struct gettynums *np;
93 	register struct gettyflags *fp;
94 
95 	for (sp = gettystrs; sp->field; sp++)
96 		if (!sp->value)
97 			sp->value = sp->defalt;
98 	for (np = gettynums; np->field; np++)
99 		if (!np->set)
100 			np->value = np->defalt;
101 	for (fp = gettyflags; fp->field; fp++)
102 		if (!fp->set)
103 			fp->value = fp->defalt;
104 }
105 
106 static char **
107 charnames[] = {
108 	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
109 	&SU, &DS, &RP, &FL, &WE, &LN, 0
110 };
111 
112 static char *
113 charvars[] = {
114 	&tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc,
115 	&tc.t_quitc, &tc.t_startc, &tc.t_stopc,
116 	&tc.t_eofc, &tc.t_brkc, &ltc.t_suspc,
117 	&ltc.t_dsuspc, &ltc.t_rprntc, &ltc.t_flushc,
118 	&ltc.t_werasc, &ltc.t_lnextc, 0
119 };
120 
121 setchars()
122 {
123 	register int i;
124 	register char *p;
125 
126 	for (i = 0; charnames[i]; i++) {
127 		p = *charnames[i];
128 		if (p && *p)
129 			*charvars[i] = *p;
130 		else
131 			*charvars[i] = '\377';
132 	}
133 }
134 
135 long
136 setflags(n)
137 {
138 	register long f;
139 
140 	switch (n) {
141 	case 0:
142 		if (F0set)
143 			return(F0);
144 		break;
145 	case 1:
146 		if (F1set)
147 			return(F1);
148 		break;
149 	default:
150 		if (F2set)
151 			return(F2);
152 		break;
153 	}
154 
155 	f = 0;
156 
157 	if (AP)
158 		f |= ANYP;
159 	else if (OP)
160 		f |= ODDP;
161 	else if (EP)
162 		f |= EVENP;
163 
164 	if (UC)
165 		f |= LCASE;
166 
167 	if (NL)
168 		f |= CRMOD;
169 
170 	f |= delaybits();
171 
172 	if (n == 1) {		/* read mode flags */
173 		if (RW)
174 			f |= RAW;
175 		else
176 			f |= CBREAK;
177 		return (f);
178 	}
179 
180 	if (!HT)
181 		f |= XTABS;
182 
183 	if (n == 0)
184 		return (f);
185 
186 	if (CB)
187 		f |= CRTBS;
188 
189 	if (CE)
190 		f |= CRTERA;
191 
192 	if (CK)
193 		f |= CRTKIL;
194 
195 	if (PE)
196 		f |= PRTERA;
197 
198 	if (EC)
199 		f |= ECHO;
200 
201 	if (XC)
202 		f |= CTLECH;
203 
204 	if (DX)
205 		f |= DECCTQ;
206 
207 	return (f);
208 }
209 
210 struct delayval {
211 	unsigned	delay;		/* delay in ms */
212 	int		bits;
213 };
214 
215 /*
216  * below are random guesses, I can't be bothered checking
217  */
218 
219 struct delayval	crdelay[] = {
220 	1,		CR1,
221 	2,		CR2,
222 	3,		CR3,
223 	83,		CR1,
224 	166,		CR2,
225 	0,		CR3,
226 };
227 
228 struct delayval nldelay[] = {
229 	1,		NL1,		/* special, calculated */
230 	2,		NL2,
231 	3,		NL3,
232 	100,		NL2,
233 	0,		NL3,
234 };
235 
236 struct delayval	bsdelay[] = {
237 	1,		BS1,
238 	0,		0,
239 };
240 
241 struct delayval	ffdelay[] = {
242 	1,		FF1,
243 	1750,		FF1,
244 	0,		FF1,
245 };
246 
247 struct delayval	tbdelay[] = {
248 	1,		TAB1,
249 	2,		TAB2,
250 	3,		XTABS,		/* this is expand tabs */
251 	100,		TAB1,
252 	0,		TAB2,
253 };
254 
255 delaybits()
256 {
257 	register f;
258 
259 	f  = adelay(CD, crdelay);
260 	f |= adelay(ND, nldelay);
261 	f |= adelay(FD, ffdelay);
262 	f |= adelay(TD, tbdelay);
263 	f |= adelay(BD, bsdelay);
264 	return (f);
265 }
266 
267 adelay(ms, dp)
268 	register ms;
269 	register struct delayval *dp;
270 {
271 	if (ms == 0)
272 		return (0);
273 	while (dp->delay && ms > dp->delay)
274 		dp++;
275 	return (dp->bits);
276 }
277 
278 char	editedhost[32];
279 
280 edithost(pat)
281 	register char *pat;
282 {
283 	register char *host = HN;
284 	register char *res = editedhost;
285 
286 	if (!pat)
287 		pat = "";
288 	while (*pat) {
289 		switch (*pat) {
290 
291 		case '#':
292 			if (*host)
293 				host++;
294 			break;
295 
296 		case '@':
297 			if (*host)
298 				*res++ = *host++;
299 			break;
300 
301 		default:
302 			*res++ = *pat;
303 			break;
304 
305 		}
306 		if (res == &editedhost[sizeof editedhost - 1]) {
307 			*res = '\0';
308 			return;
309 		}
310 		pat++;
311 	}
312 	if (*host)
313 		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
314 	else
315 		*res = '\0';
316 	editedhost[sizeof editedhost - 1] = '\0';
317 }
318 
319 struct speedtab {
320 	int	speed;
321 	int	uxname;
322 } speedtab[] = {
323 	50,	B50,
324 	75,	B75,
325 	110,	B110,
326 	134,	B134,
327 	150,	B150,
328 	200,	B200,
329 	300,	B300,
330 	600,	B600,
331 	1200,	B1200,
332 	1800,	B1800,
333 	2400,	B2400,
334 	4800,	B4800,
335 	9600,	B9600,
336 	19200,	EXTA,
337 	19,	EXTA,		/* for people who say 19.2K */
338 	38400,	EXTB,
339 	38,	EXTB,
340 	7200,	EXTB,		/* alternative */
341 	0
342 };
343 
344 speed(val)
345 {
346 	register struct speedtab *sp;
347 
348 	if (val <= 15)
349 		return (val);
350 
351 	for (sp = speedtab; sp->speed; sp++)
352 		if (sp->speed == val)
353 			return (sp->uxname);
354 
355 	return (B300);		/* default in impossible cases */
356 }
357 
358 makeenv(env)
359 	char *env[];
360 {
361 	static char termbuf[128] = "TERM=";
362 	register char *p, *q;
363 	register char **ep;
364 	char *index();
365 
366 	ep = env;
367 	if (TT && *TT) {
368 		strcat(termbuf, TT);
369 		*ep++ = termbuf;
370 	}
371 	if (p = EV) {
372 		q = p;
373 		while (q = index(q, ',')) {
374 			*q++ = '\0';
375 			*ep++ = p;
376 			p = q;
377 		}
378 		if (*p)
379 			*ep++ = p;
380 	}
381 	*ep = (char *)0;
382 }
383 
384 /*
385  * This speed select mechanism is written for the Develcon DATASWITCH.
386  * The Develcon sends a string of the form "B{speed}\n" at a predefined
387  * baud rate. This string indicates the user's actual speed.
388  * The routine below returns the terminal type mapped from derived speed.
389  */
390 struct	portselect {
391 	char	*ps_baud;
392 	char	*ps_type;
393 } portspeeds[] = {
394 	{ "B110",	"std.110" },
395 	{ "B134",	"std.134" },
396 	{ "B150",	"std.150" },
397 	{ "B300",	"std.300" },
398 	{ "B600",	"std.600" },
399 	{ "B1200",	"std.1200" },
400 	{ "B2400",	"std.2400" },
401 	{ "B4800",	"std.4800" },
402 	{ "B9600",	"std.9600" },
403 	{ "B19200",	"std.19200" },
404 	{ 0 }
405 };
406 
407 char *
408 portselector()
409 {
410 	char c, baud[20], *type = "default";
411 	register struct portselect *ps;
412 	int len;
413 
414 	alarm(5*60);
415 	for (len = 0; len < sizeof (baud) - 1; len++) {
416 		if (read(0, &c, 1) <= 0)
417 			break;
418 		c &= 0177;
419 		if (c == '\n' || c == '\r')
420 			break;
421 		if (c == 'B')
422 			len = 0;	/* in case of leading garbage */
423 		baud[len] = c;
424 	}
425 	baud[len] = '\0';
426 	for (ps = portspeeds; ps->ps_baud; ps++)
427 		if (strcmp(ps->ps_baud, baud) == 0) {
428 			type = ps->ps_type;
429 			break;
430 		}
431 	sleep(2);	/* wait for connection to complete */
432 	return (type);
433 }
434 
435 /*
436  * This auto-baud speed select mechanism is written for the Micom 600
437  * portselector. Selection is done by looking at how the character '\r'
438  * is garbled at the different speeds.
439  */
440 #include <sys/time.h>
441 
442 char *
443 autobaud()
444 {
445 	int rfds;
446 	struct timeval timeout;
447 	char c, *type = "9600-baud";
448 	int null = 0;
449 
450 	ioctl(0, TIOCFLUSH, &null);
451 	rfds = 1 << 0;
452 	timeout.tv_sec = 5;
453 	timeout.tv_usec = 0;
454 	if (select(32, &rfds, (int *)0, (int *)0, &timeout) <= 0)
455 		return (type);
456 	if (read(0, &c, sizeof(char)) != sizeof(char))
457 		return (type);
458 	timeout.tv_sec = 0;
459 	timeout.tv_usec = 20;
460 	(void) select(32, (int *)0, (int *)0, (int *)0, &timeout);
461 	ioctl(0, TIOCFLUSH, &null);
462 	switch (c & 0377) {
463 
464 	case 0200:		/* 300-baud */
465 		type = "300-baud";
466 		break;
467 
468 	case 0346:		/* 1200-baud */
469 		type = "1200-baud";
470 		break;
471 
472 	case  015:		/* 2400-baud */
473 	case 0215:
474 		type = "2400-baud";
475 		break;
476 
477 	default:		/* 4800-baud */
478 		type = "4800-baud";
479 		break;
480 
481 	case 0377:		/* 9600-baud */
482 		type = "9600-baud";
483 		break;
484 	}
485 	return (type);
486 }
487