|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)tset.c 1.6 (Berkeley) 8/11/83"; ! 3: #endif ! 4: ! 5: /* ! 6: ** TSET -- set terminal modes ! 7: ** ! 8: ** This program does sophisticated terminal initialization. ! 9: ** I recommend that you include it in your .start_up or .login ! 10: ** file to initialize whatever terminal you are on. ! 11: ** ! 12: ** There are several features: ! 13: ** ! 14: ** A special file or sequence (as controlled by the ttycap file) ! 15: ** is sent to the terminal. ! 16: ** ! 17: ** Mode bits are set on a per-terminal_type basis (much better ! 18: ** than UNIX itself). This allows special delays, automatic ! 19: ** tabs, etc. ! 20: ** ! 21: ** Erase and Kill characters can be set to whatever you want. ! 22: ** Default is to change erase to control-H on a terminal which ! 23: ** can overstrike, and leave it alone on anything else. Kill ! 24: ** is always left alone unless specifically requested. These ! 25: ** characters can be represented as "^X" meaning control-X; ! 26: ** X is any character. ! 27: ** ! 28: ** Terminals which are dialups or plugboard types can be aliased ! 29: ** to whatever type you may have in your home or office. Thus, ! 30: ** if you know that when you dial up you will always be on a ! 31: ** TI 733, you can specify that fact to tset. You can represent ! 32: ** a type as "?type". This will ask you what type you want it ! 33: ** to be -- if you reply with just a newline, it will default ! 34: ** to the type given. ! 35: ** ! 36: ** The htmp file, used by ex, etc., can be updated. ! 37: ** ! 38: ** The current terminal type can be queried. ! 39: ** ! 40: ** Usage: ! 41: ** tset [-] [-EC] [-eC] [-kC] [-s] [-h] [-u] [-r] ! 42: ** [-m [ident] [test baudrate] :type] ! 43: ** [-Q] [-I] [-S] [type] ! 44: ** ! 45: ** In systems with environments, use: ! 46: ** eval `tset -s ...` ! 47: ** Actually, this doesn't work in old csh's. ! 48: ** Instead, use: ! 49: ** tset -s ... > tset.tmp ! 50: ** source tset.tmp ! 51: ** rm tset.tmp ! 52: ** or: ! 53: ** set noglob ! 54: ** set term=(`tset -S ....`) ! 55: ** setenv TERM $term[1] ! 56: ** setenv TERMCAP "$term[2]" ! 57: ** unset term ! 58: ** unset noglob ! 59: ** ! 60: ** Positional Parameters: ! 61: ** type -- the terminal type to force. If this is ! 62: ** specified, initialization is for this ! 63: ** terminal type. ! 64: ** ! 65: ** Flags: ! 66: ** - -- report terminal type. Whatever type is ! 67: ** decided on is reported. If no other flags ! 68: ** are stated, the only affect is to write ! 69: ** the terminal type on the standard output. ! 70: ** -r -- report to user in addition to other flags. ! 71: ** -EC -- set the erase character to C on all terminals ! 72: ** except those which cannot backspace (e.g., ! 73: ** a TTY 33). C defaults to control-H. ! 74: ** -eC -- set the erase character to C on all terminals. ! 75: ** C defaults to control-H. If neither -E or -e ! 76: ** are specified, the erase character is set to ! 77: ** control-H if the terminal can both backspace ! 78: ** and not overstrike (e.g., a CRT). If the erase ! 79: ** character is NULL (zero byte), it will be reset ! 80: ** to '#' if nothing else is specified. ! 81: ** -kC -- set the kill character to C on all terminals. ! 82: ** Default for C is control-X. If not specified, ! 83: ** the kill character is untouched; however, if ! 84: ** not specified and the kill character is NULL ! 85: ** (zero byte), the kill character is set to '@'. ! 86: ** -iC -- reserved for setable interrupt character. ! 87: ** -qC -- reserved for setable quit character. ! 88: ** -m -- map the system identified type to some user ! 89: ** specified type. The mapping can be baud rate ! 90: ** dependent. This replaces the old -d, -p flags. ! 91: ** (-d type -> -m dialup:type) ! 92: ** (-p type -> -m plug:type) ! 93: ** Syntax: -m identifier [test baudrate] :type ! 94: ** where: ``identifier'' is whatever is found in ! 95: ** /etc/ttytype for this port, (abscence of an identifier ! 96: ** matches any identifier); ``test'' may be any combination ! 97: ** of > = < ! @; ``baudrate'' is as with stty(1); ! 98: ** ``type'' is the actual terminal type to use if the ! 99: ** mapping condition is met. Multiple maps are scanned ! 100: ** in order and the first match prevails. ! 101: ** -n -- If the new tty driver from UCB is available, this flag ! 102: ** will activate the new options for erase and kill ! 103: ** processing. This will be different for printers ! 104: ** and crt's. For crts, if the baud rate is < 1200 then ! 105: ** erase and kill don't remove characters from the screen. ! 106: ** -h -- don't read htmp file. Normally the terminal type ! 107: ** is determined by reading the htmp file or the ! 108: ** environment (unless some mapping is specified). ! 109: ** This forces a read of the ttytype file -- useful ! 110: ** when htmp is somehow wrong. (V6 only) ! 111: ** -u -- don't update htmp. It seemed like this should ! 112: ** be put in. Note that htmp is never actually ! 113: ** written if there are no changes, so don't bother ! 114: ** bother using this for efficiency reasons alone. ! 115: ** -s -- output setenv commands for TERM. This can be ! 116: ** used with ! 117: ** `tset -s ...` ! 118: ** and is to be prefered to: ! 119: ** setenv TERM `tset - ...` ! 120: ** because -s sets the TERMCAP variable also. ! 121: ** -S -- Similar to -s but outputs 2 strings suitable for ! 122: ** use in csh .login files as follows: ! 123: ** set noglob ! 124: ** set term=(`tset -S .....`) ! 125: ** setenv TERM $term[1] ! 126: ** setenv TERMCAP "$term[2]" ! 127: ** unset term ! 128: ** unset noglob ! 129: ** -Q -- be quiet. don't output 'Erase set to' etc. ! 130: ** -I -- don't do terminal initialization (is & if ! 131: ** strings). ! 132: ** -v -- On virtual terminal systems, don't set up a ! 133: ** virtual terminal. Otherwise tset will tell ! 134: ** the operating system what kind of terminal you ! 135: ** are on (if it is a known terminal) and fix up ! 136: ** the output of -s to use virtual terminal sequences. ! 137: ** ! 138: ** Files: ! 139: ** /etc/ttytype ! 140: ** contains a terminal id -> terminal type ! 141: ** mapping; used when any user mapping is specified, ! 142: ** or the environment doesn't have TERM set. ! 143: ** /etc/termcap ! 144: ** a terminal_type -> terminal_capabilities ! 145: ** mapping. ! 146: ** ! 147: ** Return Codes: ! 148: ** -1 -- couldn't open ttycap. ! 149: ** 1 -- bad terminal type, or standard output not tty. ! 150: ** 0 -- ok. ! 151: ** ! 152: ** Defined Constants: ! 153: ** DIALUP -- the type code for a dialup port. ! 154: ** PLUGBOARD -- the type code for a plugboard port. ! 155: ** ARPANET -- the type code for an arpanet port. ! 156: ** BACKSPACE -- control-H, the default for -e. ! 157: ** CTRL('X') -- control-X, the default for -k. ! 158: ** OLDERASE -- the system default erase character. ! 159: ** OLDKILL -- the system default kill character. ! 160: ** FILEDES -- the file descriptor to do the operation ! 161: ** on, nominally 1 or 2. ! 162: ** STDOUT -- the standard output file descriptor. ! 163: ** UIDMASK -- the bit pattern to mask with the getuid() ! 164: ** call to get just the user id. ! 165: ** GTTYN -- defines file containing generalized ttynames ! 166: ** and compiles code to look there. ! 167: ** ! 168: ** Requires: ! 169: ** Routines to handle htmp, ttytype, and ttycap. ! 170: ** ! 171: ** Compilation Flags: ! 172: ** OLDFLAGS -- must be defined to compile code for any of ! 173: ** the -d, -p, or -a flags. ! 174: ** OLDDIALUP -- accept the -d flag. ! 175: ** OLDPLUGBOARD -- accept the -p flag. ! 176: ** OLDARPANET -- accept the -a flag. ! 177: ** FULLLOGIN -- if defined, login sets the ttytype from ! 178: ** /etc/ttytype file. ! 179: ** V6 -- if clear, use environments, not htmp. ! 180: ** also use TIOCSETN rather than stty to avoid flushing ! 181: ** GTTYN -- if set, compiles code to look at /etc/ttytype. ! 182: ** UCB_NTTY -- set to handle new tty driver modes. ! 183: ** ! 184: ** Trace Flags: ! 185: ** none ! 186: ** ! 187: ** Diagnostics: ! 188: ** Bad flag ! 189: ** An incorrect option was specified. ! 190: ** Too few args ! 191: ** more command line arguments are required. ! 192: ** Unexpected arg ! 193: ** wrong type of argument was encountered. ! 194: ** Cannot open ... ! 195: ** The specified file could not be openned. ! 196: ** Type ... unknown ! 197: ** An unknown terminal type was specified. ! 198: ** Cannot update htmp ! 199: ** Cannot update htmp file when the standard ! 200: ** output is not a terminal. ! 201: ** Erase set to ... ! 202: ** Telling that the erase character has been ! 203: ** set to the specified character. ! 204: ** Kill set to ... ! 205: ** Ditto for kill ! 206: ** Erase is ... Kill is ... ! 207: ** Tells that the erase/kill characters were ! 208: ** wierd before, but they are being left as-is. ! 209: ** Not a terminal ! 210: ** Set if FILEDES is not a terminal. ! 211: ** ! 212: ** Compilation Instructions: ! 213: ** cc -n -O tset.c -ltermlib ! 214: ** mv a.out tset ! 215: ** chown bin tset ! 216: ** chmod 4755 tset ! 217: ** ! 218: ** where 'bin' should be whoever owns the 'htmp' file. ! 219: ** If 'htmp' is 666, then tset need not be setuid. ! 220: ** ! 221: ** For version 6 the compile command should be: ! 222: ** cc -n -O -I/usr/include/retrofit tset.c -ltermlib -lretro -lS ! 223: ** ! 224: ** Author: ! 225: ** Eric Allman ! 226: ** Electronics Research Labs ! 227: ** U.C. Berkeley ! 228: ** ! 229: ** History: ! 230: ** 1/81 -- Added alias checking for mapping identifiers. ! 231: ** 9/80 -- Added UCB_NTTY mods to setup the new tty driver. ! 232: ** Added the 'reset ...' invocation. ! 233: ** 7/80 -- '-S' added. '-m' mapping added. TERMCAP string ! 234: ** cleaned up. ! 235: ** 3/80 -- Changed to use tputs. Prc & flush added. ! 236: ** 10/79 -- '-s' option extended to handle TERMCAP ! 237: ** variable, set noglob, quote the entry, ! 238: ** and know about the Bourne shell. Terminal ! 239: ** initialization moved to before any information ! 240: ** output so screen clears would not screw you. ! 241: ** '-Q' option added. ! 242: ** 8/79 -- '-' option alone changed to only output ! 243: ** type. '-s' option added. 'VERSION7' ! 244: ** changed to 'V6' for compatibility. ! 245: ** 12/78 -- modified for eventual migration to VAX/UNIX, ! 246: ** so the '-' option is changed to output only ! 247: ** the terminal type to STDOUT instead of ! 248: ** FILEDES. FULLLOGIN flag added. ! 249: ** 9/78 -- '-' and '-p' options added (now fully ! 250: ** compatible with ttytype!), and spaces are ! 251: ** permitted between the -d and the type. ! 252: ** 8/78 -- The sense of -h and -u were reversed, and the ! 253: ** -f flag is dropped -- same effect is available ! 254: ** by just stating the terminal type. ! 255: ** 10/77 -- Written. ! 256: */ ! 257: ! 258: # ifdef USG ! 259: # define index strchr ! 260: # define rindex strrchr ! 261: # define curerase mode.c_cc[VERASE] ! 262: # define curkill mode.c_cc[VKILL] ! 263: # define olderase oldmode.c_cc[VERASE] ! 264: # define oldkill oldmode.c_cc[VKILL] ! 265: # else ! 266: # define curerase mode.sg_erase ! 267: # define curkill mode.sg_kill ! 268: # define olderase oldmode.sg_erase ! 269: # define oldkill oldmode.sg_kill ! 270: # endif ! 271: ! 272: /* ! 273: # define FULLLOGIN 1 ! 274: /*/ ! 275: # ifndef V6 ! 276: # define GTTYN "/etc/ttytype" ! 277: # endif ! 278: ! 279: # ifndef USG ! 280: # include <sgtty.h> ! 281: # else ! 282: # include <termio.h> ! 283: # endif ! 284: ! 285: # include <stdio.h> ! 286: # include <signal.h> ! 287: # ifdef V6 ! 288: # include <retrofit.h> ! 289: # endif ! 290: ! 291: # define YES 1 ! 292: # define NO 0 ! 293: #undef CTRL ! 294: # define CTRL(x) (x ^ 0100) ! 295: # define BACKSPACE (CTRL('H')) ! 296: # define CHK(val, dft) (val<=0 ? dft : val) ! 297: # define isdigit(c) (c >= '0' && c <= '9') ! 298: # define isalnum(c) (c > ' ' && !(index("<@=>!:|\177", c)) ) ! 299: # define OLDERASE '#' ! 300: # define OLDKILL '@' ! 301: ! 302: # define FILEDES 2 /* do gtty/stty on this descriptor */ ! 303: # define STDOUT 1 /* output of -s/-S to this descriptor */ ! 304: ! 305: # ifdef V6 ! 306: # define UIDMASK 0377 ! 307: # else ! 308: # define UIDMASK -1 ! 309: # endif ! 310: ! 311: # ifdef UCB_NTTY ! 312: # define USAGE "usage: tset [-] [-nrsIQS] [-eC] [-kC] [-m [ident][test speed]:type] [type]\n" ! 313: # else ! 314: # define USAGE "usage: tset [-] [-rsIQS] [-eC] [-kC] [-m [ident][test speed]:type] [type]\n" ! 315: # endif ! 316: ! 317: # define OLDFLAGS ! 318: # define DIALUP "dialup" ! 319: # define OLDDIALUP "sd" ! 320: # define PLUGBOARD "plugboard" ! 321: # define OLDPLUGBOARD "sp" ! 322: /*** ! 323: # define ARPANET "arpanet" ! 324: # define OLDARPANET "sa" ! 325: /***/ ! 326: ! 327: # define DEFTYPE "unknown" ! 328: ! 329: ! 330: # ifdef GTTYN ! 331: # define NOTTY 0 ! 332: # else ! 333: # define NOTTY 'x' ! 334: # endif ! 335: ! 336: /* ! 337: * Baud Rate Conditionals ! 338: */ ! 339: # define ANY 0 ! 340: # define GT 1 ! 341: # define EQ 2 ! 342: # define LT 4 ! 343: # define GE (GT|EQ) ! 344: # define LE (LT|EQ) ! 345: # define NE (GT|LT) ! 346: # define ALL (GT|EQ|LT) ! 347: ! 348: ! 349: ! 350: # define NMAP 10 ! 351: ! 352: struct map { ! 353: char *Ident; ! 354: char Test; ! 355: char Speed; ! 356: char *Type; ! 357: } map[NMAP]; ! 358: ! 359: struct map *Map = map; ! 360: ! 361: /* This should be available in an include file */ ! 362: struct ! 363: { ! 364: char *string; ! 365: int speed; ! 366: int baudrate; ! 367: } speeds[] = { ! 368: "0", B0, 0, ! 369: "50", B50, 50, ! 370: "75", B75, 75, ! 371: "110", B110, 110, ! 372: "134", B134, 134, ! 373: "134.5",B134, 134, ! 374: "150", B150, 150, ! 375: "200", B200, 200, ! 376: "300", B300, 300, ! 377: "600", B600, 600, ! 378: "1200", B1200, 1200, ! 379: "1800", B1800, 1800, ! 380: "2400", B2400, 2400, ! 381: "4800", B4800, 4800, ! 382: "9600", B9600, 9600, ! 383: "exta", EXTA, 19200, ! 384: "extb", EXTB, 38400, ! 385: 0, ! 386: }; ! 387: ! 388: #ifdef CBVIRTTERM ! 389: struct vterm { ! 390: char cap[2]; ! 391: char *value; ! 392: } vtab [] = { ! 393: "al", "\033\120", ! 394: "cd", "\033\114", ! 395: "ce", "\033\113", ! 396: "cm", "\033\107%r%.%.", ! 397: "cl", "\033\112", ! 398: "dc", "\033\115", ! 399: "dl", "\033\116", ! 400: "ic", "\033\117", ! 401: "kl", "\033\104", ! 402: "kr", "\033\103", ! 403: "ku", "\033\101", ! 404: "kd", "\033\102", ! 405: "kh", "\033\105", ! 406: "nd", "\033\103", ! 407: "se", "\033\142\004", ! 408: "so", "\033\141\004", ! 409: "ue", "\033\142\001", ! 410: "up", "\033\101", ! 411: "us", "\033\141\001", ! 412: "\0\0", NULL, ! 413: }; ! 414: ! 415: int VirTermNo = -2; ! 416: # endif CBVIRTTERM ! 417: ! 418: char Erase_char; /* new erase character */ ! 419: char Kill_char; /* new kill character */ ! 420: char Specialerase; /* set => Erase_char only on terminals with backspace */ ! 421: ! 422: # ifdef GTTYN ! 423: char *Ttyid = NOTTY; /* terminal identifier */ ! 424: # else ! 425: char Ttyid = NOTTY; /* terminal identifier */ ! 426: # endif ! 427: char *TtyType; /* type of terminal */ ! 428: char *DefType; /* default type if none other computed */ ! 429: char *NewType; /* mapping identifier based on old flags */ ! 430: int Mapped; /* mapping has been specified */ ! 431: int Dash_u; /* don't update htmp */ ! 432: int Dash_h; /* don't read htmp */ ! 433: int DoSetenv; /* output setenv commands */ ! 434: int BeQuiet; /* be quiet */ ! 435: int NoInit; /* don't output initialization string */ ! 436: int IsReset; /* invoked as reset */ ! 437: int Report; /* report current type */ ! 438: int Ureport; /* report to user */ ! 439: int RepOnly; /* report only */ ! 440: int CmndLine; /* output full command lines (-s option) */ ! 441: int Ask; /* ask user for termtype */ ! 442: int DoVirtTerm = YES; /* Set up a virtual terminal */ ! 443: int New = NO; /* use new tty discipline */ ! 444: int HasAM; /* True if terminal has automatic margins */ ! 445: int PadBaud; /* Min rate of padding needed */ ! 446: ! 447: # define CAPBUFSIZ 1024 ! 448: char Capbuf[CAPBUFSIZ]; /* line from /etc/termcap for this TtyType */ ! 449: char *Ttycap; /* termcap line from termcap or environ */ ! 450: ! 451: char Aliasbuf[128]; ! 452: char *Alias[16]; ! 453: ! 454: struct delay ! 455: { ! 456: int d_delay; ! 457: int d_bits; ! 458: }; ! 459: ! 460: # include "tset.delays.h" ! 461: ! 462: # ifndef USG ! 463: struct sgttyb mode; ! 464: struct sgttyb oldmode; ! 465: # else ! 466: struct termio mode; ! 467: struct termio oldmode; ! 468: # endif ! 469: # ifdef CBVIRTTERM ! 470: struct termcb block = {0, 2, 0, 0, 0, 20}; ! 471: # endif CBVIRTTERM ! 472: ! 473: ! 474: main(argc, argv) ! 475: int argc; ! 476: char *argv[]; ! 477: { ! 478: char buf[256]; ! 479: char termbuf[32]; ! 480: auto char *bufp; ! 481: register char *p; ! 482: char *command; ! 483: register int i; ! 484: int j; ! 485: int Break; ! 486: int Not; ! 487: char *nextarg(); ! 488: char *mapped(); ! 489: extern char *rindex(); ! 490: # ifdef V6 ! 491: extern char *hsgettype(); ! 492: # else ! 493: extern char *getenv(); ! 494: # endif ! 495: # ifdef GTTYN ! 496: char *stypeof(); ! 497: extern char *ttyname(); ! 498: extern char *tgetstr(); ! 499: # endif ! 500: char bs_char; ! 501: int csh; ! 502: int settle; ! 503: int setmode(); ! 504: extern prc(); ! 505: extern char PC; ! 506: # ifdef V6 ! 507: extern int ospeed; ! 508: # else ! 509: extern short ospeed; ! 510: # endif ! 511: # ifdef UCB_NTTY ! 512: int lmode; ! 513: int ldisc; ! 514: ! 515: ioctl(FILEDES, TIOCLGET, &lmode); ! 516: ioctl(FILEDES, TIOCGETD, &ldisc); ! 517: # endif ! 518: ! 519: # ifndef USG ! 520: if (gtty(FILEDES, &mode) < 0) ! 521: # else ! 522: if (ioctl(FILEDES, TCGETA, &mode) < 0) ! 523: # endif ! 524: { ! 525: prs("Not a terminal\n"); ! 526: exit(1); ! 527: } ! 528: bmove(&mode, &oldmode, sizeof mode); ! 529: # ifndef USG ! 530: ospeed = mode.sg_ospeed & 017; ! 531: # else ! 532: ospeed = mode.c_cflag & CBAUD; ! 533: # endif ! 534: signal(SIGINT, setmode); ! 535: signal(SIGQUIT, setmode); ! 536: signal(SIGTERM, setmode); ! 537: ! 538: if (command = rindex(argv[0], '/')) ! 539: command++; ! 540: else ! 541: command = argv[0]; ! 542: if (sequal(command, "reset") ) ! 543: { ! 544: /* ! 545: * reset the teletype mode bits to a sensible state. ! 546: * Copied from the program by Kurt Shoens & Mark Horton. ! 547: * Very useful after crapping out in raw. ! 548: */ ! 549: # ifndef V6 ! 550: # ifdef TIOCGETC ! 551: struct tchars tbuf; ! 552: # endif TIOCGETC ! 553: # ifdef UCB_NTTY ! 554: struct ltchars ltc; ! 555: ! 556: if (ldisc == NTTYDISC) ! 557: { ! 558: ioctl(FILEDES, TIOCGLTC, <c); ! 559: ltc.t_suspc = CHK(ltc.t_suspc, CTRL('Z')); ! 560: ltc.t_dsuspc = CHK(ltc.t_dsuspc, CTRL('Y')); ! 561: ltc.t_rprntc = CHK(ltc.t_rprntc, CTRL('R')); ! 562: ltc.t_flushc = CHK(ltc.t_flushc, CTRL('O')); ! 563: ltc.t_werasc = CHK(ltc.t_werasc, CTRL('W')); ! 564: ltc.t_lnextc = CHK(ltc.t_lnextc, CTRL('V')); ! 565: ioctl(FILEDES, TIOCSLTC, <c); ! 566: } ! 567: # endif UCB_NTTY ! 568: # ifndef USG ! 569: # ifdef TIOCGETC ! 570: ioctl(FILEDES, TIOCGETC, &tbuf); ! 571: tbuf.t_intrc = CHK(tbuf.t_intrc, CTRL('?')); ! 572: tbuf.t_quitc = CHK(tbuf.t_quitc, CTRL('\\')); ! 573: tbuf.t_startc = CHK(tbuf.t_startc, CTRL('Q')); ! 574: tbuf.t_stopc = CHK(tbuf.t_stopc, CTRL('S')); ! 575: tbuf.t_eofc = CHK(tbuf.t_eofc, CTRL('D')); ! 576: /* brkc is left alone */ ! 577: ioctl(FILEDES, TIOCSETC, &tbuf); ! 578: # endif TIOCGETC ! 579: mode.sg_flags &= ~(RAW ! 580: # ifdef CBREAK ! 581: |CBREAK ! 582: # endif CBREAK ! 583: |VTDELAY|ALLDELAY); ! 584: mode.sg_flags |= XTABS|ECHO|CRMOD|ANYP; ! 585: curerase = CHK(curerase, OLDERASE); ! 586: curkill = CHK(curkill, OLDKILL); ! 587: # else USG ! 588: ioctl(FILEDES, TCGETA, &mode); ! 589: curerase = CHK(curerase, OLDERASE); ! 590: curkill = CHK(curkill, OLDKILL); ! 591: mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CTRL('?')); ! 592: mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CTRL('\\')); ! 593: mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CTRL('D')); ! 594: ! 595: mode.c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON); ! 596: mode.c_iflag &= ~(IGNBRK|PARMRK|INPCK|INLCR|IGNCR|IUCLC|IXOFF); ! 597: mode.c_oflag |= (OPOST|ONLCR); ! 598: mode.c_oflag &= ~(OLCUC|OCRNL|ONOCR|ONLRET|OFILL|OFDEL| ! 599: NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); ! 600: mode.c_cflag |= (CS7|CREAD); ! 601: mode.c_cflag &= ~(CSIZE|PARODD|CLOCAL); ! 602: mode.c_lflag |= (ISIG|ICANON|ECHO|ECHOK); ! 603: mode.c_lflag &= ~(XCASE|ECHONL|NOFLSH); ! 604: ioctl(FILEDES, TCSETAW, &mode); ! 605: # endif USG ! 606: # endif V6 ! 607: Dash_u = YES; ! 608: BeQuiet = YES; ! 609: IsReset = YES; ! 610: } ! 611: else if (argc == 2 && sequal(argv[1], "-")) ! 612: { ! 613: RepOnly = YES; ! 614: Dash_u = YES; ! 615: } ! 616: argc--; ! 617: ! 618: /* scan argument list and collect flags */ ! 619: while (--argc >= 0) ! 620: { ! 621: p = *++argv; ! 622: if (*p == '-') ! 623: { ! 624: if (*++p == NULL) ! 625: Report = YES; /* report current terminal type */ ! 626: else while (*p) switch (*p++) ! 627: { ! 628: ! 629: # ifdef UCB_NTTY ! 630: case 'n': ! 631: ldisc = NTTYDISC; ! 632: if (ioctl(FILEDES, TIOCSETD, &ldisc)<0) ! 633: fatal("ioctl ", "new"); ! 634: continue; ! 635: # endif ! 636: ! 637: case 'r': /* report to user */ ! 638: Ureport = YES; ! 639: continue; ! 640: ! 641: case 'E': /* special erase: operate on all but TTY33 */ ! 642: Specialerase = YES; ! 643: /* explicit fall-through to -e case */ ! 644: ! 645: case 'e': /* erase character */ ! 646: if (*p == NULL) ! 647: Erase_char = -1; ! 648: else ! 649: { ! 650: if (*p == '^' && p[1] != NULL) ! 651: Erase_char = CTRL(*++p); ! 652: else ! 653: Erase_char = *p; ! 654: p++; ! 655: } ! 656: continue; ! 657: ! 658: case 'k': /* kill character */ ! 659: if (*p == NULL) ! 660: Kill_char = CTRL('X'); ! 661: else ! 662: { ! 663: if (*p == '^' && p[1] != NULL) ! 664: Kill_char = CTRL(*++p); ! 665: else ! 666: Kill_char = *p; ! 667: p++; ! 668: } ! 669: continue; ! 670: ! 671: # ifdef OLDFLAGS ! 672: # ifdef OLDDIALUP ! 673: case 'd': /* dialup type */ ! 674: NewType = DIALUP; ! 675: goto mapold; ! 676: # endif ! 677: ! 678: # ifdef OLDPLUGBOARD ! 679: case 'p': /* plugboard type */ ! 680: NewType = PLUGBOARD; ! 681: goto mapold; ! 682: # endif ! 683: ! 684: # ifdef OLDARPANET ! 685: case 'a': /* arpanet type */ ! 686: Newtype = ARPANET; ! 687: goto mapold; ! 688: # endif ! 689: ! 690: mapold: Map->Ident = NewType; ! 691: Map->Test = ALL; ! 692: if (*p == NULL) ! 693: { ! 694: p = nextarg(argc--, argv++); ! 695: } ! 696: Map->Type = p; ! 697: Map++; ! 698: Mapped = YES; ! 699: p = ""; ! 700: continue; ! 701: # endif ! 702: ! 703: case 'm': /* map identifier to type */ ! 704: /* This code is very loose. Almost no ! 705: ** syntax checking is done!! However, ! 706: ** illegal syntax will only produce ! 707: ** weird results. ! 708: */ ! 709: if (*p == NULL) ! 710: { ! 711: p = nextarg(argc--, argv++); ! 712: } ! 713: if (isalnum(*p)) ! 714: { ! 715: Map->Ident = p; /* identifier */ ! 716: while (isalnum(*p)) p++; ! 717: } ! 718: else ! 719: Map->Ident = ""; ! 720: Break = NO; ! 721: Not = NO; ! 722: while (!Break) switch (*p) ! 723: { ! 724: case NULL: ! 725: p = nextarg(argc--, argv++); ! 726: continue; ! 727: ! 728: case ':': /* mapped type */ ! 729: *p++ = NULL; ! 730: Break = YES; ! 731: continue; ! 732: ! 733: case '>': /* conditional */ ! 734: Map->Test |= GT; ! 735: *p++ = NULL; ! 736: continue; ! 737: ! 738: case '<': /* conditional */ ! 739: Map->Test |= LT; ! 740: *p++ = NULL; ! 741: continue; ! 742: ! 743: case '=': /* conditional */ ! 744: case '@': ! 745: Map->Test |= EQ; ! 746: *p++ = NULL; ! 747: continue; ! 748: ! 749: case '!': /* invert conditions */ ! 750: Not = ~Not; ! 751: *p++ = NULL; ! 752: continue; ! 753: ! 754: case 'B': /* Baud rate */ ! 755: p++; ! 756: /* intentional fallthru */ ! 757: default: ! 758: if (isdigit(*p) || *p == 'e') ! 759: { ! 760: Map->Speed = baudrate(p); ! 761: while (isalnum(*p) || *p == '.') ! 762: p++; ! 763: } ! 764: else ! 765: Break = YES; ! 766: continue; ! 767: } ! 768: if (Not) /* invert sense of test */ ! 769: { ! 770: Map->Test = (~(Map->Test))&ALL; ! 771: } ! 772: if (*p == NULL) ! 773: { ! 774: p = nextarg(argc--, argv++); ! 775: } ! 776: Map->Type = p; ! 777: p = ""; ! 778: Map++; ! 779: Mapped = YES; ! 780: continue; ! 781: ! 782: case 'h': /* don't get type from htmp or env */ ! 783: Dash_h = YES; ! 784: continue; ! 785: ! 786: case 'u': /* don't update htmp */ ! 787: Dash_u = YES; ! 788: continue; ! 789: ! 790: case 's': /* output setenv commands */ ! 791: DoSetenv = YES; ! 792: CmndLine = YES; ! 793: continue; ! 794: ! 795: case 'S': /* output setenv strings */ ! 796: DoSetenv = YES; ! 797: CmndLine = NO; ! 798: continue; ! 799: ! 800: case 'Q': /* be quiet */ ! 801: BeQuiet = YES; ! 802: continue; ! 803: ! 804: case 'I': /* no initialization */ ! 805: NoInit = YES; ! 806: continue; ! 807: ! 808: case 'A': /* Ask user */ ! 809: Ask = YES; ! 810: continue; ! 811: ! 812: case 'v': /* no virtual terminal */ ! 813: DoVirtTerm = NO; ! 814: continue; ! 815: ! 816: default: ! 817: *p-- = NULL; ! 818: fatal("Bad flag -", p); ! 819: } ! 820: } ! 821: else ! 822: { ! 823: /* terminal type */ ! 824: DefType = p; ! 825: } ! 826: } ! 827: ! 828: if (DefType) ! 829: { ! 830: if (Mapped) ! 831: { ! 832: Map->Ident = ""; /* means "map any type" */ ! 833: Map->Test = ALL; /* at all baud rates */ ! 834: Map->Type = DefType; /* to the default type */ ! 835: } ! 836: else ! 837: TtyType = DefType; ! 838: } ! 839: ! 840: # ifndef V6 ! 841: /* ! 842: * Get rid of $TERMCAP, if it's there, so we get a real ! 843: * entry from /etc/termcap. This prevents us from being ! 844: * fooled by out of date stuff in the environment, and ! 845: * makes tabs work right on CB/Unix. ! 846: */ ! 847: bufp = getenv("TERMCAP"); ! 848: if (bufp && *bufp != '/') ! 849: strcpy(bufp-8, "NOTHING"); /* overwrite only "TERMCAP" */ ! 850: /* get current idea of terminal type from environment */ ! 851: if (!Dash_h && !Mapped && TtyType == 0) ! 852: TtyType = getenv("TERM"); ! 853: # endif ! 854: ! 855: /* determine terminal id if needed */ ! 856: # ifdef V6 ! 857: if (Ttyid == NOTTY && (TtyType == 0 || !Dash_h || !Dash_u)) ! 858: Ttyid = ttyn(FILEDES); ! 859: # else ! 860: if (!RepOnly && Ttyid == NOTTY && (TtyType == 0 || !Dash_h)) ! 861: Ttyid = ttyname(FILEDES); ! 862: # endif ! 863: ! 864: # ifdef V6 ! 865: /* get htmp if ever used */ ! 866: if (!Dash_u || (TtyType == 0 && !Dash_h)) ! 867: { ! 868: /* get htmp entry -- if error or wrong user use ttytype */ ! 869: if (Ttyid == NOTTY || hget(Ttyid) < 0 || ! 870: hgettype() == 0 || hgetuid() != (getuid() & UIDMASK)) ! 871: Dash_h++; ! 872: } ! 873: ! 874: /* find terminal type (if not already known) */ ! 875: if (TtyType == 0 && !Dash_h) ! 876: { ! 877: /* get type from /etc/htmp */ ! 878: TtyType = hsgettype(); ! 879: } ! 880: # endif ! 881: ! 882: # ifdef GTTYN ! 883: /* If still undefined, look at /etc/ttytype */ ! 884: if (TtyType == 0) ! 885: { ! 886: TtyType = stypeof(Ttyid); ! 887: } ! 888: # endif ! 889: ! 890: /* If still undefined, use DEFTYPE */ ! 891: if (TtyType == 0) ! 892: { ! 893: TtyType = DEFTYPE; ! 894: } ! 895: ! 896: /* check for dialup or other mapping */ ! 897: if (Mapped) ! 898: TtyType = mapped(TtyType); ! 899: ! 900: /* TtyType now contains a pointer to the type of the terminal */ ! 901: /* If the first character is '?', ask the user */ ! 902: if (TtyType[0] == '?') ! 903: { ! 904: Ask = YES; ! 905: TtyType++; ! 906: if (TtyType[0] == '\0') ! 907: TtyType = DEFTYPE; ! 908: } ! 909: if (Ask) ! 910: { ! 911: prs("TERM = ("); ! 912: prs(TtyType); ! 913: prs(") "); ! 914: flush(); ! 915: ! 916: /* read the terminal. If not empty, set type */ ! 917: i = read(2, termbuf, sizeof termbuf - 1); ! 918: if (i > 0) ! 919: { ! 920: if (termbuf[i - 1] == '\n') ! 921: i--; ! 922: termbuf[i] = '\0'; ! 923: if (termbuf[0] != '\0') ! 924: TtyType = termbuf; ! 925: } ! 926: } ! 927: ! 928: /* get terminal capabilities */ ! 929: if (!(Alias[0] && isalias(TtyType))) { ! 930: switch (tgetent(Capbuf, TtyType)) ! 931: { ! 932: case -1: ! 933: prs("Cannot find termcap\n"); ! 934: flush(); ! 935: exit(-1); ! 936: ! 937: case 0: ! 938: prs("Type "); ! 939: prs(TtyType); ! 940: prs(" unknown\n"); ! 941: flush(); ! 942: if (DoSetenv) ! 943: { ! 944: TtyType = DEFTYPE; ! 945: tgetent(Capbuf, TtyType); ! 946: } ! 947: else ! 948: exit(1); ! 949: } ! 950: } ! 951: Ttycap = Capbuf; ! 952: ! 953: if (!RepOnly) ! 954: { ! 955: /* determine erase and kill characters */ ! 956: if (Specialerase && !tgetflag("bs")) ! 957: Erase_char = 0; ! 958: bufp = buf; ! 959: p = tgetstr("kb", &bufp); ! 960: if (p == NULL || p[1] != '\0') ! 961: p = tgetstr("bc", &bufp); ! 962: if (p != NULL && p[1] == '\0') ! 963: bs_char = p[0]; ! 964: else if (tgetflag("bs")) ! 965: bs_char = BACKSPACE; ! 966: else ! 967: bs_char = 0; ! 968: if (Erase_char == 0 && !tgetflag("os") && curerase == OLDERASE) ! 969: { ! 970: if (tgetflag("bs") || bs_char != 0) ! 971: Erase_char = -1; ! 972: } ! 973: if (Erase_char < 0) ! 974: Erase_char = (bs_char != 0) ? bs_char : BACKSPACE; ! 975: ! 976: if (curerase == 0) ! 977: curerase = OLDERASE; ! 978: if (Erase_char != 0) ! 979: curerase = Erase_char; ! 980: ! 981: if (curkill == 0) ! 982: curkill = OLDKILL; ! 983: if (Kill_char != 0) ! 984: curkill = Kill_char; ! 985: ! 986: /* set modes */ ! 987: PadBaud = tgetnum("pb"); /* OK if fails */ ! 988: for (i=0; speeds[i].string; i++) ! 989: if (speeds[i].baudrate == PadBaud) { ! 990: PadBaud = speeds[i].speed; ! 991: break; ! 992: } ! 993: # ifndef USG ! 994: setdelay("dC", CRdelay, CRbits, &mode.sg_flags); ! 995: setdelay("dN", NLdelay, NLbits, &mode.sg_flags); ! 996: setdelay("dB", BSdelay, BSbits, &mode.sg_flags); ! 997: setdelay("dF", FFdelay, FFbits, &mode.sg_flags); ! 998: setdelay("dT", TBdelay, TBbits, &mode.sg_flags); ! 999: if (tgetflag("UC") || (command[0] & 0140) == 0100) ! 1000: mode.sg_flags |= LCASE; ! 1001: else if (tgetflag("LC")) ! 1002: mode.sg_flags &= ~LCASE; ! 1003: mode.sg_flags &= ~(EVENP | ODDP | RAW); ! 1004: # ifdef CBREAK ! 1005: mode.sg_flags &= ~CBREAK; ! 1006: # endif ! 1007: if (tgetflag("EP")) ! 1008: mode.sg_flags |= EVENP; ! 1009: if (tgetflag("OP")) ! 1010: mode.sg_flags |= ODDP; ! 1011: if ((mode.sg_flags & (EVENP | ODDP)) == 0) ! 1012: mode.sg_flags |= EVENP | ODDP; ! 1013: mode.sg_flags |= CRMOD | ECHO | XTABS; ! 1014: if (tgetflag("NL")) /* new line, not line feed */ ! 1015: mode.sg_flags &= ~CRMOD; ! 1016: if (tgetflag("HD")) /* half duplex */ ! 1017: mode.sg_flags &= ~ECHO; ! 1018: if (tgetflag("pt")) /* print tabs */ ! 1019: mode.sg_flags &= ~XTABS; ! 1020: # else ! 1021: setdelay("dC", CRdelay, CRbits, &mode.c_oflag); ! 1022: setdelay("dN", NLdelay, NLbits, &mode.c_oflag); ! 1023: setdelay("dB", BSdelay, BSbits, &mode.c_oflag); ! 1024: setdelay("dF", FFdelay, FFbits, &mode.c_oflag); ! 1025: setdelay("dT", TBdelay, TBbits, &mode.c_oflag); ! 1026: setdelay("dV", VTdelay, VTbits, &mode.c_oflag); ! 1027: ! 1028: if (tgetflag("UC") || (command[0] & 0140) == 0100) { ! 1029: mode.c_iflag |= IUCLC; ! 1030: mode.c_oflag |= OLCUC; ! 1031: } ! 1032: else if (tgetflag("LC")) { ! 1033: mode.c_iflag &= ~IUCLC; ! 1034: mode.c_oflag &= ~OLCUC; ! 1035: } ! 1036: mode.c_iflag &= ~(PARMRK|INPCK); ! 1037: mode.c_lflag |= ICANON; ! 1038: if (tgetflag("EP")) { ! 1039: mode.c_cflag |= PARENB; ! 1040: mode.c_cflag &= ~PARODD; ! 1041: } ! 1042: if (tgetflag("OP")) { ! 1043: mode.c_cflag |= PARENB; ! 1044: mode.c_cflag |= PARODD; ! 1045: } ! 1046: ! 1047: mode.c_oflag |= ONLCR; ! 1048: mode.c_iflag |= ICRNL; ! 1049: mode.c_lflag |= ECHO; ! 1050: mode.c_oflag |= TAB3; ! 1051: if (tgetflag("NL")) { /* new line, not line feed */ ! 1052: mode.c_oflag &= ~ONLCR; ! 1053: mode.c_iflag &= ~ICRNL; ! 1054: } ! 1055: if (tgetflag("HD")) /* half duplex */ ! 1056: mode.c_lflag &= ~ECHO; ! 1057: if (tgetflag("pt")) /* print tabs */ ! 1058: mode.c_oflag &= ~TAB3; ! 1059: ! 1060: mode.c_lflag |= (ECHOE|ECHOK); ! 1061: # endif ! 1062: # ifdef CBVIRTTERM ! 1063: HasAM = tgetflag("am"); ! 1064: # endif CBVIRTTERM ! 1065: # ifdef UCB_NTTY ! 1066: if (ldisc == NTTYDISC) ! 1067: { ! 1068: lmode |= LCTLECH; /* display ctrl chars */ ! 1069: if (tgetflag("hc")) ! 1070: { /** set printer modes **/ ! 1071: lmode &= ~(LCRTBS|LCRTERA|LCRTKIL); ! 1072: lmode |= LPRTERA; ! 1073: } ! 1074: else ! 1075: { /** set crt modes **/ ! 1076: if (!tgetflag("os")) ! 1077: { ! 1078: lmode &= ~LPRTERA; ! 1079: lmode |= LCRTBS; ! 1080: if (mode.sg_ospeed >= B1200) ! 1081: lmode |= LCRTERA|LCRTKIL; ! 1082: } ! 1083: } ! 1084: } ! 1085: ioctl(FILEDES, TIOCLSET, &lmode); ! 1086: # endif ! 1087: ! 1088: /* get pad character */ ! 1089: bufp = buf; ! 1090: if (tgetstr("pc", &bufp) != 0) ! 1091: PC = buf[0]; ! 1092: ! 1093: /* output startup string */ ! 1094: if (!NoInit) ! 1095: { ! 1096: # ifndef USG ! 1097: if (oldmode.sg_flags&(XTABS|CRMOD)) ! 1098: { ! 1099: oldmode.sg_flags &= ~(XTABS|CRMOD); ! 1100: setmode(-1); ! 1101: } ! 1102: # else ! 1103: if (oldmode.c_oflag&(TAB3|ONLCR|OCRNL|ONLRET)) ! 1104: { ! 1105: oldmode.c_oflag &= (TAB3|ONLCR|OCRNL|ONLRET); ! 1106: setmode(-1); ! 1107: } ! 1108: # endif ! 1109: # ifdef CBVIRTTERM ! 1110: block.st_termt = 0; ! 1111: ioctl(FILEDES, LDSETT, &block); ! 1112: # endif CBVIRTTERM ! 1113: if (settabs()) { ! 1114: settle = YES; ! 1115: flush(); ! 1116: } ! 1117: bufp = buf; ! 1118: if (tgetstr(IsReset? "rs" : "is", &bufp) != 0) ! 1119: { ! 1120: tputs(buf, 0, prc); ! 1121: settle = YES; ! 1122: flush(); ! 1123: } ! 1124: bufp = buf; ! 1125: if (tgetstr(IsReset? "rf" : "if", &bufp) != 0) ! 1126: { ! 1127: cat(buf); ! 1128: settle = YES; ! 1129: } ! 1130: if (settle) ! 1131: { ! 1132: prc('\r'); ! 1133: flush(); ! 1134: sleep(1); /* let terminal settle down */ ! 1135: } ! 1136: } ! 1137: ! 1138: # ifdef CBVIRTTERM ! 1139: if (DoVirtTerm) { ! 1140: j = tgetnum("vt"); ! 1141: VirTermNo = -1; ! 1142: for (i=0; vt_map[i].stdnum; i++) ! 1143: if (vt_map[i].stdnum == j) ! 1144: VirTermNo = vt_map[i].localnum; ! 1145: } else ! 1146: VirTermNo = -1; ! 1147: # endif CBVIRTTERM ! 1148: ! 1149: setmode(0); /* set new modes, if they've changed */ ! 1150: ! 1151: /* set up environment for the shell we are using */ ! 1152: /* (this code is rather heuristic, checking for $SHELL */ ! 1153: /* ending in the 3 characters "csh") */ ! 1154: csh = NO; ! 1155: if (DoSetenv) ! 1156: { ! 1157: # ifndef V6 ! 1158: char *sh; ! 1159: ! 1160: if ((sh = getenv("SHELL")) && (i = strlen(sh)) >= 3) ! 1161: { ! 1162: if ((csh = sequal(&sh[i-3], "csh")) && CmndLine) ! 1163: write(STDOUT, "set noglob;\n", 12); ! 1164: } ! 1165: if (!csh) ! 1166: # endif ! 1167: /* running Bourne shell */ ! 1168: write(STDOUT, "export TERMCAP TERM;\n", 21); ! 1169: } ! 1170: } ! 1171: ! 1172: /* report type if appropriate */ ! 1173: if (DoSetenv || Report || Ureport) ! 1174: { ! 1175: /* if type is the short name, find first alias (if any) */ ! 1176: makealias(Ttycap); ! 1177: if (sequal(TtyType, Alias[0]) && Alias[1]) { ! 1178: TtyType = Alias[1]; ! 1179: } ! 1180: ! 1181: if (DoSetenv) ! 1182: { ! 1183: if (csh) ! 1184: { ! 1185: if (CmndLine) ! 1186: write(STDOUT, "setenv TERM ", 12); ! 1187: write(STDOUT, TtyType, strlen(TtyType)); ! 1188: write(STDOUT, " ", 1); ! 1189: if (CmndLine) ! 1190: write(STDOUT, ";\n", 2); ! 1191: } ! 1192: else ! 1193: { ! 1194: write(STDOUT, "TERM=", 5); ! 1195: write(STDOUT, TtyType, strlen(TtyType)); ! 1196: write(STDOUT, ";\n", 2); ! 1197: } ! 1198: } ! 1199: else if (Report) ! 1200: { ! 1201: write(STDOUT, TtyType, strlen(TtyType)); ! 1202: write(STDOUT, "\n", 1); ! 1203: } ! 1204: if (Ureport) ! 1205: { ! 1206: prs("Terminal type is "); ! 1207: prs(TtyType); ! 1208: prs("\n"); ! 1209: flush(); ! 1210: } ! 1211: ! 1212: if (DoSetenv) ! 1213: { ! 1214: if (csh) ! 1215: { ! 1216: if (CmndLine) ! 1217: write(STDOUT, "setenv TERMCAP '", 16); ! 1218: } ! 1219: else ! 1220: write(STDOUT, "TERMCAP='", 9); ! 1221: wrtermcap(Ttycap); ! 1222: if (csh) ! 1223: { ! 1224: if (CmndLine) ! 1225: { ! 1226: write(STDOUT, "';\n", 3); ! 1227: write(STDOUT, "unset noglob;\n", 14); ! 1228: } ! 1229: } ! 1230: else ! 1231: write(STDOUT, "';\n", 3); ! 1232: } ! 1233: } ! 1234: ! 1235: if (RepOnly) ! 1236: exit(0); ! 1237: ! 1238: /* tell about changing erase and kill characters */ ! 1239: reportek("Erase", curerase, olderase, OLDERASE); ! 1240: reportek("Kill", curkill, oldkill, OLDKILL); ! 1241: ! 1242: # ifdef V6 ! 1243: /* update htmp */ ! 1244: if (!Dash_u) ! 1245: { ! 1246: if (Ttyid == 0) ! 1247: Ttyid = ttyn(FILEDES); ! 1248: if (Ttyid == 'x') ! 1249: { ! 1250: prs("Cannot update htmp\n"); ! 1251: flush(); ! 1252: } ! 1253: else ! 1254: { ! 1255: /* update htmp file only if changed */ ! 1256: if (!bequal(Capbuf, hsgettype(), 2)) ! 1257: { ! 1258: hsettype(Capbuf[0] | (Capbuf[1] << 8)); ! 1259: hput(Ttyid); ! 1260: } ! 1261: } ! 1262: } ! 1263: # endif ! 1264: ! 1265: exit(0); ! 1266: } ! 1267: ! 1268: /* ! 1269: * Set the hardware tabs on the terminal, using the ct (clear all tabs), ! 1270: * st (set one tab) and ch (horizontal cursor addressing) capabilities. ! 1271: * This is done before if and is, so they can patch in case we blow this. ! 1272: */ ! 1273: settabs() ! 1274: { ! 1275: char caps[100]; ! 1276: char *capsp = caps; ! 1277: char *clear_tabs, *set_tab, *set_column, *set_pos; ! 1278: char *tg_out, *tgoto(); ! 1279: int columns, lines, c; ! 1280: ! 1281: clear_tabs = tgetstr("ct", &capsp); ! 1282: set_tab = tgetstr("st", &capsp); ! 1283: set_column = tgetstr("ch", &capsp); ! 1284: if (set_column == 0) ! 1285: set_pos = tgetstr("cm", &capsp); ! 1286: columns = tgetnum("co"); ! 1287: lines = tgetnum("li"); ! 1288: ! 1289: if (clear_tabs && set_tab) { ! 1290: prc('\r'); /* force to be at left margin */ ! 1291: tputs(clear_tabs, 0, prc); ! 1292: } ! 1293: if (set_tab) { ! 1294: for (c=8; c<columns; c += 8) { ! 1295: /* get to that column. */ ! 1296: tg_out = "OOPS"; /* also returned by tgoto */ ! 1297: if (set_column) ! 1298: tg_out = tgoto(set_column, 0, c); ! 1299: if (*tg_out == 'O' && set_pos) ! 1300: tg_out = tgoto(set_pos, c, lines-1); ! 1301: if (*tg_out != 'O') ! 1302: tputs(tg_out, 1, prc); ! 1303: else { ! 1304: prc(' '); prc(' '); prc(' '); prc(' '); ! 1305: prc(' '); prc(' '); prc(' '); prc(' '); ! 1306: } ! 1307: /* set the tab */ ! 1308: tputs(set_tab, 0, prc); ! 1309: } ! 1310: prc('\r'); ! 1311: return 1; ! 1312: } ! 1313: return 0; ! 1314: } ! 1315: ! 1316: setmode(flag) ! 1317: int flag; ! 1318: /* flag serves several purposes: ! 1319: * if called as the result of a signal, flag will be > 0. ! 1320: * if called from terminal init, flag == -1 means reset "oldmode". ! 1321: * called with flag == 0 at end of normal mode processing. ! 1322: */ ! 1323: { ! 1324: # ifndef USG ! 1325: struct sgttyb *ttymode; ! 1326: # else ! 1327: struct termio *ttymode; ! 1328: # endif ! 1329: ! 1330: if (flag < 0) /* unconditionally reset oldmode (called from init) */ ! 1331: ttymode = &oldmode; ! 1332: else if (!bequal(&mode, &oldmode, sizeof mode)) ! 1333: ttymode = &mode; ! 1334: else /* don't need it */ ! 1335: # ifndef USG ! 1336: ttymode = (struct sgttyb *)0; ! 1337: # else ! 1338: ttymode = (struct termio *)0; ! 1339: # endif ! 1340: ! 1341: if (ttymode) ! 1342: { ! 1343: # ifdef USG ! 1344: ioctl(FILEDES, TCSETAW, ttymode); ! 1345: # else ! 1346: # ifndef V6 ! 1347: ioctl(FILEDES, TIOCSETN, ttymode); /* don't flush */ ! 1348: # else ! 1349: stty(FILEDES, ttymode); ! 1350: # endif ! 1351: # endif ! 1352: } ! 1353: # ifdef CBVIRTTERM ! 1354: if (VirTermNo != -2) { ! 1355: int r1, r2; ! 1356: extern int errno; ! 1357: ! 1358: r1 = ioctl(FILEDES, LDGETT, &block); ! 1359: block.st_flgs |= TM_SET; ! 1360: block.st_termt = VirTermNo; ! 1361: if (block.st_termt < 0) ! 1362: block.st_termt = 0; ! 1363: if (!HasAM) ! 1364: block.st_flgs |= TM_ANL; ! 1365: else ! 1366: block.st_flgs &= ~TM_ANL; ! 1367: r2 = ioctl(FILEDES, LDSETT, &block); ! 1368: } ! 1369: # endif ! 1370: ! 1371: if (flag > 0) /* trapped signal */ ! 1372: exit(1); ! 1373: } ! 1374: ! 1375: reportek(name, new, old, def) ! 1376: char *name; ! 1377: char old; ! 1378: char new; ! 1379: char def; ! 1380: { ! 1381: register char o; ! 1382: register char n; ! 1383: register char *p; ! 1384: char buf[32]; ! 1385: char *bufp; ! 1386: ! 1387: if (BeQuiet) ! 1388: return; ! 1389: o = old; ! 1390: n = new; ! 1391: ! 1392: if (o == n && n == def) ! 1393: return; ! 1394: prs(name); ! 1395: if (o == n) ! 1396: prs(" is "); ! 1397: else ! 1398: prs(" set to "); ! 1399: bufp = buf; ! 1400: if (tgetstr("kb", &bufp) > 0 && n == buf[0] && buf[1] == NULL) ! 1401: prs("Backspace\n"); ! 1402: else if (n == 0177) ! 1403: prs("Delete\n"); ! 1404: else ! 1405: { ! 1406: if (n < 040) ! 1407: { ! 1408: prs("Ctrl-"); ! 1409: n ^= 0100; ! 1410: } ! 1411: p = "x\n"; ! 1412: p[0] = n; ! 1413: prs(p); ! 1414: } ! 1415: flush(); ! 1416: } ! 1417: ! 1418: ! 1419: ! 1420: ! 1421: setdelay(cap, dtab, bits, flags) ! 1422: char *cap; ! 1423: struct delay dtab[]; ! 1424: int bits; ! 1425: int *flags; ! 1426: { ! 1427: register int i; ! 1428: register struct delay *p; ! 1429: # ifdef V6 ! 1430: extern int ospeed; ! 1431: # else ! 1432: extern short ospeed; ! 1433: # endif ! 1434: ! 1435: /* see if this capability exists at all */ ! 1436: i = tgetnum(cap); ! 1437: if (i < 0) ! 1438: i = 0; ! 1439: /* No padding at speeds below PadBaud */ ! 1440: if (PadBaud > ospeed) ! 1441: i = 0; ! 1442: ! 1443: /* clear out the bits, replace with new ones */ ! 1444: *flags &= ~bits; ! 1445: ! 1446: /* scan dtab for first entry with adequate delay */ ! 1447: for (p = dtab; p->d_delay >= 0; p++) ! 1448: { ! 1449: if (p->d_delay >= i) ! 1450: { ! 1451: p++; ! 1452: break; ! 1453: } ! 1454: } ! 1455: ! 1456: /* use last entry if none will do */ ! 1457: *flags |= (--p)->d_bits; ! 1458: } ! 1459: ! 1460: ! 1461: prs(s) ! 1462: char *s; ! 1463: { ! 1464: while (*s != '\0') ! 1465: prc(*s++); ! 1466: } ! 1467: ! 1468: ! 1469: char OutBuf[256]; ! 1470: int OutPtr; ! 1471: ! 1472: prc(c) ! 1473: char c; ! 1474: { ! 1475: OutBuf[OutPtr++] = c; ! 1476: if (OutPtr >= sizeof OutBuf) ! 1477: flush(); ! 1478: } ! 1479: ! 1480: flush() ! 1481: { ! 1482: if (OutPtr > 0) ! 1483: write(2, OutBuf, OutPtr); ! 1484: OutPtr = 0; ! 1485: } ! 1486: ! 1487: ! 1488: cat(file) ! 1489: char *file; ! 1490: { ! 1491: register int fd; ! 1492: register int i; ! 1493: char buf[BUFSIZ]; ! 1494: ! 1495: fd = open(file, 0); ! 1496: if (fd < 0) ! 1497: { ! 1498: prs("Cannot open "); ! 1499: prs(file); ! 1500: prs("\n"); ! 1501: flush(); ! 1502: return; ! 1503: } ! 1504: ! 1505: while ((i = read(fd, buf, BUFSIZ)) > 0) ! 1506: write(FILEDES, buf, i); ! 1507: ! 1508: close(fd); ! 1509: } ! 1510: ! 1511: ! 1512: ! 1513: bmove(from, to, length) ! 1514: char *from; ! 1515: char *to; ! 1516: int length; ! 1517: { ! 1518: register char *p, *q; ! 1519: register int i; ! 1520: ! 1521: i = length; ! 1522: p = from; ! 1523: q = to; ! 1524: ! 1525: while (i-- > 0) ! 1526: *q++ = *p++; ! 1527: } ! 1528: ! 1529: ! 1530: ! 1531: bequal(a, b, len) /* must be same thru len chars */ ! 1532: char *a; ! 1533: char *b; ! 1534: int len; ! 1535: { ! 1536: register char *p, *q; ! 1537: register int i; ! 1538: ! 1539: i = len; ! 1540: p = a; ! 1541: q = b; ! 1542: ! 1543: while ((*p == *q) && --i > 0) ! 1544: { ! 1545: p++; q++; ! 1546: } ! 1547: return ((*p == *q) && i >= 0); ! 1548: } ! 1549: ! 1550: sequal(a, b) /* must be same thru NULL */ ! 1551: char *a; ! 1552: char *b; ! 1553: { ! 1554: register char *p = a, *q = b; ! 1555: ! 1556: while (*p && *q && (*p == *q)) ! 1557: { ! 1558: p++; q++; ! 1559: } ! 1560: return (*p == *q); ! 1561: } ! 1562: ! 1563: makealias(buf) ! 1564: char *buf; ! 1565: { ! 1566: register int i; ! 1567: register char *a; ! 1568: register char *b; ! 1569: ! 1570: Alias[0] = a = Aliasbuf; ! 1571: b = buf; ! 1572: i = 1; ! 1573: while (*b && *b != ':') { ! 1574: if (*b == '|') { ! 1575: *a++ = NULL; ! 1576: Alias[i++] = a; ! 1577: b++; ! 1578: } ! 1579: else ! 1580: *a++ = *b++; ! 1581: } ! 1582: *a = NULL; ! 1583: Alias[i] = NULL; ! 1584: # ifdef DEB ! 1585: for(i = 0; Alias[i]; printf("A:%s\n", Alias[i++])); ! 1586: # endif ! 1587: } ! 1588: ! 1589: isalias(ident) /* is ident same as one of the aliases? */ ! 1590: char *ident; ! 1591: { ! 1592: char **a = Alias; ! 1593: ! 1594: if (*a) ! 1595: while (*a) ! 1596: if (sequal(ident, *a)) ! 1597: return(YES); ! 1598: else ! 1599: a++; ! 1600: return(NO); ! 1601: } ! 1602: ! 1603: # ifdef GTTYN ! 1604: char * ! 1605: stypeof(ttyid) ! 1606: char *ttyid; ! 1607: { ! 1608: static char typebuf[BUFSIZ]; ! 1609: register char *PortType; ! 1610: register char *PortName; ! 1611: register char *TtyId; ! 1612: register char *p; ! 1613: register FILE *f; ! 1614: ! 1615: if (ttyid == NOTTY) ! 1616: return (DEFTYPE); ! 1617: f = fopen(GTTYN, "r"); ! 1618: if (f == NULL) ! 1619: return (DEFTYPE); ! 1620: ! 1621: /* split off end of name */ ! 1622: TtyId = ttyid; ! 1623: while (*ttyid) ! 1624: if (*ttyid++ == '/') ! 1625: TtyId = ttyid; ! 1626: ! 1627: /* scan the file */ ! 1628: while (fgets(typebuf, sizeof typebuf, f) != NULL) ! 1629: { ! 1630: p = PortType = typebuf; ! 1631: while (*p && isalnum(*p)) ! 1632: p++; ! 1633: *p++ = NULL; ! 1634: ! 1635: /* skip separator */ ! 1636: while (*p && !isalnum(*p)) ! 1637: p++; ! 1638: ! 1639: PortName = p; ! 1640: /* put NULL at end of name */ ! 1641: while (*p && isalnum(*p)) ! 1642: p++; ! 1643: *p = NULL; ! 1644: ! 1645: /* check match on port name */ ! 1646: if (sequal(PortName, TtyId)) /* found it */ ! 1647: { ! 1648: fclose (f); ! 1649: /* get aliases from termcap entry */ ! 1650: if (Mapped && tgetent(Capbuf, PortType) > 0) { ! 1651: makealias(Capbuf); ! 1652: if (sequal(Alias[0], PortType) && Alias[1]) ! 1653: PortType = Alias[1]; ! 1654: } ! 1655: return(PortType); ! 1656: } ! 1657: } ! 1658: fclose (f); ! 1659: return (DEFTYPE); ! 1660: } ! 1661: # endif ! 1662: ! 1663: /* ! 1664: * routine to output the string for the environment TERMCAP variable ! 1665: */ ! 1666: #define WHITE(c) (c == ' ' || c == '\t') ! 1667: char delcap[128][2]; ! 1668: int ncap = 0; ! 1669: ! 1670: wrtermcap(bp) ! 1671: char *bp; ! 1672: { ! 1673: char buf[CAPBUFSIZ]; ! 1674: register int i; ! 1675: char *p = buf; ! 1676: char *tp; ! 1677: char *putbuf(); ! 1678: int space, empty; ! 1679: ! 1680: /* discard names with blanks */ ! 1681: /** May not be desireable ? **/ ! 1682: while (*bp && *bp != ':') { ! 1683: if (*bp == '|') { ! 1684: tp = bp+1; ! 1685: space = NO; ! 1686: while (*tp && *tp != '|' && *tp != ':') { ! 1687: space = (space || WHITE(*tp) ); ! 1688: tp++; ! 1689: } ! 1690: if (space) { ! 1691: bp = tp; ! 1692: continue; ! 1693: } ! 1694: } ! 1695: *p++ = *bp++; ! 1696: } ! 1697: /**/ ! 1698: ! 1699: # ifdef CBVIRTTERM ! 1700: if (VirTermNo > 0) { ! 1701: p = putbuf(p, ":am"); /* All virt terms have auto margins */ ! 1702: cancelled("am"); ! 1703: } ! 1704: # endif ! 1705: while (*bp) { ! 1706: switch (*bp) { ! 1707: case ':': /* discard empty, cancelled or dupl fields */ ! 1708: tp = bp+1; ! 1709: empty = YES; ! 1710: while (*tp && *tp != ':') { ! 1711: empty = (empty && WHITE(*tp) ); ! 1712: tp++; ! 1713: } ! 1714: # ifdef CBVIRTTERM ! 1715: /* ! 1716: * Virtual terminals use ic, not im or ei. Turn ! 1717: * any of them into ic - duplicates will be cancelled ! 1718: * below. I assume that terminals needing im+ic+ei ! 1719: * are handled by the kernel. ! 1720: */ ! 1721: if (VirTermNo > 0 && !HasAM && ! 1722: (bp[1]=='i' && bp[2]=='m' || ! 1723: bp[1]=='e' && bp[2]=='i')) { ! 1724: bp[1] = 'i'; ! 1725: bp[2] = 'c'; ! 1726: } ! 1727: if (VirTermNo > 0 && !HasAM && ! 1728: (bp[1]=='c' && bp[2]=='s')) { ! 1729: bp[1] = 'd'; ! 1730: bp[2] = 'l'; ! 1731: /* Also need al, so kludge: */ ! 1732: if (!cancelled("al")) ! 1733: p = putbuf(p, ":al=\033\120"); ! 1734: } ! 1735: # endif CBVIRTTERM ! 1736: if (empty || cancelled(bp+1)) { ! 1737: bp = tp; ! 1738: continue; ! 1739: } ! 1740: # ifdef CBVIRTTERM ! 1741: if (VirTermNo > 0 && !HasAM) ! 1742: for (i = 0; vtab[i].value; i++) { ! 1743: if (vtab[i].cap[0] == bp[1] && ! 1744: vtab[i].cap[1] == bp[2]) { ! 1745: *p++ = *bp++; /* colon */ ! 1746: *p++ = *bp++; /* first char */ ! 1747: *p++ = *bp++; /* second " */ ! 1748: *p++ = *bp++; /* = sign */ ! 1749: p = putbuf(p, vtab[i].value); ! 1750: bp = tp; ! 1751: goto contin; ! 1752: } ! 1753: } ! 1754: # endif CBVIRTTERM ! 1755: break; ! 1756: ! 1757: case ' ': /* no spaces in output */ ! 1758: p = putbuf(p, "\\040"); ! 1759: bp++; ! 1760: continue; ! 1761: ! 1762: case '!': /* the shell thinks this is history */ ! 1763: p = putbuf(p, "\\041"); ! 1764: bp++; ! 1765: continue; ! 1766: ! 1767: case ',': /* the shell thinks this is history */ ! 1768: p = putbuf(p, "\\054"); ! 1769: bp++; ! 1770: continue; ! 1771: ! 1772: case '"': /* no quotes in output */ ! 1773: p = putbuf(p, "\\042"); ! 1774: bp++; ! 1775: continue; ! 1776: ! 1777: case '\'': /* no quotes in output */ ! 1778: p = putbuf(p, "\\047"); ! 1779: bp++; ! 1780: continue; ! 1781: ! 1782: case '`': /* no back quotes in output */ ! 1783: p = putbuf(p, "\\140"); ! 1784: bp++; ! 1785: continue; ! 1786: ! 1787: case '\\': ! 1788: case '^': /* anything following is OK */ ! 1789: *p++ = *bp++; ! 1790: # ifdef CBVIRTTERM ! 1791: if (*bp == 'E' && VirTermNo > 0 && ! 1792: (bp[-3]!='\\'||bp[-2]!='E') && ! 1793: (bp[1]!='\\'||bp[2]!='E')) ! 1794: p = putbuf(p, "E\\"); ! 1795: # endif CBVIRTTERM ! 1796: } ! 1797: *p++ = *bp++; ! 1798: contin: ; ! 1799: } ! 1800: *p++ = ':'; /* we skipped the last : with the : lookahead hack */ ! 1801: write (STDOUT, buf, p-buf); ! 1802: } ! 1803: ! 1804: cancelled(cap) ! 1805: char *cap; ! 1806: { ! 1807: register int i; ! 1808: ! 1809: for (i = 0; i < ncap; i++) ! 1810: { ! 1811: if (cap[0] == delcap[i][0] && cap[1] == delcap[i][1]) ! 1812: return (YES); ! 1813: } ! 1814: /* delete a second occurrance of the same capability */ ! 1815: delcap[ncap][0] = cap[0]; ! 1816: delcap[ncap][1] = cap[1]; ! 1817: ncap++; ! 1818: return (cap[2] == '@'); ! 1819: } ! 1820: ! 1821: char * ! 1822: putbuf(ptr, str) ! 1823: char *ptr; ! 1824: char *str; ! 1825: { ! 1826: char buf[20]; ! 1827: ! 1828: while (*str) { ! 1829: switch (*str) { ! 1830: case '\033': ! 1831: ptr = putbuf(ptr, "\\E"); ! 1832: str++; ! 1833: break; ! 1834: default: ! 1835: if (*str <= ' ') { ! 1836: sprintf(buf, "\\%03o", *str); ! 1837: ptr = putbuf(ptr, buf); ! 1838: str++; ! 1839: } else ! 1840: *ptr++ = *str++; ! 1841: } ! 1842: } ! 1843: return (ptr); ! 1844: } ! 1845: ! 1846: ! 1847: baudrate(p) ! 1848: char *p; ! 1849: { ! 1850: char buf[8]; ! 1851: int i = 0; ! 1852: ! 1853: while (i < 7 && (isalnum(*p) || *p == '.')) ! 1854: buf[i++] = *p++; ! 1855: buf[i] = NULL; ! 1856: for (i=0; speeds[i].string; i++) ! 1857: if (sequal(speeds[i].string, buf)) ! 1858: return (speeds[i].speed); ! 1859: return (-1); ! 1860: } ! 1861: ! 1862: char * ! 1863: mapped(type) ! 1864: char *type; ! 1865: { ! 1866: # ifdef V6 ! 1867: extern int ospeed; ! 1868: # else ! 1869: extern short ospeed; ! 1870: # endif ! 1871: int match; ! 1872: ! 1873: # ifdef DEB ! 1874: printf ("spd:%d\n", ospeed); ! 1875: prmap(); ! 1876: # endif ! 1877: Map = map; ! 1878: while (Map->Ident) ! 1879: { ! 1880: if (*(Map->Ident) == NULL || sequal(Map->Ident, type) || isalias(Map->Ident)) ! 1881: { ! 1882: match = NO; ! 1883: switch (Map->Test) ! 1884: { ! 1885: case ANY: /* no test specified */ ! 1886: case ALL: ! 1887: match = YES; ! 1888: break; ! 1889: ! 1890: case GT: ! 1891: match = (ospeed > Map->Speed); ! 1892: break; ! 1893: ! 1894: case GE: ! 1895: match = (ospeed >= Map->Speed); ! 1896: break; ! 1897: ! 1898: case EQ: ! 1899: match = (ospeed == Map->Speed); ! 1900: break; ! 1901: ! 1902: case LE: ! 1903: match = (ospeed <= Map->Speed); ! 1904: break; ! 1905: ! 1906: case LT: ! 1907: match = (ospeed < Map->Speed); ! 1908: break; ! 1909: ! 1910: case NE: ! 1911: match = (ospeed != Map->Speed); ! 1912: break; ! 1913: } ! 1914: if (match) ! 1915: return (Map->Type); ! 1916: } ! 1917: Map++; ! 1918: } ! 1919: /* no match found; return given type */ ! 1920: return (type); ! 1921: } ! 1922: ! 1923: # ifdef DEB ! 1924: prmap() ! 1925: { ! 1926: Map = map; ! 1927: while (Map->Ident) ! 1928: { ! 1929: printf ("%s t:%d s:%d %s\n", ! 1930: Map->Ident, Map->Test, Map->Speed, Map->Type); ! 1931: Map++; ! 1932: } ! 1933: } ! 1934: # endif ! 1935: ! 1936: char * ! 1937: nextarg(argc, argv) ! 1938: int argc; ! 1939: char *argv[]; ! 1940: { ! 1941: if (argc <= 0) ! 1942: fatal ("Too few args: ", *argv); ! 1943: if (*(*++argv) == '-') ! 1944: fatal ("Unexpected arg: ", *argv); ! 1945: return (*argv); ! 1946: } ! 1947: ! 1948: fatal (mesg, obj) ! 1949: char *mesg; ! 1950: char *obj; ! 1951: { ! 1952: prs (mesg); ! 1953: prs (obj); ! 1954: prc ('\n'); ! 1955: prs (USAGE); ! 1956: flush(); ! 1957: exit(1); ! 1958: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.