Home | History | Annotate | Line # | Download | only in getty
subr.c revision 1.7
      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.7 1994/04/28 22:12:31 pk Exp $";
     37 #endif /* not lint */
     38 
     39 /*
     40  * Melbourne getty.
     41  */
     42 #define COMPAT_43
     43 #include <stdlib.h>
     44 #include <unistd.h>
     45 #include <string.h>
     46 #include <termios.h>
     47 #include <sys/ioctl.h>
     48 
     49 #include "gettytab.h"
     50 #include "pathnames.h"
     51 
     52 extern	struct termios tmode;
     53 
     54 static void	compatflags __P((long));
     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.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
    148 	&tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
    149 	&tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
    150 	&tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
    151 	&tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 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 void
    169 setflags(n)
    170 {
    171 	register tcflag_t iflag, oflag, cflag, lflag;
    172 
    173 #ifdef COMPAT_43
    174 	switch (n) {
    175 	case 0:
    176 		if (F0set) {
    177 			compatflags(F0);
    178 			return;
    179 		}
    180 		break;
    181 	case 1:
    182 		if (F1set) {
    183 			compatflags(F1);
    184 			return;
    185 		}
    186 		break;
    187 	default:
    188 		if (F2set) {
    189 			compatflags(F2);
    190 			return;
    191 		}
    192 		break;
    193 	}
    194 #endif
    195 
    196 	switch (n) {
    197 	case 0:
    198 		if (C0set && I0set && L0set && O0set) {
    199 			tmode.c_cflag = C0;
    200 			tmode.c_iflag = I0;
    201 			tmode.c_lflag = L0;
    202 			tmode.c_oflag = O0;
    203 			return;
    204 		}
    205 		break;
    206 	case 1:
    207 		if (C1set && I1set && L1set && O1set) {
    208 			tmode.c_cflag = C1;
    209 			tmode.c_iflag = I1;
    210 			tmode.c_lflag = L1;
    211 			tmode.c_oflag = O1;
    212 			return;
    213 		}
    214 		break;
    215 	default:
    216 		if (C2set && I2set && L2set && O2set) {
    217 			tmode.c_cflag = C2;
    218 			tmode.c_iflag = I2;
    219 			tmode.c_lflag = L2;
    220 			tmode.c_oflag = O2;
    221 			return;
    222 		}
    223 		break;
    224 	}
    225 
    226 	iflag = (BRKINT|ICRNL|IMAXBEL|IXON|IXANY);
    227 	oflag = (OPOST|ONLCR|OXTABS);
    228 	cflag = (CREAD);
    229 	lflag = (ICANON|ISIG|IEXTEN);
    230 
    231 	if (NP) {
    232 		iflag |= IGNPAR;
    233 		cflag |= CS8;
    234 	} else if (AP) {
    235 		iflag |= IGNPAR|ISTRIP;
    236 		cflag |= CS7;
    237 	} else if (OP) {
    238 		iflag |= INPCK|ISTRIP;
    239 		cflag |= PARENB|PARODD|CS7;
    240 	} else if (EP) {
    241 		iflag |= INPCK|ISTRIP;
    242 		cflag |= PARENB|CS7;
    243 	}
    244 
    245 #if 0
    246 	if (UC)
    247 		f |= LCASE;
    248 #endif
    249 
    250 	if (HC)
    251 		cflag |= HUPCL;
    252 
    253 	if (NL) {
    254 		iflag |= ICRNL;
    255 		oflag |= ONLCR;
    256 	}
    257 
    258 #ifdef XXX_DELAY
    259 	f |= delaybits();
    260 #endif
    261 
    262 	if (n == 1) {		/* read mode flags */
    263 		if (RW) {
    264 			iflag = 0;
    265 			oflag = 0;
    266 			cflag = CREAD|CS8;
    267 			lflag = 0;
    268 		} else {
    269 			lflag &= ~ICANON;
    270 		}
    271 		goto out;
    272 	}
    273 
    274 	if (!HT)
    275 		oflag |= OXTABS;
    276 
    277 	if (n == 0)
    278 		goto out;
    279 
    280 #if 0
    281 	if (CB)
    282 		f |= CRTBS;
    283 #endif
    284 
    285 	if (CE)
    286 		lflag |= ECHOE;
    287 
    288 	if (CK)
    289 		lflag |= ECHOKE;
    290 
    291 	if (PE)
    292 		lflag |= ECHOPRT;
    293 
    294 	if (EC)
    295 		lflag |= ECHO;
    296 
    297 	if (XC)
    298 		lflag |= ECHOCTL;
    299 
    300 	if (DX)
    301 		lflag |= IXANY;
    302 
    303 	if (MB)
    304 		cflag |= MDMBUF;
    305 
    306 out:
    307 	tmode.c_iflag = iflag;
    308 	tmode.c_oflag = oflag;
    309 	tmode.c_cflag = cflag;
    310 	tmode.c_lflag = lflag;
    311 }
    312 
    313 #ifdef COMPAT_43
    314 /*
    315  * Old TTY => termios, snatched from <sys/kern/tty_compat.c>
    316  */
    317 void
    318 compatflags(flags)
    319 register long flags;
    320 {
    321 	register tcflag_t iflag, oflag, cflag, lflag;
    322 
    323 	iflag = (BRKINT|ICRNL|IMAXBEL|IXON|IXANY);
    324 	oflag = (OPOST|ONLCR|OXTABS);
    325 	cflag = (CREAD);
    326 	lflag = (ICANON|ISIG|IEXTEN);
    327 
    328 	if (flags & RAW) {
    329 		iflag &= IXOFF|IXANY;
    330 		oflag &= ~OPOST;
    331 		lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
    332 	} else {
    333 		iflag |= BRKINT|IXON|IMAXBEL;
    334 		oflag |= OPOST;
    335 		lflag |= ISIG|IEXTEN|ECHOCTL;	/* XXX was echoctl on ? */
    336 		if (flags & XTABS)
    337 			oflag |= OXTABS;
    338 		else
    339 			oflag &= ~OXTABS;
    340 		if (flags & CBREAK)
    341 			lflag &= ~ICANON;
    342 		else
    343 			lflag |= ICANON;
    344 		if (flags&CRMOD) {
    345 			iflag |= ICRNL;
    346 			oflag |= ONLCR;
    347 		} else {
    348 			iflag &= ~ICRNL;
    349 			oflag &= ~ONLCR;
    350 		}
    351 	}
    352 	if (flags&ECHO)
    353 		lflag |= ECHO;
    354 	else
    355 		lflag &= ~ECHO;
    356 
    357 	if (flags&(RAW|LITOUT|PASS8)) {
    358 		cflag &= ~(CSIZE|PARENB);
    359 		cflag |= CS8;
    360 		if ((flags&(RAW|PASS8)) == 0)
    361 			iflag |= ISTRIP;
    362 		else
    363 			iflag &= ~ISTRIP;
    364 	} else {
    365 		cflag &= ~CSIZE;
    366 		cflag |= CS7|PARENB;
    367 		iflag |= ISTRIP;
    368 	}
    369 	if ((flags&(EVENP|ODDP)) == EVENP) {
    370 		iflag |= INPCK;
    371 		cflag &= ~PARODD;
    372 	} else if ((flags&(EVENP|ODDP)) == ODDP) {
    373 		iflag |= INPCK;
    374 		cflag |= PARODD;
    375 	} else
    376 		iflag &= ~INPCK;
    377 	if (flags&LITOUT)
    378 		oflag &= ~OPOST;	/* move earlier ? */
    379 	if (flags&TANDEM)
    380 		iflag |= IXOFF;
    381 	else
    382 		iflag &= ~IXOFF;
    383 
    384 	if (flags&CRTERA)
    385 		lflag |= ECHOE;
    386 	else
    387 		lflag &= ~ECHOE;
    388 	if (flags&CRTKIL)
    389 		lflag |= ECHOKE;
    390 	else
    391 		lflag &= ~ECHOKE;
    392 	if (flags&PRTERA)
    393 		lflag |= ECHOPRT;
    394 	else
    395 		lflag &= ~ECHOPRT;
    396 	if (flags&CTLECH)
    397 		lflag |= ECHOCTL;
    398 	else
    399 		lflag &= ~ECHOCTL;
    400 	if ((flags&DECCTQ) == 0)
    401 		lflag |= IXANY;
    402 	else
    403 		lflag &= ~IXANY;
    404 	if (flags & MDMBUF)
    405 		cflag |= MDMBUF;
    406 	else
    407 		cflag &= ~MDMBUF;
    408 	if (flags&NOHANG)
    409 		cflag &= ~HUPCL;
    410 	else
    411 		cflag |= HUPCL;
    412 	lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
    413 	lflag |= flags&(TOSTOP|FLUSHO|PENDIN|NOFLSH);
    414 	if (flags&(LITOUT|PASS8)) {
    415 		iflag &= ~ISTRIP;
    416 		cflag &= ~(CSIZE|PARENB);
    417 		cflag |= CS8;
    418 		if (flags&LITOUT)
    419 			oflag &= ~OPOST;
    420 		if ((flags&(PASS8|RAW)) == 0)
    421   			iflag |= ISTRIP;
    422 	} else if ((flags&RAW) == 0) {
    423 		cflag &= ~CSIZE;
    424 		cflag |= CS7|PARENB;
    425 		oflag |= OPOST;
    426 	}
    427 
    428 	tmode.c_iflag = iflag;
    429 	tmode.c_oflag = oflag;
    430 	tmode.c_cflag = cflag;
    431 	tmode.c_lflag = lflag;
    432 }
    433 #endif
    434 
    435 #ifdef XXX_DELAY
    436 struct delayval {
    437 	unsigned	delay;		/* delay in ms */
    438 	int		bits;
    439 };
    440 
    441 /*
    442  * below are random guesses, I can't be bothered checking
    443  */
    444 
    445 struct delayval	crdelay[] = {
    446 	1,		CR1,
    447 	2,		CR2,
    448 	3,		CR3,
    449 	83,		CR1,
    450 	166,		CR2,
    451 	0,		CR3,
    452 };
    453 
    454 struct delayval nldelay[] = {
    455 	1,		NL1,		/* special, calculated */
    456 	2,		NL2,
    457 	3,		NL3,
    458 	100,		NL2,
    459 	0,		NL3,
    460 };
    461 
    462 struct delayval	bsdelay[] = {
    463 	1,		BS1,
    464 	0,		0,
    465 };
    466 
    467 struct delayval	ffdelay[] = {
    468 	1,		FF1,
    469 	1750,		FF1,
    470 	0,		FF1,
    471 };
    472 
    473 struct delayval	tbdelay[] = {
    474 	1,		TAB1,
    475 	2,		TAB2,
    476 	3,		XTABS,		/* this is expand tabs */
    477 	100,		TAB1,
    478 	0,		TAB2,
    479 };
    480 
    481 delaybits()
    482 {
    483 	register f;
    484 
    485 	f  = adelay(CD, crdelay);
    486 	f |= adelay(ND, nldelay);
    487 	f |= adelay(FD, ffdelay);
    488 	f |= adelay(TD, tbdelay);
    489 	f |= adelay(BD, bsdelay);
    490 	return (f);
    491 }
    492 
    493 adelay(ms, dp)
    494 	register ms;
    495 	register struct delayval *dp;
    496 {
    497 	if (ms == 0)
    498 		return (0);
    499 	while (dp->delay && ms > dp->delay)
    500 		dp++;
    501 	return (dp->bits);
    502 }
    503 #endif
    504 
    505 char	editedhost[32];
    506 
    507 edithost(pat)
    508 	register char *pat;
    509 {
    510 	register char *host = HN;
    511 	register char *res = editedhost;
    512 
    513 	if (!pat)
    514 		pat = "";
    515 	while (*pat) {
    516 		switch (*pat) {
    517 
    518 		case '#':
    519 			if (*host)
    520 				host++;
    521 			break;
    522 
    523 		case '@':
    524 			if (*host)
    525 				*res++ = *host++;
    526 			break;
    527 
    528 		default:
    529 			*res++ = *pat;
    530 			break;
    531 
    532 		}
    533 		if (res == &editedhost[sizeof editedhost - 1]) {
    534 			*res = '\0';
    535 			return;
    536 		}
    537 		pat++;
    538 	}
    539 	if (*host)
    540 		strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
    541 	else
    542 		*res = '\0';
    543 	editedhost[sizeof editedhost - 1] = '\0';
    544 }
    545 
    546 struct speedtab {
    547 	int	speed;
    548 	int	uxname;
    549 } speedtab[] = {
    550 	50,	B50,
    551 	75,	B75,
    552 	110,	B110,
    553 	134,	B134,
    554 	150,	B150,
    555 	200,	B200,
    556 	300,	B300,
    557 	600,	B600,
    558 	1200,	B1200,
    559 	1800,	B1800,
    560 	2400,	B2400,
    561 	4800,	B4800,
    562 	9600,	B9600,
    563 	19200,	EXTA,
    564 	19,	EXTA,		/* for people who say 19.2K */
    565 	38400,	EXTB,
    566 	38,	EXTB,
    567 	7200,	EXTB,		/* alternative */
    568 	57600,	B57600,
    569 	115200,	B115200,
    570 	0
    571 };
    572 
    573 speed(val)
    574 {
    575 	register struct speedtab *sp;
    576 
    577 	if (val <= 15)
    578 		return (val);
    579 
    580 	for (sp = speedtab; sp->speed; sp++)
    581 		if (sp->speed == val)
    582 			return (sp->uxname);
    583 
    584 	return (B300);		/* default in impossible cases */
    585 }
    586 
    587 makeenv(env)
    588 	char *env[];
    589 {
    590 	static char termbuf[128] = "TERM=";
    591 	register char *p, *q;
    592 	register char **ep;
    593 	char *index();
    594 
    595 	ep = env;
    596 	if (TT && *TT) {
    597 		strcat(termbuf, TT);
    598 		*ep++ = termbuf;
    599 	}
    600 	if (p = EV) {
    601 		q = p;
    602 		while (q = index(q, ',')) {
    603 			*q++ = '\0';
    604 			*ep++ = p;
    605 			p = q;
    606 		}
    607 		if (*p)
    608 			*ep++ = p;
    609 	}
    610 	*ep = (char *)0;
    611 }
    612 
    613 /*
    614  * This speed select mechanism is written for the Develcon DATASWITCH.
    615  * The Develcon sends a string of the form "B{speed}\n" at a predefined
    616  * baud rate. This string indicates the user's actual speed.
    617  * The routine below returns the terminal type mapped from derived speed.
    618  */
    619 struct	portselect {
    620 	char	*ps_baud;
    621 	char	*ps_type;
    622 } portspeeds[] = {
    623 	{ "B110",	"std.110" },
    624 	{ "B134",	"std.134" },
    625 	{ "B150",	"std.150" },
    626 	{ "B300",	"std.300" },
    627 	{ "B600",	"std.600" },
    628 	{ "B1200",	"std.1200" },
    629 	{ "B2400",	"std.2400" },
    630 	{ "B4800",	"std.4800" },
    631 	{ "B9600",	"std.9600" },
    632 	{ "B19200",	"std.19200" },
    633 	{ 0 }
    634 };
    635 
    636 char *
    637 portselector()
    638 {
    639 	char c, baud[20], *type = "default";
    640 	register struct portselect *ps;
    641 	int len;
    642 
    643 	alarm(5*60);
    644 	for (len = 0; len < sizeof (baud) - 1; len++) {
    645 		if (read(STDIN_FILENO, &c, 1) <= 0)
    646 			break;
    647 		c &= 0177;
    648 		if (c == '\n' || c == '\r')
    649 			break;
    650 		if (c == 'B')
    651 			len = 0;	/* in case of leading garbage */
    652 		baud[len] = c;
    653 	}
    654 	baud[len] = '\0';
    655 	for (ps = portspeeds; ps->ps_baud; ps++)
    656 		if (strcmp(ps->ps_baud, baud) == 0) {
    657 			type = ps->ps_type;
    658 			break;
    659 		}
    660 	sleep(2);	/* wait for connection to complete */
    661 	return (type);
    662 }
    663 
    664 /*
    665  * This auto-baud speed select mechanism is written for the Micom 600
    666  * portselector. Selection is done by looking at how the character '\r'
    667  * is garbled at the different speeds.
    668  */
    669 #include <sys/time.h>
    670 
    671 char *
    672 autobaud()
    673 {
    674 	int rfds;
    675 	struct timeval timeout;
    676 	char c, *type = "9600-baud";
    677 	int null = 0;
    678 
    679 	ioctl(0, TIOCFLUSH, &null);
    680 	rfds = 1 << 0;
    681 	timeout.tv_sec = 5;
    682 	timeout.tv_usec = 0;
    683 	if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
    684 	    (fd_set *)NULL, &timeout) <= 0)
    685 		return (type);
    686 	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
    687 		return (type);
    688 	timeout.tv_sec = 0;
    689 	timeout.tv_usec = 20;
    690 	(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
    691 	    (fd_set *)NULL, &timeout);
    692 	ioctl(0, TIOCFLUSH, &null);
    693 	switch (c & 0377) {
    694 
    695 	case 0200:		/* 300-baud */
    696 		type = "300-baud";
    697 		break;
    698 
    699 	case 0346:		/* 1200-baud */
    700 		type = "1200-baud";
    701 		break;
    702 
    703 	case  015:		/* 2400-baud */
    704 	case 0215:
    705 		type = "2400-baud";
    706 		break;
    707 
    708 	default:		/* 4800-baud */
    709 		type = "4800-baud";
    710 		break;
    711 
    712 	case 0377:		/* 9600-baud */
    713 		type = "9600-baud";
    714 		break;
    715 	}
    716 	return (type);
    717 }
    718