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