subr.c revision 1592
1239922Sgonzo/* 2239922Sgonzo * Copyright (c) 1983, 1993 3239922Sgonzo * The Regents of the University of California. All rights reserved. 4239922Sgonzo * 5239922Sgonzo * Redistribution and use in source and binary forms, with or without 6239922Sgonzo * modification, are permitted provided that the following conditions 7239922Sgonzo * are met: 8239922Sgonzo * 1. Redistributions of source code must retain the above copyright 9239922Sgonzo * notice, this list of conditions and the following disclaimer. 10239922Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 11239922Sgonzo * notice, this list of conditions and the following disclaimer in the 12239922Sgonzo * documentation and/or other materials provided with the distribution. 13239922Sgonzo * 3. All advertising materials mentioning features or use of this software 14239922Sgonzo * must display the following acknowledgement: 15239922Sgonzo * This product includes software developed by the University of 16239922Sgonzo * California, Berkeley and its contributors. 17239922Sgonzo * 4. Neither the name of the University nor the names of its contributors 18239922Sgonzo * may be used to endorse or promote products derived from this software 19239922Sgonzo * without specific prior written permission. 20239922Sgonzo * 21239922Sgonzo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22239922Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23239922Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24239922Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25239922Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26239922Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27239922Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28239922Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29239922Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30239922Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31239922Sgonzo * SUCH DAMAGE. 32239922Sgonzo */ 33239922Sgonzo 34239922Sgonzo#ifndef lint 35239922Sgonzostatic char sccsid[] = "@(#)subr.c 8.1 (Berkeley) 6/4/93"; 36239922Sgonzo#endif /* not lint */ 37239922Sgonzo 38239922Sgonzo/* 39239922Sgonzo * Melbourne getty. 40239922Sgonzo */ 41239922Sgonzo#define USE_OLD_TTY 42239922Sgonzo#include <stdlib.h> 43239922Sgonzo#include <sgtty.h> 44239922Sgonzo#include <string.h> 45239922Sgonzo#include <unistd.h> 46239922Sgonzo 47239922Sgonzo#include "gettytab.h" 48239922Sgonzo#include "extern.h" 49239922Sgonzo#include "pathnames.h" 50239922Sgonzo 51239922Sgonzoextern struct sgttyb tmode; 52239922Sgonzoextern struct tchars tc; 53239922Sgonzoextern struct ltchars ltc; 54239922Sgonzo 55239922Sgonzo/* 56239922Sgonzo * Get a table entry. 57239922Sgonzo */ 58239922Sgonzovoid 59239922Sgonzogettable(name, buf) 60239922Sgonzo char *name, *buf; 61239922Sgonzo{ 62239922Sgonzo register struct gettystrs *sp; 63239922Sgonzo register struct gettynums *np; 64239922Sgonzo register struct gettyflags *fp; 65239922Sgonzo long n; 66239922Sgonzo char *dba[2]; 67239922Sgonzo dba[0] = _PATH_GETTYTAB; 68239922Sgonzo dba[1] = 0; 69239922Sgonzo 70239922Sgonzo if (cgetent(&buf, dba, name) != 0) 71243423Sgonzo return; 72243423Sgonzo 73243423Sgonzo for (sp = gettystrs; sp->field; sp++) 74243423Sgonzo cgetstr(buf, sp->field, &sp->value); 75243423Sgonzo for (np = gettynums; np->field; np++) { 76243423Sgonzo if (cgetnum(buf, np->field, &n) == -1) 77243423Sgonzo np->set = 0; 78243423Sgonzo else { 79243423Sgonzo np->set = 1; 80243423Sgonzo np->value = n; 81243423Sgonzo } 82243423Sgonzo } 83243423Sgonzo for (fp = gettyflags; fp->field; fp++) { 84243423Sgonzo if (cgetcap(buf, fp->field, ':') == NULL) 85243423Sgonzo fp->set = 0; 86243423Sgonzo else { 87243423Sgonzo fp->set = 1; 88243423Sgonzo fp->value = 1 ^ fp->invrt; 89243423Sgonzo } 90243423Sgonzo } 91243423Sgonzo#ifdef DEBUG 92243423Sgonzo printf("name=\"%s\", buf=\"%s\"\n", name, buf); 93243423Sgonzo for (sp = gettystrs; sp->field; sp++) 94243423Sgonzo printf("cgetstr: %s=%s\n", sp->field, sp->value); 95243423Sgonzo for (np = gettynums; np->field; np++) 96243423Sgonzo printf("cgetnum: %s=%d\n", np->field, np->value); 97239922Sgonzo for (fp = gettyflags; fp->field; fp++) 98239922Sgonzo printf("cgetflags: %s='%c' set='%c'\n", fp->field, 99243423Sgonzo fp->value + '0', fp->set + '0'); 100239922Sgonzo exit(1); 101239922Sgonzo#endif /* DEBUG */ 102239922Sgonzo} 103239922Sgonzo 104239922Sgonzovoid 105239922Sgonzogendefaults() 106239922Sgonzo{ 107239922Sgonzo register struct gettystrs *sp; 108239922Sgonzo register struct gettynums *np; 109239922Sgonzo register struct gettyflags *fp; 110239922Sgonzo 111239922Sgonzo for (sp = gettystrs; sp->field; sp++) 112239922Sgonzo if (sp->value) 113239922Sgonzo sp->defalt = sp->value; 114239922Sgonzo for (np = gettynums; np->field; np++) 115239922Sgonzo if (np->set) 116239922Sgonzo np->defalt = np->value; 117239922Sgonzo for (fp = gettyflags; fp->field; fp++) 118239922Sgonzo if (fp->set) 119239922Sgonzo fp->defalt = fp->value; 120239922Sgonzo else 121239922Sgonzo fp->defalt = fp->invrt; 122239922Sgonzo} 123239922Sgonzo 124239922Sgonzovoid 125239922Sgonzosetdefaults() 126239922Sgonzo{ 127239922Sgonzo register struct gettystrs *sp; 128239922Sgonzo register struct gettynums *np; 129239922Sgonzo register struct gettyflags *fp; 130239922Sgonzo 131239922Sgonzo for (sp = gettystrs; sp->field; sp++) 132239922Sgonzo if (!sp->value) 133239922Sgonzo sp->value = sp->defalt; 134239922Sgonzo for (np = gettynums; np->field; np++) 135239922Sgonzo if (!np->set) 136239922Sgonzo np->value = np->defalt; 137243423Sgonzo for (fp = gettyflags; fp->field; fp++) 138239922Sgonzo if (!fp->set) 139239922Sgonzo fp->value = fp->defalt; 140239922Sgonzo} 141239922Sgonzo 142239922Sgonzostatic char ** 143239922Sgonzocharnames[] = { 144239922Sgonzo &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK, 145239922Sgonzo &SU, &DS, &RP, &FL, &WE, &LN, 0 146239922Sgonzo}; 147239922Sgonzo 148239922Sgonzostatic char * 149239922Sgonzocharvars[] = { 150239922Sgonzo &tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc, 151239922Sgonzo &tc.t_quitc, &tc.t_startc, &tc.t_stopc, 152239922Sgonzo &tc.t_eofc, &tc.t_brkc, <c.t_suspc, 153239922Sgonzo <c.t_dsuspc, <c.t_rprntc, <c.t_flushc, 154239922Sgonzo <c.t_werasc, <c.t_lnextc, 0 155239922Sgonzo}; 156239922Sgonzo 157243423Sgonzovoid 158243423Sgonzosetchars() 159239922Sgonzo{ 160239922Sgonzo register int i; 161239922Sgonzo register char *p; 162239922Sgonzo 163239922Sgonzo for (i = 0; charnames[i]; i++) { 164239922Sgonzo p = *charnames[i]; 165239922Sgonzo if (p && *p) 166239922Sgonzo *charvars[i] = *p; 167243423Sgonzo else 168243423Sgonzo *charvars[i] = '\377'; 169239922Sgonzo } 170243423Sgonzo} 171243423Sgonzo 172243423Sgonzolong 173243423Sgonzosetflags(n) 174243423Sgonzo int n; 175243423Sgonzo{ 176243423Sgonzo register long f; 177243423Sgonzo 178243423Sgonzo switch (n) { 179243423Sgonzo case 0: 180243423Sgonzo if (F0set) 181243423Sgonzo return(F0); 182243423Sgonzo break; 183243423Sgonzo case 1: 184243423Sgonzo if (F1set) 185243423Sgonzo return(F1); 186243423Sgonzo break; 187243423Sgonzo default: 188243423Sgonzo if (F2set) 189243423Sgonzo return(F2); 190243423Sgonzo break; 191239922Sgonzo } 192239922Sgonzo 193239922Sgonzo f = 0; 194239922Sgonzo 195239922Sgonzo if (AP) 196239922Sgonzo f |= ANYP; 197239922Sgonzo else if (OP) 198239922Sgonzo f |= ODDP; 199239922Sgonzo else if (EP) 200239922Sgonzo f |= EVENP; 201239922Sgonzo 202239922Sgonzo if (UC) 203239922Sgonzo f |= LCASE; 204239922Sgonzo 205239922Sgonzo if (NL) 206243423Sgonzo f |= CRMOD; 207239922Sgonzo 208239922Sgonzo f |= delaybits(); 209239922Sgonzo 210239922Sgonzo if (n == 1) { /* read mode flags */ 211239922Sgonzo if (RW) 212239922Sgonzo f |= RAW; 213239922Sgonzo else 214239922Sgonzo f |= CBREAK; 215239922Sgonzo return (f); 216239922Sgonzo } 217239922Sgonzo 218243423Sgonzo if (!HT) 219243423Sgonzo f |= XTABS; 220243423Sgonzo 221243423Sgonzo if (n == 0) 222243423Sgonzo return (f); 223243423Sgonzo 224243423Sgonzo if (CB) 225243423Sgonzo f |= CRTBS; 226239922Sgonzo 227243423Sgonzo if (CE) 228239922Sgonzo f |= CRTERA; 229243423Sgonzo 230243423Sgonzo if (CK) 231239922Sgonzo f |= CRTKIL; 232239922Sgonzo 233239922Sgonzo if (PE) 234239922Sgonzo f |= PRTERA; 235239922Sgonzo 236239922Sgonzo if (EC) 237239922Sgonzo f |= ECHO; 238243423Sgonzo 239239922Sgonzo if (XC) 240239922Sgonzo f |= CTLECH; 241239922Sgonzo 242239922Sgonzo if (DX) 243239922Sgonzo f |= DECCTQ; 244239922Sgonzo 245239922Sgonzo return (f); 246239922Sgonzo} 247239922Sgonzo 248239922Sgonzostruct delayval { 249239922Sgonzo unsigned delay; /* delay in ms */ 250243423Sgonzo int bits; 251239922Sgonzo}; 252239922Sgonzo 253239922Sgonzo/* 254239922Sgonzo * below are random guesses, I can't be bothered checking 255239922Sgonzo */ 256239922Sgonzo 257239922Sgonzostruct delayval crdelay[] = { 258239922Sgonzo { 1, CR1 }, 259239922Sgonzo { 2, CR2 }, 260239922Sgonzo { 3, CR3 }, 261239922Sgonzo { 83, CR1 }, 262239922Sgonzo { 166, CR2 }, 263239922Sgonzo { 0, CR3 }, 264239922Sgonzo}; 265239922Sgonzo 266239922Sgonzostruct delayval nldelay[] = { 267239922Sgonzo { 1, NL1 }, /* special, calculated */ 268239922Sgonzo { 2, NL2 }, 269239922Sgonzo { 3, NL3 }, 270239922Sgonzo { 100, NL2 }, 271239922Sgonzo { 0, NL3 }, 272239922Sgonzo}; 273239922Sgonzo 274239922Sgonzostruct delayval bsdelay[] = { 275239922Sgonzo { 1, BS1 }, 276239922Sgonzo { 0, 0 }, 277239922Sgonzo}; 278239922Sgonzo 279239922Sgonzostruct delayval ffdelay[] = { 280239922Sgonzo { 1, FF1 }, 281239922Sgonzo { 1750, FF1 }, 282239922Sgonzo { 0, FF1 }, 283239922Sgonzo}; 284239922Sgonzo 285239922Sgonzostruct delayval tbdelay[] = { 286239922Sgonzo { 1, TAB1 }, 287239922Sgonzo { 2, TAB2 }, 288239922Sgonzo { 3, XTABS }, /* this is expand tabs */ 289239922Sgonzo { 100, TAB1 }, 290239922Sgonzo { 0, TAB2 }, 291239922Sgonzo}; 292239922Sgonzo 293239922Sgonzoint 294239922Sgonzodelaybits() 295239922Sgonzo{ 296239922Sgonzo register int f; 297239922Sgonzo 298239922Sgonzo f = adelay(CD, crdelay); 299239922Sgonzo f |= adelay(ND, nldelay); 300239922Sgonzo f |= adelay(FD, ffdelay); 301239922Sgonzo f |= adelay(TD, tbdelay); 302239922Sgonzo f |= adelay(BD, bsdelay); 303239922Sgonzo return (f); 304239922Sgonzo} 305239922Sgonzo 306239922Sgonzoint 307239922Sgonzoadelay(ms, dp) 308239922Sgonzo register ms; 309239922Sgonzo register struct delayval *dp; 310239922Sgonzo{ 311239922Sgonzo if (ms == 0) 312239922Sgonzo return (0); 313239922Sgonzo while (dp->delay && ms > dp->delay) 314239922Sgonzo dp++; 315239922Sgonzo return (dp->bits); 316239922Sgonzo} 317239922Sgonzo 318239922Sgonzochar editedhost[32]; 319239922Sgonzo 320239922Sgonzovoid 321239922Sgonzoedithost(pat) 322239922Sgonzo register char *pat; 323239922Sgonzo{ 324239922Sgonzo register char *host = HN; 325239922Sgonzo register char *res = editedhost; 326239922Sgonzo 327239922Sgonzo if (!pat) 328239922Sgonzo pat = ""; 329239922Sgonzo while (*pat) { 330239922Sgonzo switch (*pat) { 331239922Sgonzo 332239922Sgonzo case '#': 333239922Sgonzo if (*host) 334239922Sgonzo host++; 335239922Sgonzo break; 336239922Sgonzo 337239922Sgonzo case '@': 338239922Sgonzo if (*host) 339239922Sgonzo *res++ = *host++; 340239922Sgonzo break; 341239922Sgonzo 342239922Sgonzo default: 343239922Sgonzo *res++ = *pat; 344239922Sgonzo break; 345239922Sgonzo 346239922Sgonzo } 347239922Sgonzo if (res == &editedhost[sizeof editedhost - 1]) { 348239922Sgonzo *res = '\0'; 349239922Sgonzo return; 350243423Sgonzo } 351239922Sgonzo pat++; 352239922Sgonzo } 353239922Sgonzo if (*host) 354239922Sgonzo strncpy(res, host, sizeof editedhost - (res - editedhost) - 1); 355239922Sgonzo else 356239922Sgonzo *res = '\0'; 357239922Sgonzo editedhost[sizeof editedhost - 1] = '\0'; 358239922Sgonzo} 359239922Sgonzo 360239922Sgonzostruct speedtab { 361239922Sgonzo int speed; 362239922Sgonzo int uxname; 363239922Sgonzo} speedtab[] = { 364239922Sgonzo { 50, B50 }, 365239922Sgonzo { 75, B75 }, 366239922Sgonzo { 110, B110 }, 367239922Sgonzo { 134, B134 }, 368239922Sgonzo { 150, B150 }, 369239922Sgonzo { 200, B200 }, 370239922Sgonzo { 300, B300 }, 371239922Sgonzo { 600, B600 }, 372239922Sgonzo { 1200, B1200 }, 373239922Sgonzo { 1800, B1800 }, 374239922Sgonzo { 2400, B2400 }, 375239922Sgonzo { 4800, B4800 }, 376239922Sgonzo { 9600, B9600 }, 377239922Sgonzo { 19200, EXTA }, 378239922Sgonzo { 19, EXTA }, /* for people who say 19.2K */ 379239922Sgonzo { 38400, EXTB }, 380239922Sgonzo { 38, EXTB }, 381239922Sgonzo { 7200, EXTB }, /* alternative */ 382239922Sgonzo { 0 } 383239922Sgonzo}; 384239922Sgonzo 385239922Sgonzoint 386239922Sgonzospeed(val) 387239922Sgonzo int val; 388239922Sgonzo{ 389239922Sgonzo register struct speedtab *sp; 390239922Sgonzo 391239922Sgonzo if (val <= 15) 392239922Sgonzo return (val); 393239922Sgonzo 394239922Sgonzo for (sp = speedtab; sp->speed; sp++) 395239922Sgonzo if (sp->speed == val) 396239922Sgonzo return (sp->uxname); 397239922Sgonzo 398239922Sgonzo return (B300); /* default in impossible cases */ 399239922Sgonzo} 400239922Sgonzo 401239922Sgonzovoid 402239922Sgonzomakeenv(env) 403239922Sgonzo char *env[]; 404239922Sgonzo{ 405239922Sgonzo static char termbuf[128] = "TERM="; 406239922Sgonzo register char *p, *q; 407239922Sgonzo register char **ep; 408239922Sgonzo 409239922Sgonzo ep = env; 410239922Sgonzo if (TT && *TT) { 411239922Sgonzo strcat(termbuf, TT); 412239922Sgonzo *ep++ = termbuf; 413239922Sgonzo } 414239922Sgonzo if (p = EV) { 415239922Sgonzo q = p; 416239922Sgonzo while (q = strchr(q, ',')) { 417239922Sgonzo *q++ = '\0'; 418239922Sgonzo *ep++ = p; 419239922Sgonzo p = q; 420239922Sgonzo } 421239922Sgonzo if (*p) 422239922Sgonzo *ep++ = p; 423239922Sgonzo } 424239922Sgonzo *ep = (char *)0; 425239922Sgonzo} 426239922Sgonzo 427239922Sgonzo/* 428239922Sgonzo * This speed select mechanism is written for the Develcon DATASWITCH. 429239922Sgonzo * The Develcon sends a string of the form "B{speed}\n" at a predefined 430243423Sgonzo * baud rate. This string indicates the user's actual speed. 431243423Sgonzo * The routine below returns the terminal type mapped from derived speed. 432243423Sgonzo */ 433243423Sgonzostruct portselect { 434243423Sgonzo char *ps_baud; 435243423Sgonzo char *ps_type; 436243423Sgonzo} portspeeds[] = { 437243423Sgonzo { "B110", "std.110" }, 438243423Sgonzo { "B134", "std.134" }, 439243423Sgonzo { "B150", "std.150" }, 440243423Sgonzo { "B300", "std.300" }, 441243423Sgonzo { "B600", "std.600" }, 442243423Sgonzo { "B1200", "std.1200" }, 443243423Sgonzo { "B2400", "std.2400" }, 444243423Sgonzo { "B4800", "std.4800" }, 445243423Sgonzo { "B9600", "std.9600" }, 446239922Sgonzo { "B19200", "std.19200" }, 447239922Sgonzo { 0 } 448239922Sgonzo}; 449243423Sgonzo 450239922Sgonzochar * 451243423Sgonzoportselector() 452243423Sgonzo{ 453243423Sgonzo char c, baud[20], *type = "default"; 454239922Sgonzo register struct portselect *ps; 455243423Sgonzo int len; 456243423Sgonzo 457239922Sgonzo alarm(5*60); 458243423Sgonzo for (len = 0; len < sizeof (baud) - 1; len++) { 459243423Sgonzo if (read(STDIN_FILENO, &c, 1) <= 0) 460239922Sgonzo break; 461243423Sgonzo c &= 0177; 462243423Sgonzo if (c == '\n' || c == '\r') 463243423Sgonzo break; 464243423Sgonzo if (c == 'B') 465243423Sgonzo len = 0; /* in case of leading garbage */ 466243423Sgonzo baud[len] = c; 467243423Sgonzo } 468243423Sgonzo baud[len] = '\0'; 469243423Sgonzo for (ps = portspeeds; ps->ps_baud; ps++) 470243423Sgonzo if (strcmp(ps->ps_baud, baud) == 0) { 471243423Sgonzo type = ps->ps_type; 472239922Sgonzo break; 473243423Sgonzo } 474243423Sgonzo sleep(2); /* wait for connection to complete */ 475243423Sgonzo return (type); 476243423Sgonzo} 477239922Sgonzo 478243423Sgonzo/* 479243423Sgonzo * This auto-baud speed select mechanism is written for the Micom 600 480243423Sgonzo * portselector. Selection is done by looking at how the character '\r' 481243423Sgonzo * is garbled at the different speeds. 482243423Sgonzo */ 483243423Sgonzo#include <sys/time.h> 484243423Sgonzo 485243423Sgonzochar * 486243423Sgonzoautobaud() 487239922Sgonzo{ 488239922Sgonzo int rfds; 489239922Sgonzo struct timeval timeout; 490239922Sgonzo char c, *type = "9600-baud"; 491239922Sgonzo int null = 0; 492239922Sgonzo 493239922Sgonzo ioctl(0, TIOCFLUSH, &null); 494239922Sgonzo rfds = 1 << 0; 495239922Sgonzo timeout.tv_sec = 5; 496239922Sgonzo timeout.tv_usec = 0; 497239922Sgonzo if (select(32, (fd_set *)&rfds, (fd_set *)NULL, 498239922Sgonzo (fd_set *)NULL, &timeout) <= 0) 499239922Sgonzo return (type); 500239922Sgonzo if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char)) 501239922Sgonzo return (type); 502239922Sgonzo timeout.tv_sec = 0; 503239922Sgonzo timeout.tv_usec = 20; 504239922Sgonzo (void) select(32, (fd_set *)NULL, (fd_set *)NULL, 505239922Sgonzo (fd_set *)NULL, &timeout); 506239922Sgonzo ioctl(0, TIOCFLUSH, &null); 507239922Sgonzo switch (c & 0377) { 508239922Sgonzo 509239922Sgonzo case 0200: /* 300-baud */ 510239922Sgonzo type = "300-baud"; 511243423Sgonzo break; 512239922Sgonzo 513239922Sgonzo case 0346: /* 1200-baud */ 514239922Sgonzo type = "1200-baud"; 515239922Sgonzo break; 516239922Sgonzo 517239922Sgonzo case 015: /* 2400-baud */ 518239922Sgonzo case 0215: 519239922Sgonzo type = "2400-baud"; 520239922Sgonzo break; 521239922Sgonzo 522239922Sgonzo default: /* 4800-baud */ 523239922Sgonzo type = "4800-baud"; 524239922Sgonzo break; 525239922Sgonzo 526243423Sgonzo case 0377: /* 9600-baud */ 527239922Sgonzo type = "9600-baud"; 528239922Sgonzo break; 529239922Sgonzo } 530239922Sgonzo return (type); 531239922Sgonzo} 532239922Sgonzo