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