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