Annotation of 43BSD/ucb/tset/tset.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.