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