xref: /csrg-svn/libexec/getty/subr.c (revision 25233)
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.3 (Berkeley) 10/18/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] = '\377';
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 	{ "B19200",	"std.19200" },
389 	{ 0 }
390 };
391 
392 char *
393 portselector()
394 {
395 	char c, baud[20], *type = "default";
396 	register struct portselect *ps;
397 	int len;
398 
399 	alarm(5*60);
400 	for (len = 0; len < sizeof (baud) - 1; len++) {
401 		if (read(0, &c, 1) <= 0)
402 			break;
403 		c &= 0177;
404 		if (c == '\n' || c == '\r')
405 			break;
406 		if (c == 'B')
407 			len = 0;	/* in case of leading garbage */
408 		baud[len] = c;
409 	}
410 	baud[len] = '\0';
411 	for (ps = portspeeds; ps->ps_baud; ps++)
412 		if (strcmp(ps->ps_baud, baud) == 0) {
413 			type = ps->ps_type;
414 			break;
415 		}
416 	sleep(2);	/* wait for connection to complete */
417 	return (type);
418 }
419 
420 /*
421  * This auto-baud speed select mechanism is written for the Micom 600
422  * portselector. Selection is done by looking at how the character '\r'
423  * is garbled at the different speeds.
424  */
425 #include <sys/time.h>
426 
427 char *
428 autobaud()
429 {
430 	int rfds;
431 	struct timeval timeout;
432 	char c, *type = "9600-baud";
433 	int null = 0;
434 
435 	ioctl(0, TIOCFLUSH, &null);
436 	rfds = 1 << 0;
437 	timeout.tv_sec = 5;
438 	timeout.tv_usec = 0;
439 	if (select(32, &rfds, (int *)0, (int *)0, &timeout) <= 0)
440 		return (type);
441 	if (read(0, &c, sizeof(char)) != sizeof(char))
442 		return (type);
443 	timeout.tv_sec = 0;
444 	timeout.tv_usec = 20;
445 	(void) select(32, (int *)0, (int *)0, (int *)0, &timeout);
446 	ioctl(0, TIOCFLUSH, &null);
447 	switch (c & 0377) {
448 
449 	case 0200:		/* 300-baud */
450 		type = "300-baud";
451 		break;
452 
453 	case 0346:		/* 1200-baud */
454 		type = "1200-baud";
455 		break;
456 
457 	case  015:		/* 2400-baud */
458 	case 0215:
459 		type = "2400-baud";
460 		break;
461 
462 	default:		/* 4800-baud */
463 		type = "4800-baud";
464 		break;
465 
466 	case 0377:		/* 9600-baud */
467 		type = "9600-baud";
468 		break;
469 	}
470 	return (type);
471 }
472