|
|
1.1 ! root 1: /* ! 2: # define DEB ! 3: /* ! 4: ** TSET -- set terminal modes ! 5: ** ! 6: ** This program does sophisticated terminal initialization. ! 7: ** I recommend that you include it in your .start_up or .login ! 8: ** file to initialize whatever terminal you are on. ! 9: ** ! 10: ** There are several features: ! 11: ** ! 12: ** A special file or sequence (as controlled by the ttycap file) ! 13: ** is sent to the terminal. ! 14: ** ! 15: ** Mode bits are set on a per-terminal_type basis (much better ! 16: ** than UNIX itself). This allows special delays, automatic ! 17: ** tabs, etc. ! 18: ** ! 19: ** Erase and Kill characters can be set to whatever you want. ! 20: ** Default is to change erase to control-H on a terminal which ! 21: ** can overstrike, and leave it alone on anything else. Kill ! 22: ** is always left alone unless specifically requested. These ! 23: ** characters can be represented as "^X" meaning control-X; ! 24: ** X is any character. ! 25: ** ! 26: ** Terminals which are dialups or plugboard types can be aliased ! 27: ** to whatever type you may have in your home or office. Thus, ! 28: ** if you know that when you dial up you will always be on a ! 29: ** TI 733, you can specify that fact to tset. You can represent ! 30: ** a type as "?type". This will ask you what type you want it ! 31: ** to be -- if you reply with just a newline, it will default ! 32: ** to the type given. ! 33: ** ! 34: ** The htmp file, used by ex, etc., can be updated. ! 35: ** ! 36: ** The current terminal type can be queried. ! 37: ** ! 38: ** Usage: ! 39: ** tset [-] [-EC] [-eC] [-kC] [-s] [-h] [-u] [-r] ! 40: ** [-m [ident] [test baudrate] :type] ! 41: ** [-Q] [-I] [-S] [type] ! 42: ** ! 43: ** In systems with environments, use: ! 44: ** `tset -s ...` ! 45: ** Actually, this doesn't work because of a shell bug. ! 46: ** Instead, use: ! 47: ** tset -s ... > tset.tmp ! 48: ** source tset.tmp ! 49: ** rm tset.tmp ! 50: ** or: ! 51: ** set noglob ! 52: ** set term=(`tset -S ....`) ! 53: ** setenv TERM $term[1] ! 54: ** setenv TERMCAP "$term[2]" ! 55: ** unset term ! 56: ** unset noglob ! 57: ** ! 58: ** Positional Parameters: ! 59: ** type -- the terminal type to force. If this is ! 60: ** specified, initialization is for this ! 61: ** terminal type. ! 62: ** ! 63: ** Flags: ! 64: ** - -- report terminal type. Whatever type is ! 65: ** decided on is reported. If no other flags ! 66: ** are stated, the only affect is to write ! 67: ** the terminal type on the standard output. ! 68: ** -r -- report to user in addition to other flags. ! 69: ** -EC -- set the erase character to C on all terminals ! 70: ** except those which cannot backspace (e.g., ! 71: ** a TTY 33). C defaults to control-H. ! 72: ** -eC -- set the erase character to C on all terminals. ! 73: ** C defaults to control-H. If neither -E or -e ! 74: ** are specified, the erase character is set to ! 75: ** control-H if the terminal can both backspace ! 76: ** and not overstrike (e.g., a CRT). If the erase ! 77: ** character is NULL (zero byte), it will be reset ! 78: ** to '#' if nothing else is specified. ! 79: ** -kC -- set the kill character to C on all terminals. ! 80: ** Default for C is control-X. If not specified, ! 81: ** the kill character is untouched; however, if ! 82: ** not specified and the kill character is NULL ! 83: ** (zero byte), the kill character is set to '@'. ! 84: ** -iC -- reserved for setable interrupt character. ! 85: ** -qC -- reserved for setable quit character. ! 86: ** -m -- map the system identified type to some user ! 87: ** specified type. The mapping can be baud rate ! 88: ** dependent. This replaces the old -d, -p flags. ! 89: ** (-d type -> -m dialup:type) ! 90: ** (-p type -> -m plug:type) ! 91: ** Syntax: -m identifier [test baudrate] :type ! 92: ** where: ``identifier'' is whatever is found in ! 93: ** /etc/ttytype for this port, (abscence of an identifier ! 94: ** matches any identifier); ``test'' may be any combination ! 95: ** of > = < ! @; ``baudrate'' is as with stty(1); ! 96: ** ``type'' is the actual terminal type to use if the ! 97: ** mapping condition is met. Multiple maps are scanned ! 98: ** in order and the first match prevails. ! 99: ** -h -- don't read htmp file. Normally the terminal type ! 100: ** is determined by reading the htmp file or the ! 101: ** environment (unless some mapping is specified). ! 102: ** This forces a read of the ttytype file -- useful ! 103: ** when htmp is somehow wrong. ! 104: ** -u -- don't update htmp. It seemed like this should ! 105: ** be put in. Note that htmp is never actually ! 106: ** written if there are no changes, so don't bother ! 107: ** bother using this for efficiency reasons alone. ! 108: ** -s -- output setenv commands for TERM. This can be ! 109: ** used with ! 110: ** `tset -s ...` ! 111: ** and is to be prefered to: ! 112: ** setenv TERM `tset - ...` ! 113: ** because -s sets the TERMCAP variable also. ! 114: ** -S -- Similar to -s but outputs 2 strings suitable for ! 115: ** use in csh .login files as follows: ! 116: ** set noglob ! 117: ** set term=(`tset -S .....`) ! 118: ** setenv TERM $term[1] ! 119: ** setenv TERMCAP "$term[2]" ! 120: ** unset term ! 121: ** unset noglob ! 122: ** -Q -- be quiet. don't output 'Erase set to' etc. ! 123: ** -I -- don't do terminal initialization (is & if ! 124: ** strings). ! 125: ** ! 126: ** Files: ! 127: ** /etc/ttytype ! 128: ** contains a terminal id -> terminal type ! 129: ** mapping; used when any user mapping is specified, ! 130: ** or the environment doesn't have TERM set. ! 131: ** /etc/termcap ! 132: ** a terminal_type -> terminal_capabilities ! 133: ** mapping. ! 134: ** ! 135: ** Return Codes: ! 136: ** -1 -- couldn't open ttycap. ! 137: ** 1 -- bad terminal type, or standard output not tty. ! 138: ** 0 -- ok. ! 139: ** ! 140: ** Defined Constants: ! 141: ** DIALUP -- the type code for a dialup port ! 142: ** PLUGBOARD -- the code for a plugboard port. ! 143: ** ARPANET -- the code for an arpanet port. ! 144: ** BACKSPACE -- control-H, the default for -e. ! 145: ** CONTROLX -- control-X, the default for -k. ! 146: ** OLDERASE -- the system default erase character. ! 147: ** OLDKILL -- the system default kill character. ! 148: ** FILEDES -- the file descriptor to do the operation ! 149: ** on, nominally 1 or 2. ! 150: ** STDOUT -- the standard output file descriptor. ! 151: ** UIDMASK -- the bit pattern to mask with the getuid() ! 152: ** call to get just the user id. ! 153: ** GTTYN -- defines file containing generalized ttynames ! 154: ** and compiles code to look there. ! 155: ** ! 156: ** Requires: ! 157: ** Routines to handle htmp, ttytype, and ttycap. ! 158: ** ! 159: ** Compilation Flags: ! 160: ** OLDDIALUP -- accept the -d flag. Map "sd" to "dialup". ! 161: ** OLDPLUGBOARD -- accept the -p flag. Map "sp" to "plugboard". ! 162: ** OLDARPANET -- accept the -a flag. Map "sa" to "arpanet". ! 163: ** OLDFLAGS -- must be defined to compile code for any of ! 164: ** the -d, -p, or -a flags. ! 165: ** FULLLOGIN -- if defined, login sets the ttytype from ! 166: ** /etc/ttytype file. ! 167: ** V6 -- if clear, use environments, not htmp. ! 168: ** also use TIOCSETN rather than stty to avoid flushing ! 169: ** GTTYN -- if set, compiles code to look at /etc/ttytype. ! 170: ** ! 171: ** Trace Flags: ! 172: ** none ! 173: ** ! 174: ** Diagnostics: ! 175: ** Bad flag ! 176: ** An incorrect option was specified. ! 177: ** Too few args ! 178: ** more command line arguments are required. ! 179: ** Unexpected arg ! 180: ** wrong type of argument was encountered. ! 181: ** Cannot open ... ! 182: ** The specified file could not be openned. ! 183: ** Type ... unknown ! 184: ** An unknown terminal type was specified. ! 185: ** Cannot update htmp ! 186: ** Cannot update htmp file when the standard ! 187: ** output is not a terminal. ! 188: ** Erase set to ... ! 189: ** Telling that the erase character has been ! 190: ** set to the specified character. ! 191: ** Kill set to ... ! 192: ** Ditto for kill ! 193: ** Erase is ... Kill is ... ! 194: ** Tells that the erase/kill characters were ! 195: ** wierd before, but they are being left as-is. ! 196: ** Not a terminal ! 197: ** Set if FILEDES is not a terminal. ! 198: ** ! 199: ** Compilation Instructions: ! 200: ** cc -n -O tset.c -ltermlib ! 201: ** mv a.out tset ! 202: ** chown bin tset ! 203: ** chmod 4755 tset ! 204: ** ! 205: ** where 'bin' should be whoever owns the 'htmp' file. ! 206: ** If 'htmp' is 666, then tset need not be setuid. ! 207: ** ! 208: ** Author: ! 209: ** Eric Allman ! 210: ** Electronics Research Labs ! 211: ** U.C. Berkeley ! 212: ** ! 213: ** History: ! 214: ** 7/80 -- '-S' added. -m mapping added. TERMCAP string ! 215: ** cleaned up. ! 216: ** 3/80 -- Changed to use tputs. Prc & flush added. ! 217: ** 10/79 -- '-s' option extended to handle TERMCAP ! 218: ** variable, set noglob, quote the entry, ! 219: ** and know about the Bourne shell. Terminal ! 220: ** initialization moved to before any information ! 221: ** output so screen clears would not screw you. ! 222: ** '-Q' option added. ! 223: ** 8/79 -- '-' option alone changed to only output ! 224: ** type. '-s' option added. 'VERSION7' ! 225: ** changed to 'V6' for compatibility. ! 226: ** 12/78 -- modified for eventual migration to VAX/UNIX, ! 227: ** so the '-' option is changed to output only ! 228: ** the terminal type to STDOUT instead of ! 229: ** FILEDES. FULLLOGIN flag added. ! 230: ** 9/78 -- '-' and '-p' options added (now fully ! 231: ** compatible with ttytype!), and spaces are ! 232: ** permitted between the -d and the type. ! 233: ** 8/78 -- The sense of -h and -u were reversed, and the ! 234: ** -f flag is dropped -- same effect is available ! 235: ** by just stating the terminal type. ! 236: ** 10/77 -- Written. ! 237: */ ! 238: ! 239: /* ! 240: # define FULLLOGIN 1 ! 241: */ ! 242: # ifndef V6 ! 243: # define GTTYN "/etc/ttytype" ! 244: # endif ! 245: ! 246: # include <ctype.h> ! 247: # include <sgtty.h> ! 248: # include <stdio.h> ! 249: ! 250: # define BACKSPACE ('H' & 037) ! 251: # define CONTROLX ('X' & 037) ! 252: # define OLDERASE '#' ! 253: # define OLDKILL '@' ! 254: ! 255: # define FILEDES 2 ! 256: # define STDOUT 1 ! 257: ! 258: # ifdef V6 ! 259: # define UIDMASK 0377 ! 260: # else ! 261: # define UIDMASK -1 ! 262: # endif ! 263: ! 264: # define DEFTYPE "unknown" ! 265: # define USAGE\ ! 266: "usage: tset [-] [-hrsuIQS] [-eC] [-kC] [-m [ident][test speed]:type] [type]\n" ! 267: ! 268: # define DIALUP "dialup" ! 269: # define OLDDIALUP "sd" ! 270: # define PLUGBOARD "plugboard" ! 271: # define OLDPLUGBOARD "sp" ! 272: /*** ! 273: # define ARPANET "arpanet" ! 274: # define OLDARPANET "sa" ! 275: ***/ ! 276: # define OLDFLAGS ! 277: ! 278: ! 279: ! 280: # ifdef GTTYN ! 281: typedef char *ttyid_t; ! 282: # define NOTTY 0 ! 283: # else ! 284: typedef char ttyid_t; ! 285: # define NOTTY 'x' ! 286: # endif ! 287: ! 288: /* ! 289: * Baud Rate Conditionals ! 290: */ ! 291: # define ANY 0 ! 292: # define GT 1 ! 293: # define EQ 2 ! 294: # define LT 4 ! 295: # define GE (GT|EQ) ! 296: # define LE (LT|EQ) ! 297: # define NE (GT|LT) ! 298: # define ALL (GT|EQ|LT) ! 299: ! 300: ! 301: ! 302: # define NMAP 10 ! 303: ! 304: struct map { ! 305: char *Ident; ! 306: char Test; ! 307: char Speed; ! 308: char *Type; ! 309: } map[NMAP]; ! 310: ! 311: struct map *Map = map; ! 312: ! 313: struct ! 314: { ! 315: char *string; ! 316: int speed; ! 317: } speeds[] = { ! 318: "0", B0, ! 319: "50", B50, ! 320: "75", B75, ! 321: "110", B110, ! 322: "134", B134, ! 323: "134.5",B134, ! 324: "150", B150, ! 325: "200", B200, ! 326: "300", B300, ! 327: "600", B600, ! 328: "1200", B1200, ! 329: "1800", B1800, ! 330: "2400", B2400, ! 331: "4800", B4800, ! 332: "9600", B9600, ! 333: "exta", EXTA, ! 334: "extb", EXTB, ! 335: 0, ! 336: }; ! 337: ! 338: char Erase_char; /* new erase character */ ! 339: char Kill_char; /* new kill character */ ! 340: char Specialerase; /* set => Erase_char only on terminals with backspace */ ! 341: ! 342: ttyid_t Ttyid = NOTTY; /* terminal identifier */ ! 343: char *TtyType; /* type of terminal */ ! 344: char *DefType; /* default type if none other computed */ ! 345: char *NewType; /* mapping identifier based on old flags */ ! 346: int Dash_u; /* don't update htmp */ ! 347: int Dash_h; /* don't read htmp */ ! 348: int DoSetenv; /* output setenv commands */ ! 349: int BeQuiet; /* be quiet */ ! 350: int NoInit; /* don't output initialization string */ ! 351: int Report; /* report current type */ ! 352: int Ureport; /* report to user */ ! 353: int RepOnly; /* report only */ ! 354: int CmndLine; /* output full command lines (-s option) */ ! 355: int Ask; /* ask user for termtype */ ! 356: ! 357: # define CAPBUFSIZ 1024 ! 358: char Capbuf[CAPBUFSIZ]; /* line from /etc/termcap for this TtyType */ ! 359: char *Ttycap; /* termcap line from termcap or environ */ ! 360: ! 361: struct delay ! 362: { ! 363: int d_delay; ! 364: int d_bits; ! 365: }; ! 366: ! 367: # include "tset.delays.h" ! 368: ! 369: ! 370: ! 371: main(argc, argv) ! 372: int argc; ! 373: char *argv[]; ! 374: { ! 375: struct sgttyb mode; ! 376: struct sgttyb oldmode; ! 377: char buf[256]; ! 378: auto char *bufp; ! 379: register char *p; ! 380: char *command; ! 381: register int i; ! 382: int Break; ! 383: int Not; ! 384: int Mapped; ! 385: extern char *nextarg(); ! 386: extern char *mapped(); ! 387: # ifdef V6 ! 388: extern char *hsgettype(); ! 389: # else ! 390: extern char *getenv(); ! 391: # endif ! 392: # ifdef GTTYN ! 393: extern char *stypeof(); ! 394: extern char *ttyname(); ! 395: extern char *tgetstr(); ! 396: # endif ! 397: char bs_char; ! 398: int csh; ! 399: extern prc(); ! 400: extern char PC; ! 401: extern short ospeed; ! 402: ! 403: if (gtty(FILEDES, &mode) < 0) ! 404: { ! 405: prs("Not a terminal\n"); ! 406: exit(1); ! 407: } ! 408: bmove(&mode, &oldmode, sizeof mode); ! 409: ospeed = mode.sg_ospeed; ! 410: ! 411: /* scan argument list and collect flags */ ! 412: command = argv[0]; ! 413: if (argc == 2 && argv[1][0] == '-' && argv[1][1] == '\0') ! 414: { ! 415: RepOnly++; ! 416: Dash_u++; ! 417: } ! 418: argc--; ! 419: while (--argc >= 0) ! 420: { ! 421: p = *++argv; ! 422: if (*p == '-') ! 423: { ! 424: if (*++p == NULL) ! 425: Report++; /* report current terminal type */ ! 426: else while (*p) switch (*p++) ! 427: { ! 428: ! 429: case 'r': /* report to user */ ! 430: Ureport++; ! 431: continue; ! 432: ! 433: case 'E': /* special erase: operate on all but TTY33 */ ! 434: Specialerase++; ! 435: /* explicit fall-through to -e case */ ! 436: ! 437: case 'e': /* erase character */ ! 438: if (*p == NULL) ! 439: Erase_char = -1; ! 440: else ! 441: { ! 442: if (*p == '^' && p[1] != NULL) ! 443: Erase_char = *++p & 037; ! 444: else ! 445: Erase_char = *p; ! 446: p++; ! 447: } ! 448: continue; ! 449: ! 450: case 'k': /* kill character */ ! 451: if (*p == NULL) ! 452: Kill_char = CONTROLX; ! 453: else ! 454: { ! 455: if (*p == '^' && p[1] != NULL) ! 456: Kill_char = *++p & 037; ! 457: else ! 458: Kill_char = *p; ! 459: p++; ! 460: } ! 461: continue; ! 462: ! 463: # ifdef OLDFLAGS ! 464: # ifdef OLDDIALUP ! 465: case 'd': /* dialup type */ ! 466: NewType = DIALUP; ! 467: goto mapold; ! 468: # endif ! 469: ! 470: # ifdef OLDPLUGBOARD ! 471: case 'p': /* plugboard type */ ! 472: NewType = PLUGBOARD; ! 473: goto mapold; ! 474: # endif ! 475: ! 476: # ifdef OLDARPANET ! 477: case 'a': /* arpanet type */ ! 478: Newtype = ARPANET; ! 479: goto mapold; ! 480: # endif ! 481: ! 482: mapold: Map->Ident = NewType; ! 483: Map->Test = ALL; ! 484: if (*p == NULL) ! 485: { ! 486: p = nextarg(argc--, argv++); ! 487: } ! 488: Map->Type = p; ! 489: Map++; ! 490: Mapped++; ! 491: p = ""; ! 492: continue; ! 493: # endif ! 494: ! 495: case 'm': /* map identifier to type */ ! 496: /* This code is very loose. Almost no ! 497: ** syntax checking is done!! However, ! 498: ** illegal syntax will only produce ! 499: ** weird results. ! 500: */ ! 501: if (*p == NULL) ! 502: { ! 503: p = nextarg(argc--, argv++); ! 504: } ! 505: if (isalnum(*p)) ! 506: { ! 507: Map->Ident = p; /* identifier */ ! 508: while (isalnum(*p)) p++; ! 509: } ! 510: else ! 511: Map->Ident = ""; ! 512: Break = 0; ! 513: Not = 0; ! 514: while (!Break) switch (*p) ! 515: { ! 516: case NULL: ! 517: p = nextarg(argc--, argv++); ! 518: continue; ! 519: ! 520: case ':': /* mapped type */ ! 521: *p++ = NULL; ! 522: Break++; ! 523: continue; ! 524: ! 525: case '>': /* conditional */ ! 526: Map->Test |= GT; ! 527: *p++ = NULL; ! 528: continue; ! 529: ! 530: case '<': /* conditional */ ! 531: Map->Test |= LT; ! 532: *p++ = NULL; ! 533: continue; ! 534: ! 535: case '=': /* conditional */ ! 536: case '@': ! 537: Map->Test |= EQ; ! 538: *p++ = NULL; ! 539: continue; ! 540: ! 541: case '!': /* invert conditions */ ! 542: Not = ~Not; ! 543: *p++ = NULL; ! 544: continue; ! 545: ! 546: case 'B': /* Baud rate */ ! 547: p++; ! 548: /* intentional fallthru */ ! 549: default: ! 550: if (isdigit(*p) || *p == 'e') ! 551: { ! 552: Map->Speed = baudrate(p); ! 553: while (isalnum(*p) || *p == '.') ! 554: p++; ! 555: } ! 556: else ! 557: Break++; ! 558: continue; ! 559: } ! 560: if (Not) /* invert sense of test */ ! 561: { ! 562: Map->Test = (~(Map->Test))&ALL; ! 563: } ! 564: if (*p == NULL) ! 565: { ! 566: p = nextarg(argc--, argv++); ! 567: } ! 568: Map->Type = p; ! 569: p = ""; ! 570: Map++; ! 571: Mapped++; ! 572: continue; ! 573: ! 574: case 'h': /* don't get type from htmp or env */ ! 575: Dash_h++; ! 576: continue; ! 577: ! 578: case 'u': /* don't update htmp */ ! 579: Dash_u++; ! 580: continue; ! 581: ! 582: case 's': /* output setenv commands */ ! 583: DoSetenv++; ! 584: CmndLine++; ! 585: continue; ! 586: ! 587: case 'S': /* output setenv strings */ ! 588: DoSetenv++; ! 589: CmndLine=0; ! 590: continue; ! 591: ! 592: case 'Q': /* be quiet */ ! 593: BeQuiet++; ! 594: continue; ! 595: ! 596: case 'I': /* no initialization */ ! 597: NoInit++; ! 598: continue; ! 599: ! 600: case 'A': /* Ask user */ ! 601: Ask++; ! 602: continue; ! 603: ! 604: default: ! 605: *p-- = NULL; ! 606: fatal("Bad flag -", p); ! 607: } ! 608: } ! 609: else ! 610: { ! 611: /* terminal type */ ! 612: DefType = p; ! 613: } ! 614: } ! 615: ! 616: if (DefType) ! 617: { ! 618: if (Mapped) ! 619: { ! 620: Map->Ident = ""; /* means "map any type" */ ! 621: Map->Test = ALL; /* at all baud rates */ ! 622: Map->Type = DefType; /* to the default type */ ! 623: } ! 624: else ! 625: TtyType = DefType; ! 626: } ! 627: ! 628: # ifndef V6 ! 629: /* get current idea of terminal type from environment */ ! 630: if (!Dash_h && !Mapped && TtyType == 0) ! 631: TtyType = getenv("TERM"); ! 632: # endif ! 633: ! 634: /* determine terminal id if needed */ ! 635: # ifdef V6 ! 636: if (Ttyid == NOTTY && (TtyType == 0 || !Dash_h || !Dash_u)) ! 637: Ttyid = ttyn(FILEDES); ! 638: # else ! 639: if (!RepOnly && Ttyid == NOTTY && (TtyType == 0 || !Dash_h)) ! 640: Ttyid = ttyname(FILEDES); ! 641: # endif ! 642: ! 643: # ifdef V6 ! 644: /* get htmp if ever used */ ! 645: if (!Dash_u || (TtyType == 0 && !Dash_h)) ! 646: { ! 647: /* get htmp entry -- if error or wrong user use ttytype */ ! 648: if (Ttyid == NOTTY || hget(Ttyid) < 0 || ! 649: hgettype() == 0 || hgetuid() != (getuid() & UIDMASK)) ! 650: Dash_h++; ! 651: } ! 652: ! 653: /* find terminal type (if not already known) */ ! 654: if (TtyType == 0 && !Dash_h) ! 655: { ! 656: /* get type from /etc/htmp */ ! 657: TtyType = hsgettype(); ! 658: } ! 659: # endif ! 660: ! 661: # ifdef GTTYN ! 662: /* If still undefined, look at /etc/ttytype */ ! 663: if (TtyType == 0) ! 664: { ! 665: TtyType = stypeof(Ttyid); ! 666: } ! 667: # endif ! 668: ! 669: /* If still undefined, use DEFTYPE */ ! 670: if (TtyType == 0) ! 671: { ! 672: TtyType = DEFTYPE; ! 673: } ! 674: ! 675: /* check for dialup or other mapping */ ! 676: if (Mapped) ! 677: TtyType = mapped(TtyType, ospeed); ! 678: ! 679: /* TtyType now contains a pointer to the type of the terminal */ ! 680: /* If the first character is '?', ask the user */ ! 681: if (TtyType[0] == '?') ! 682: { ! 683: Ask++; ! 684: TtyType++; ! 685: if (TtyType[0] == '\0') ! 686: TtyType = DEFTYPE; ! 687: } ! 688: if (Ask) ! 689: { ! 690: prs("TERM = ("); ! 691: prs(TtyType); ! 692: prs(") "); ! 693: flush(); ! 694: ! 695: /* read the terminal. If not empty, set type */ ! 696: i = read(2, buf, sizeof buf - 1); ! 697: if (i >= 0) ! 698: { ! 699: if (buf[i - 1] == '\n') ! 700: i--; ! 701: buf[i] = '\0'; ! 702: if (buf[0] != '\0') ! 703: TtyType = buf; ! 704: } ! 705: } ! 706: ! 707: if (Ttycap == 0) ! 708: { ! 709: /* get terminal capabilities */ ! 710: switch (tgetent(Capbuf, TtyType)) ! 711: { ! 712: case -1: ! 713: prs("Cannot open termcap file\n"); ! 714: flush(); ! 715: exit(-1); ! 716: ! 717: case 0: ! 718: prs("Type "); ! 719: prs(TtyType); ! 720: prs(" unknown\n"); ! 721: flush(); ! 722: exit(1); ! 723: } ! 724: Ttycap = Capbuf; ! 725: } ! 726: ! 727: if (!RepOnly) ! 728: { ! 729: /* determine erase and kill characters */ ! 730: if (Specialerase && !tgetflag("bs")) ! 731: Erase_char = 0; ! 732: bufp = buf; ! 733: p = tgetstr("kb", &bufp); ! 734: if (p == NULL || p[1] != '\0') ! 735: p = tgetstr("bc", &bufp); ! 736: if (p != NULL && p[1] == '\0') ! 737: bs_char = p[0]; ! 738: else if (tgetflag("bs")) ! 739: bs_char = BACKSPACE; ! 740: else ! 741: bs_char = 0; ! 742: if (Erase_char == 0 && !tgetflag("os") && mode.sg_erase == OLDERASE) ! 743: { ! 744: if (tgetflag("bs") || bs_char != 0) ! 745: Erase_char = -1; ! 746: } ! 747: if (Erase_char < 0) ! 748: Erase_char = (bs_char != 0) ? bs_char : BACKSPACE; ! 749: ! 750: if (mode.sg_erase == 0) ! 751: mode.sg_erase = OLDERASE; ! 752: if (Erase_char != 0) ! 753: mode.sg_erase = Erase_char; ! 754: ! 755: if (mode.sg_kill == 0) ! 756: mode.sg_kill = OLDKILL; ! 757: if (Kill_char != 0) ! 758: mode.sg_kill = Kill_char; ! 759: ! 760: /* set modes */ ! 761: setdelay("dC", CRdelay, CRbits, &mode.sg_flags); ! 762: setdelay("dN", NLdelay, NLbits, &mode.sg_flags); ! 763: setdelay("dB", BSdelay, BSbits, &mode.sg_flags); ! 764: setdelay("dF", FFdelay, FFbits, &mode.sg_flags); ! 765: setdelay("dT", TBdelay, TBbits, &mode.sg_flags); ! 766: if (tgetflag("UC") || command[0] == 'T') ! 767: mode.sg_flags |= LCASE; ! 768: else if (tgetflag("LC")) ! 769: mode.sg_flags &= ~LCASE; ! 770: mode.sg_flags &= ~(EVENP | ODDP | RAW); ! 771: # ifndef V6 ! 772: mode.sg_flags &= ~CBREAK; ! 773: # endif ! 774: if (tgetflag("EP")) ! 775: mode.sg_flags |= EVENP; ! 776: if (tgetflag("OP")) ! 777: mode.sg_flags |= ODDP; ! 778: if ((mode.sg_flags & (EVENP | ODDP)) == 0) ! 779: mode.sg_flags |= EVENP | ODDP; ! 780: mode.sg_flags |= CRMOD | ECHO | XTABS; ! 781: if (tgetflag("NL")) /* new line, not line feed */ ! 782: mode.sg_flags &= ~CRMOD; ! 783: if (tgetflag("HD")) /* half duplex */ ! 784: mode.sg_flags &= ~ECHO; ! 785: if (tgetflag("pt")) /* print tabs */ ! 786: mode.sg_flags &= ~XTABS; ! 787: if (!bequal(&mode, &oldmode, sizeof mode)) ! 788: # ifndef V6 ! 789: ioctl(FILEDES, TIOCSETN, &mode); ! 790: # else ! 791: stty(FILEDES, &mode); ! 792: # endif ! 793: ! 794: /* get pad character */ ! 795: bufp = buf; ! 796: if (tgetstr("pc", &bufp) != 0) ! 797: PC = buf[0]; ! 798: ! 799: /* output startup string */ ! 800: if (!NoInit) ! 801: { ! 802: bufp = buf; ! 803: if (tgetstr("is", &bufp) != 0) ! 804: tputs(buf, 0, prc); ! 805: flush(); ! 806: bufp = buf; ! 807: if (tgetstr("if", &bufp) != 0) ! 808: cat(buf); ! 809: sleep(1); /* let terminal settle down */ ! 810: } ! 811: ! 812: /* set up environment for the shell we are using */ ! 813: /* (this code is rather heuristic) */ ! 814: csh = 0; ! 815: if (DoSetenv) ! 816: { ! 817: # ifndef V6 ! 818: char *sh; ! 819: ! 820: if ((sh = getenv("SHELL")) && (i = strlen(sh)) >= 3) ! 821: { ! 822: p = &sh[i-3]; ! 823: if ((csh = sequal(p, "csh")) && CmndLine) ! 824: write(STDOUT, "set noglob;\n", 12); ! 825: } ! 826: if (!csh) ! 827: # endif ! 828: /* running system shell */ ! 829: write(STDOUT, "export TERMCAP TERM;\n", 21); ! 830: } ! 831: } ! 832: ! 833: /* report type if appropriate */ ! 834: if (DoSetenv || Report || Ureport) ! 835: { ! 836: /* find first alias (if any) */ ! 837: for (p = Ttycap; *p != 0 && *p != '|' && *p != ':'; p++) ! 838: continue; ! 839: if (*p == 0 || *p == ':') ! 840: p = Ttycap; ! 841: else ! 842: p++; ! 843: bufp = p; ! 844: while (*p != '|' && *p != ':' && *p != 0) ! 845: p++; ! 846: i = *p; ! 847: if (DoSetenv) ! 848: { ! 849: if (csh) ! 850: { ! 851: if (CmndLine) ! 852: write(STDOUT, "setenv TERM ", 12); ! 853: write(STDOUT, bufp, p - bufp); ! 854: write(STDOUT, " ", 1); ! 855: if (CmndLine) ! 856: write(STDOUT, ";\n", 2); ! 857: } ! 858: else ! 859: { ! 860: write(STDOUT, "TERM=", 5); ! 861: write(STDOUT, bufp, p - bufp); ! 862: write(STDOUT, ";\n", 2); ! 863: } ! 864: } ! 865: if (Report && !DoSetenv) ! 866: { ! 867: write(STDOUT, bufp, p - bufp); ! 868: write(STDOUT, "\n", 1); ! 869: } ! 870: if (Ureport) ! 871: { ! 872: *p = '\0'; ! 873: prs("Terminal type is "); ! 874: prs(bufp); ! 875: prs("\n"); ! 876: flush(); ! 877: } ! 878: *p = i; ! 879: if (DoSetenv) ! 880: { ! 881: if (csh) ! 882: { ! 883: if (CmndLine) ! 884: write(STDOUT, "setenv TERMCAP '", 16); ! 885: } ! 886: else ! 887: write(STDOUT, "TERMCAP='", 9); ! 888: wrtermcap(Ttycap); ! 889: if (csh) ! 890: { ! 891: if (CmndLine) ! 892: { ! 893: write(STDOUT, "';\n", 3); ! 894: write(STDOUT, "unset noglob;\n", 14); ! 895: } ! 896: } ! 897: else ! 898: write(STDOUT, "';\n", 3); ! 899: } ! 900: } ! 901: ! 902: if (RepOnly) ! 903: exit(0); ! 904: ! 905: /* tell about changing erase and kill characters */ ! 906: reportek("Erase", mode.sg_erase, oldmode.sg_erase, OLDERASE); ! 907: reportek("Kill", mode.sg_kill, oldmode.sg_kill, OLDKILL); ! 908: ! 909: # ifdef V6 ! 910: /* update htmp */ ! 911: if (!Dash_u) ! 912: { ! 913: if (Ttyid == 0) ! 914: Ttyid = ttyn(FILEDES); ! 915: if (Ttyid == 'x') ! 916: { ! 917: prs("Cannot update htmp\n"); ! 918: flush(); ! 919: } ! 920: else ! 921: { ! 922: /* update htmp file only if changed */ ! 923: if (!bequal(Capbuf, hsgettype(), 2)) ! 924: { ! 925: hsettype(Capbuf[0] | (Capbuf[1] << 8)); ! 926: hput(Ttyid); ! 927: } ! 928: } ! 929: } ! 930: # endif ! 931: ! 932: exit(0); ! 933: } ! 934: ! 935: reportek(name, new, old, def) ! 936: char *name; ! 937: char old; ! 938: char new; ! 939: char def; ! 940: { ! 941: register char o; ! 942: register char n; ! 943: register char *p; ! 944: ! 945: if (BeQuiet) ! 946: return; ! 947: o = old; ! 948: n = new; ! 949: ! 950: if (o == n && n == def) ! 951: return; ! 952: prs(name); ! 953: if (o == n) ! 954: prs(" is "); ! 955: else ! 956: prs(" set to "); ! 957: if (n < 040) ! 958: { ! 959: prs("control-"); ! 960: n = (n & 037) | 0100; ! 961: } ! 962: p = "x\n"; ! 963: p[0] = n; ! 964: prs(p); ! 965: flush(); ! 966: } ! 967: ! 968: ! 969: ! 970: ! 971: setdelay(cap, dtab, bits, flags) ! 972: char *cap; ! 973: struct delay dtab[]; ! 974: int bits; ! 975: int *flags; ! 976: { ! 977: register int i; ! 978: register struct delay *p; ! 979: ! 980: /* see if this capability exists at all */ ! 981: i = tgetnum(cap); ! 982: if (i < 0) ! 983: i = 0; ! 984: ! 985: /* clear out the bits, replace with new ones */ ! 986: *flags &= ~bits; ! 987: ! 988: /* scan dtab for first entry with adequate delay */ ! 989: for (p = dtab; p->d_delay >= 0; p++) ! 990: { ! 991: if (p->d_delay >= i) ! 992: { ! 993: p++; ! 994: break; ! 995: } ! 996: } ! 997: ! 998: /* use last entry if none will do */ ! 999: *flags |= (--p)->d_bits; ! 1000: } ! 1001: ! 1002: ! 1003: prs(s) ! 1004: char *s; ! 1005: { ! 1006: while (*s != '\0') ! 1007: prc(*s++); ! 1008: } ! 1009: ! 1010: ! 1011: char OutBuf[256]; ! 1012: int OutPtr; ! 1013: ! 1014: prc(c) ! 1015: char c; ! 1016: { ! 1017: OutBuf[OutPtr++] = c; ! 1018: if (OutPtr >= sizeof OutBuf) ! 1019: flush(); ! 1020: } ! 1021: ! 1022: flush() ! 1023: { ! 1024: if (OutPtr > 0) ! 1025: write(2, OutBuf, OutPtr); ! 1026: OutPtr = 0; ! 1027: } ! 1028: ! 1029: ! 1030: cat(file) ! 1031: char *file; ! 1032: { ! 1033: register int fd; ! 1034: register int i; ! 1035: char buf[BUFSIZ]; ! 1036: ! 1037: fd = open(file, 0); ! 1038: if (fd < 0) ! 1039: { ! 1040: prs("Cannot open "); ! 1041: prs(file); ! 1042: prs("\n"); ! 1043: flush(); ! 1044: exit(-1); ! 1045: } ! 1046: ! 1047: flush(); ! 1048: while ((i = read(fd, buf, BUFSIZ)) > 0) ! 1049: write(FILEDES, buf, i); ! 1050: ! 1051: close(fd); ! 1052: } ! 1053: ! 1054: ! 1055: ! 1056: bmove(from, to, length) ! 1057: char *from; ! 1058: char *to; ! 1059: int length; ! 1060: { ! 1061: register char *p, *q; ! 1062: register int i; ! 1063: ! 1064: i = length; ! 1065: p = from; ! 1066: q = to; ! 1067: ! 1068: while (i-- > 0) ! 1069: *q++ = *p++; ! 1070: } ! 1071: ! 1072: ! 1073: ! 1074: bequal(a, b, len) ! 1075: char *a; ! 1076: char *b; ! 1077: int len; ! 1078: { ! 1079: register char *p, *q; ! 1080: register int i; ! 1081: ! 1082: i = len; ! 1083: p = a; ! 1084: q = b; ! 1085: ! 1086: while (*p && *q && (*p == *q) && --i > 0) ! 1087: { ! 1088: p++; q++; ! 1089: } ! 1090: return ((*p == *q) && i >= 0); ! 1091: } ! 1092: ! 1093: sequal(a, b) ! 1094: char *a; ! 1095: char *b; ! 1096: { ! 1097: register char *p = a, *q = b; ! 1098: ! 1099: while (*p && *q && (*p == *q)) ! 1100: { ! 1101: p++; q++; ! 1102: } ! 1103: return (*p == *q); ! 1104: } ! 1105: ! 1106: # ifdef GTTYN ! 1107: char * ! 1108: stypeof(ttyid) ! 1109: char *ttyid; ! 1110: { ! 1111: static char typebuf[50]; ! 1112: register char *PortType; ! 1113: register char *PortName; ! 1114: register char *TtyId; ! 1115: register char *p; ! 1116: register FILE *f; ! 1117: ! 1118: if (ttyid == NOTTY) ! 1119: return (DEFTYPE); ! 1120: f = fopen(GTTYN, "r"); ! 1121: if (f == NULL) ! 1122: return (DEFTYPE); ! 1123: ! 1124: /* split off end of name */ ! 1125: TtyId = ttyid; ! 1126: while (*ttyid) ! 1127: if (*ttyid++ == '/') ! 1128: TtyId = ttyid; ! 1129: ! 1130: /* scan the file */ ! 1131: while (fgets(typebuf, sizeof typebuf, f) != NULL) ! 1132: { ! 1133: p = PortType = typebuf; ! 1134: while (*p && isalnum(*p)) ! 1135: p++; ! 1136: *p++ = NULL; ! 1137: ! 1138: /* skip separator */ ! 1139: while (*p && !isalnum(*p)) ! 1140: p++; ! 1141: ! 1142: PortName = p; ! 1143: /* put NULL at end of name */ ! 1144: while (*p && isalnum(*p)) ! 1145: p++; ! 1146: *p = NULL; ! 1147: ! 1148: /* check match on port name */ ! 1149: if (sequal(PortName, TtyId)) /* found it */ ! 1150: { ! 1151: # ifdef OLDDIALUP ! 1152: if (sequal(PortType, OLDDIALUP)) ! 1153: PortType = DIALUP; ! 1154: # endif ! 1155: ! 1156: # ifdef OLDPLUGBOARD ! 1157: if (sequal(PortType, OLDPLUGBOARD)) ! 1158: PortType = PLUGBOARD; ! 1159: # endif ! 1160: ! 1161: # ifdef OLDARPANET ! 1162: if (sequal(PortType, OLDARPANET)) ! 1163: PortType = ARPANET; ! 1164: # endif ! 1165: fclose (f); ! 1166: return(PortType); ! 1167: } ! 1168: } ! 1169: fclose (f); ! 1170: return (DEFTYPE); ! 1171: } ! 1172: # endif ! 1173: ! 1174: #define YES 1 ! 1175: #define NO 0 ! 1176: /* ! 1177: * routine to output the string for the environment TERMCAP variable ! 1178: */ ! 1179: #define WHITE(c) (c == ' ' || c == '\t') ! 1180: char delcap[128][2]; ! 1181: int ncap = 0; ! 1182: ! 1183: wrtermcap(bp) ! 1184: char *bp; ! 1185: { ! 1186: char buf[CAPBUFSIZ]; ! 1187: char *p = buf; ! 1188: char *tp; ! 1189: char *putbuf(); ! 1190: int space, empty; ! 1191: ! 1192: /* discard names with blanks */ ! 1193: /** May not be desireable ? **/ ! 1194: while (*bp && *bp != ':') { ! 1195: if (*bp == '|') { ! 1196: tp = bp+1; ! 1197: space = NO; ! 1198: while (*tp && *tp != '|' && *tp != ':') { ! 1199: space = (space || WHITE(*tp) ); ! 1200: tp++; ! 1201: } ! 1202: if (space) { ! 1203: bp = tp; ! 1204: continue; ! 1205: } ! 1206: } ! 1207: *p++ = *bp++; ! 1208: } ! 1209: /**/ ! 1210: ! 1211: while (*bp) { ! 1212: switch (*bp) { ! 1213: case ':': /* discard empty, cancelled or dupl fields */ ! 1214: tp = bp+1; ! 1215: empty = YES; ! 1216: while (*tp && *tp != ':') { ! 1217: empty = (empty && WHITE(*tp) ); ! 1218: tp++; ! 1219: } ! 1220: if (empty || cancelled(bp+1)) { ! 1221: bp = tp; ! 1222: continue; ! 1223: } ! 1224: break; ! 1225: ! 1226: case ' ': /* no spaces in output */ ! 1227: p = putbuf(p, "\\040"); ! 1228: bp++; ! 1229: continue; ! 1230: ! 1231: case '"': /* no quotes in output */ ! 1232: p = putbuf(p, "\\042"); ! 1233: bp++; ! 1234: continue; ! 1235: ! 1236: case '\'': /* no quotes in output */ ! 1237: p = putbuf(p, "\\047"); ! 1238: bp++; ! 1239: continue; ! 1240: ! 1241: case '\\': ! 1242: case '^': /* anything following is OK */ ! 1243: *p++ = *bp++; ! 1244: } ! 1245: *p++ = *bp++; ! 1246: } ! 1247: write (STDOUT, buf, p-buf); ! 1248: } ! 1249: ! 1250: cancelled(cap) ! 1251: char *cap; ! 1252: { ! 1253: register int i; ! 1254: ! 1255: for (i = 0; i < ncap; i++) ! 1256: { ! 1257: if (cap[0] == delcap[i][0] && cap[1] == delcap[i][1]) ! 1258: return (YES); ! 1259: } ! 1260: /* delete a second occurrance of the same capability */ ! 1261: delcap[ncap][0] = cap[0]; ! 1262: delcap[ncap][1] = cap[1]; ! 1263: ncap++; ! 1264: return (cap[2] == '@'); ! 1265: } ! 1266: ! 1267: char * ! 1268: putbuf(ptr, str) ! 1269: char *ptr; ! 1270: char *str; ! 1271: { ! 1272: while (*str) ! 1273: *ptr++ = *str++; ! 1274: return (ptr); ! 1275: } ! 1276: ! 1277: ! 1278: baudrate(p) ! 1279: char *p; ! 1280: { ! 1281: char buf[8]; ! 1282: int i = 0; ! 1283: ! 1284: while (i < 7 && (isalnum(*p) || *p == '.')) ! 1285: buf[i++] = *p++; ! 1286: buf[i] = NULL; ! 1287: for (i=0; speeds[i].string; i++) ! 1288: if (sequal(speeds[i].string, buf)) ! 1289: return (speeds[i].speed); ! 1290: return (-1); ! 1291: } ! 1292: ! 1293: char * ! 1294: mapped(type, speed) ! 1295: char *type; ! 1296: short speed; ! 1297: { ! 1298: int match; ! 1299: ! 1300: # ifdef DEB ! 1301: printf ("spd:%d\n", speed); ! 1302: prmap(); ! 1303: # endif ! 1304: Map = map; ! 1305: while (Map->Ident) ! 1306: { ! 1307: if (*(Map->Ident) == NULL || bequal(Map->Ident, type, 4)) ! 1308: { ! 1309: match = NO; ! 1310: switch (Map->Test) ! 1311: { ! 1312: case ANY: /* no test specified */ ! 1313: case ALL: ! 1314: match = YES; ! 1315: break; ! 1316: ! 1317: case GT: ! 1318: match = (speed > Map->Speed); ! 1319: break; ! 1320: ! 1321: case GE: ! 1322: match = (speed >= Map->Speed); ! 1323: break; ! 1324: ! 1325: case EQ: ! 1326: match = (speed == Map->Speed); ! 1327: break; ! 1328: ! 1329: case LE: ! 1330: match = (speed <= Map->Speed); ! 1331: break; ! 1332: ! 1333: case LT: ! 1334: match = (speed < Map->Speed); ! 1335: break; ! 1336: ! 1337: case NE: ! 1338: match = (speed != Map->Speed); ! 1339: break; ! 1340: } ! 1341: if (match) ! 1342: return (Map->Type); ! 1343: } ! 1344: Map++; ! 1345: } ! 1346: /* no match found; return given type */ ! 1347: return (type); ! 1348: } ! 1349: ! 1350: # ifdef DEB ! 1351: prmap() ! 1352: { ! 1353: Map = map; ! 1354: while (Map->Ident) ! 1355: { ! 1356: printf ("%s t:%d s:%d %s\n", ! 1357: Map->Ident, Map->Test, Map->Speed, Map->Type); ! 1358: Map++; ! 1359: } ! 1360: } ! 1361: # endif ! 1362: ! 1363: char * ! 1364: nextarg(argc, argv) ! 1365: int argc; ! 1366: char *argv[]; ! 1367: { ! 1368: if (argc <= 0) ! 1369: fatal ("Too few args: ", *argv); ! 1370: if (*(*++argv) == '-') ! 1371: fatal ("Unexpected arg: ", *argv); ! 1372: return (*argv); ! 1373: } ! 1374: ! 1375: fatal (mesg, obj) ! 1376: char *mesg; ! 1377: char *obj; ! 1378: { ! 1379: prs (mesg); ! 1380: prs (obj); ! 1381: prc ('\n'); ! 1382: prs (USAGE); ! 1383: flush(); ! 1384: exit(1); ! 1385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.