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