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