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