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