xref: /original-bsd/libexec/getty/subr.c (revision f673f637)
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.11 (Berkeley) 05/17/93";
10 #endif /* not lint */
11 
12 /*
13  * Melbourne getty.
14  */
15 #define USE_OLD_TTY
16 #include <sgtty.h>
17 #include <string.h>
18 #include <unistd.h>
19 
20 #include "gettytab.h"
21 #include "extern.h"
22 
23 extern	struct sgttyb tmode;
24 extern	struct tchars tc;
25 extern	struct ltchars ltc;
26 
27 /*
28  * Get a table entry.
29  */
30 void
31 gettable(name, buf, area)
32 	char *name, *buf, *area;
33 {
34 	register struct gettystrs *sp;
35 	register struct gettynums *np;
36 	register struct gettyflags *fp;
37 	register n;
38 
39 	hopcount = 0;		/* new lookup, start fresh */
40 	if (getent(buf, name) != 1)
41 		return;
42 
43 	for (sp = gettystrs; sp->field; sp++)
44 		sp->value = getstr(sp->field, &area);
45 	for (np = gettynums; np->field; np++) {
46 		n = getnum(np->field);
47 		if (n == -1)
48 			np->set = 0;
49 		else {
50 			np->set = 1;
51 			np->value = n;
52 		}
53 	}
54 	for (fp = gettyflags; fp->field; fp++) {
55 		n = getflag(fp->field);
56 		if (n == -1)
57 			fp->set = 0;
58 		else {
59 			fp->set = 1;
60 			fp->value = n ^ fp->invrt;
61 		}
62 	}
63 }
64 
65 void
66 gendefaults()
67 {
68 	register struct gettystrs *sp;
69 	register struct gettynums *np;
70 	register struct gettyflags *fp;
71 
72 	for (sp = gettystrs; sp->field; sp++)
73 		if (sp->value)
74 			sp->defalt = sp->value;
75 	for (np = gettynums; np->field; np++)
76 		if (np->set)
77 			np->defalt = np->value;
78 	for (fp = gettyflags; fp->field; fp++)
79 		if (fp->set)
80 			fp->defalt = fp->value;
81 		else
82 			fp->defalt = fp->invrt;
83 }
84 
85 void
86 setdefaults()
87 {
88 	register struct gettystrs *sp;
89 	register struct gettynums *np;
90 	register struct gettyflags *fp;
91 
92 	for (sp = gettystrs; sp->field; sp++)
93 		if (!sp->value)
94 			sp->value = sp->defalt;
95 	for (np = gettynums; np->field; np++)
96 		if (!np->set)
97 			np->value = np->defalt;
98 	for (fp = gettyflags; fp->field; fp++)
99 		if (!fp->set)
100 			fp->value = fp->defalt;
101 }
102 
103 static char **
104 charnames[] = {
105 	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
106 	&SU, &DS, &RP, &FL, &WE, &LN, 0
107 };
108 
109 static char *
110 charvars[] = {
111 	&tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc,
112 	&tc.t_quitc, &tc.t_startc, &tc.t_stopc,
113 	&tc.t_eofc, &tc.t_brkc, &ltc.t_suspc,
114 	&ltc.t_dsuspc, &ltc.t_rprntc, &ltc.t_flushc,
115 	&ltc.t_werasc, &ltc.t_lnextc, 0
116 };
117 
118 void
119 setchars()
120 {
121 	register int i;
122 	register char *p;
123 
124 	for (i = 0; charnames[i]; i++) {
125 		p = *charnames[i];
126 		if (p && *p)
127 			*charvars[i] = *p;
128 		else
129 			*charvars[i] = '\377';
130 	}
131 }
132 
133 long
134 setflags(n)
135 	int 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 int
255 delaybits()
256 {
257 	register int f;
258 
259 	f  = adelay(CD, crdelay);
260 	f |= adelay(ND, nldelay);
261 	f |= adelay(FD, ffdelay);
262 	f |= adelay(TD, tbdelay);
263 	f |= adelay(BD, bsdelay);
264 	return (f);
265 }
266 
267 int
268 adelay(ms, dp)
269 	register ms;
270 	register struct delayval *dp;
271 {
272 	if (ms == 0)
273 		return (0);
274 	while (dp->delay && ms > dp->delay)
275 		dp++;
276 	return (dp->bits);
277 }
278 
279 char	editedhost[32];
280 
281 void
282 edithost(pat)
283 	register char *pat;
284 {
285 	register char *host = HN;
286 	register char *res = editedhost;
287 
288 	if (!pat)
289 		pat = "";
290 	while (*pat) {
291 		switch (*pat) {
292 
293 		case '#':
294 			if (*host)
295 				host++;
296 			break;
297 
298 		case '@':
299 			if (*host)
300 				*res++ = *host++;
301 			break;
302 
303 		default:
304 			*res++ = *pat;
305 			break;
306 
307 		}
308 		if (res == &editedhost[sizeof editedhost - 1]) {
309 			*res = '\0';
310 			return;
311 		}
312 		pat++;
313 	}
314 	if (*host)
315 		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
316 	else
317 		*res = '\0';
318 	editedhost[sizeof editedhost - 1] = '\0';
319 }
320 
321 struct speedtab {
322 	int	speed;
323 	int	uxname;
324 } speedtab[] = {
325 	{ 50,	  B50 },
326 	{ 75,	  B75 },
327 	{ 110,	 B110 },
328 	{ 134,	 B134 },
329 	{ 150,	 B150 },
330 	{ 200,	 B200 },
331 	{ 300,	 B300 },
332 	{ 600,	 B600 },
333 	{ 1200,	B1200 },
334 	{ 1800,	B1800 },
335 	{ 2400,	B2400 },
336 	{ 4800,	B4800 },
337 	{ 9600,	B9600 },
338 	{ 19200, EXTA },
339 	{ 19,	 EXTA },	/* for people who say 19.2K */
340 	{ 38400, EXTB },
341 	{ 38,	 EXTB },
342 	{ 7200,	 EXTB },	/* alternative */
343 	{ 0 }
344 };
345 
346 int
347 speed(val)
348 	int val;
349 {
350 	register struct speedtab *sp;
351 
352 	if (val <= 15)
353 		return (val);
354 
355 	for (sp = speedtab; sp->speed; sp++)
356 		if (sp->speed == val)
357 			return (sp->uxname);
358 
359 	return (B300);		/* default in impossible cases */
360 }
361 
362 void
363 makeenv(env)
364 	char *env[];
365 {
366 	static char termbuf[128] = "TERM=";
367 	register char *p, *q;
368 	register char **ep;
369 
370 	ep = env;
371 	if (TT && *TT) {
372 		strcat(termbuf, TT);
373 		*ep++ = termbuf;
374 	}
375 	if (p = EV) {
376 		q = p;
377 		while (q = strchr(q, ',')) {
378 			*q++ = '\0';
379 			*ep++ = p;
380 			p = q;
381 		}
382 		if (*p)
383 			*ep++ = p;
384 	}
385 	*ep = (char *)0;
386 }
387 
388 /*
389  * This speed select mechanism is written for the Develcon DATASWITCH.
390  * The Develcon sends a string of the form "B{speed}\n" at a predefined
391  * baud rate. This string indicates the user's actual speed.
392  * The routine below returns the terminal type mapped from derived speed.
393  */
394 struct	portselect {
395 	char	*ps_baud;
396 	char	*ps_type;
397 } portspeeds[] = {
398 	{ "B110",	"std.110" },
399 	{ "B134",	"std.134" },
400 	{ "B150",	"std.150" },
401 	{ "B300",	"std.300" },
402 	{ "B600",	"std.600" },
403 	{ "B1200",	"std.1200" },
404 	{ "B2400",	"std.2400" },
405 	{ "B4800",	"std.4800" },
406 	{ "B9600",	"std.9600" },
407 	{ "B19200",	"std.19200" },
408 	{ 0 }
409 };
410 
411 char *
412 portselector()
413 {
414 	char c, baud[20], *type = "default";
415 	register struct portselect *ps;
416 	int len;
417 
418 	alarm(5*60);
419 	for (len = 0; len < sizeof (baud) - 1; len++) {
420 		if (read(STDIN_FILENO, &c, 1) <= 0)
421 			break;
422 		c &= 0177;
423 		if (c == '\n' || c == '\r')
424 			break;
425 		if (c == 'B')
426 			len = 0;	/* in case of leading garbage */
427 		baud[len] = c;
428 	}
429 	baud[len] = '\0';
430 	for (ps = portspeeds; ps->ps_baud; ps++)
431 		if (strcmp(ps->ps_baud, baud) == 0) {
432 			type = ps->ps_type;
433 			break;
434 		}
435 	sleep(2);	/* wait for connection to complete */
436 	return (type);
437 }
438 
439 /*
440  * This auto-baud speed select mechanism is written for the Micom 600
441  * portselector. Selection is done by looking at how the character '\r'
442  * is garbled at the different speeds.
443  */
444 #include <sys/time.h>
445 
446 char *
447 autobaud()
448 {
449 	int rfds;
450 	struct timeval timeout;
451 	char c, *type = "9600-baud";
452 	int null = 0;
453 
454 	ioctl(0, TIOCFLUSH, &null);
455 	rfds = 1 << 0;
456 	timeout.tv_sec = 5;
457 	timeout.tv_usec = 0;
458 	if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
459 	    (fd_set *)NULL, &timeout) <= 0)
460 		return (type);
461 	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
462 		return (type);
463 	timeout.tv_sec = 0;
464 	timeout.tv_usec = 20;
465 	(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
466 	    (fd_set *)NULL, &timeout);
467 	ioctl(0, TIOCFLUSH, &null);
468 	switch (c & 0377) {
469 
470 	case 0200:		/* 300-baud */
471 		type = "300-baud";
472 		break;
473 
474 	case 0346:		/* 1200-baud */
475 		type = "1200-baud";
476 		break;
477 
478 	case  015:		/* 2400-baud */
479 	case 0215:
480 		type = "2400-baud";
481 		break;
482 
483 	default:		/* 4800-baud */
484 		type = "4800-baud";
485 		break;
486 
487 	case 0377:		/* 9600-baud */
488 		type = "9600-baud";
489 		break;
490 	}
491 	return (type);
492 }
493