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