xref: /csrg-svn/libexec/getty/subr.c (revision 25730)
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.4 (Berkeley) 01/07/86";
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 	if (DX)
193 		f |= DECCTQ;
194 
195 	return (f);
196 }
197 
198 struct delayval {
199 	unsigned	delay;		/* delay in ms */
200 	int		bits;
201 };
202 
203 /*
204  * below are random guesses, I can't be bothered checking
205  */
206 
207 struct delayval	crdelay[] = {
208 	1,		CR1,
209 	2,		CR2,
210 	3,		CR3,
211 	83,		CR1,
212 	166,		CR2,
213 	0,		CR3,
214 };
215 
216 struct delayval nldelay[] = {
217 	1,		NL1,		/* special, calculated */
218 	2,		NL2,
219 	3,		NL3,
220 	100,		NL2,
221 	0,		NL3,
222 };
223 
224 struct delayval	bsdelay[] = {
225 	1,		BS1,
226 	0,		0,
227 };
228 
229 struct delayval	ffdelay[] = {
230 	1,		FF1,
231 	1750,		FF1,
232 	0,		FF1,
233 };
234 
235 struct delayval	tbdelay[] = {
236 	1,		TAB1,
237 	2,		TAB2,
238 	3,		XTABS,		/* this is expand tabs */
239 	100,		TAB1,
240 	0,		TAB2,
241 };
242 
243 delaybits()
244 {
245 	register f;
246 
247 	f  = adelay(CD, crdelay);
248 	f |= adelay(ND, nldelay);
249 	f |= adelay(FD, ffdelay);
250 	f |= adelay(TD, tbdelay);
251 	f |= adelay(BD, bsdelay);
252 	return (f);
253 }
254 
255 adelay(ms, dp)
256 	register ms;
257 	register struct delayval *dp;
258 {
259 	if (ms == 0)
260 		return (0);
261 	while (dp->delay && ms > dp->delay)
262 		dp++;
263 	return (dp->bits);
264 }
265 
266 char	editedhost[32];
267 
268 edithost(pat)
269 	register char *pat;
270 {
271 	register char *host = HN;
272 	register char *res = editedhost;
273 
274 	if (!pat)
275 		pat = "";
276 	while (*pat) {
277 		switch (*pat) {
278 
279 		case '#':
280 			if (*host)
281 				host++;
282 			break;
283 
284 		case '@':
285 			if (*host)
286 				*res++ = *host++;
287 			break;
288 
289 		default:
290 			*res++ = *pat;
291 			break;
292 
293 		}
294 		if (res == &editedhost[sizeof editedhost - 1]) {
295 			*res = '\0';
296 			return;
297 		}
298 		pat++;
299 	}
300 	if (*host)
301 		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
302 	else
303 		*res = '\0';
304 	editedhost[sizeof editedhost - 1] = '\0';
305 }
306 
307 struct speedtab {
308 	int	speed;
309 	int	uxname;
310 } speedtab[] = {
311 	50,	B50,
312 	75,	B75,
313 	110,	B110,
314 	134,	B134,
315 	150,	B150,
316 	200,	B200,
317 	300,	B300,
318 	600,	B600,
319 	1200,	B1200,
320 	1800,	B1800,
321 	2400,	B2400,
322 	4800,	B4800,
323 	9600,	B9600,
324 	19200,	EXTA,
325 	19,	EXTA,		/* for people who say 19.2K */
326 	38400,	EXTB,
327 	38,	EXTB,
328 	7200,	EXTB,		/* alternative */
329 	0
330 };
331 
332 speed(val)
333 {
334 	register struct speedtab *sp;
335 
336 	if (val <= 15)
337 		return (val);
338 
339 	for (sp = speedtab; sp->speed; sp++)
340 		if (sp->speed == val)
341 			return (sp->uxname);
342 
343 	return (B300);		/* default in impossible cases */
344 }
345 
346 makeenv(env)
347 	char *env[];
348 {
349 	static char termbuf[128] = "TERM=";
350 	register char *p, *q;
351 	register char **ep;
352 	char *index();
353 
354 	ep = env;
355 	if (TT && *TT) {
356 		strcat(termbuf, TT);
357 		*ep++ = termbuf;
358 	}
359 	if (p = EV) {
360 		q = p;
361 		while (q = index(q, ',')) {
362 			*q++ = '\0';
363 			*ep++ = p;
364 			p = q;
365 		}
366 		if (*p)
367 			*ep++ = p;
368 	}
369 	*ep = (char *)0;
370 }
371 
372 /*
373  * This speed select mechanism is written for the Develcon DATASWITCH.
374  * The Develcon sends a string of the form "B{speed}\n" at a predefined
375  * baud rate. This string indicates the user's actual speed.
376  * The routine below returns the terminal type mapped from derived speed.
377  */
378 struct	portselect {
379 	char	*ps_baud;
380 	char	*ps_type;
381 } portspeeds[] = {
382 	{ "B110",	"std.110" },
383 	{ "B134",	"std.134" },
384 	{ "B150",	"std.150" },
385 	{ "B300",	"std.300" },
386 	{ "B600",	"std.600" },
387 	{ "B1200",	"std.1200" },
388 	{ "B2400",	"std.2400" },
389 	{ "B4800",	"std.4800" },
390 	{ "B9600",	"std.9600" },
391 	{ "B19200",	"std.19200" },
392 	{ 0 }
393 };
394 
395 char *
396 portselector()
397 {
398 	char c, baud[20], *type = "default";
399 	register struct portselect *ps;
400 	int len;
401 
402 	alarm(5*60);
403 	for (len = 0; len < sizeof (baud) - 1; len++) {
404 		if (read(0, &c, 1) <= 0)
405 			break;
406 		c &= 0177;
407 		if (c == '\n' || c == '\r')
408 			break;
409 		if (c == 'B')
410 			len = 0;	/* in case of leading garbage */
411 		baud[len] = c;
412 	}
413 	baud[len] = '\0';
414 	for (ps = portspeeds; ps->ps_baud; ps++)
415 		if (strcmp(ps->ps_baud, baud) == 0) {
416 			type = ps->ps_type;
417 			break;
418 		}
419 	sleep(2);	/* wait for connection to complete */
420 	return (type);
421 }
422 
423 /*
424  * This auto-baud speed select mechanism is written for the Micom 600
425  * portselector. Selection is done by looking at how the character '\r'
426  * is garbled at the different speeds.
427  */
428 #include <sys/time.h>
429 
430 char *
431 autobaud()
432 {
433 	int rfds;
434 	struct timeval timeout;
435 	char c, *type = "9600-baud";
436 	int null = 0;
437 
438 	ioctl(0, TIOCFLUSH, &null);
439 	rfds = 1 << 0;
440 	timeout.tv_sec = 5;
441 	timeout.tv_usec = 0;
442 	if (select(32, &rfds, (int *)0, (int *)0, &timeout) <= 0)
443 		return (type);
444 	if (read(0, &c, sizeof(char)) != sizeof(char))
445 		return (type);
446 	timeout.tv_sec = 0;
447 	timeout.tv_usec = 20;
448 	(void) select(32, (int *)0, (int *)0, (int *)0, &timeout);
449 	ioctl(0, TIOCFLUSH, &null);
450 	switch (c & 0377) {
451 
452 	case 0200:		/* 300-baud */
453 		type = "300-baud";
454 		break;
455 
456 	case 0346:		/* 1200-baud */
457 		type = "1200-baud";
458 		break;
459 
460 	case  015:		/* 2400-baud */
461 	case 0215:
462 		type = "2400-baud";
463 		break;
464 
465 	default:		/* 4800-baud */
466 		type = "4800-baud";
467 		break;
468 
469 	case 0377:		/* 9600-baud */
470 		type = "9600-baud";
471 		break;
472 	}
473 	return (type);
474 }
475