Annotation of 41BSD/cmd/tset/tset.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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