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