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

1.1       root        1: #
                      2: /*
                      3: **  TSET -- set terminal modes
                      4: **
                      5: **     This program does sophisticated terminal initialization.
                      6: **     I recommend that you include it in your .start_up or .login
                      7: **     file to initialize whatever terminal you are on.
                      8: **
                      9: **     There are several features:
                     10: **
                     11: **     A special file or sequence (as controlled by the ttycap file)
                     12: **     is sent to the terminal.
                     13: **
                     14: **     Mode bits are set on a per-terminal_type basis (much better
                     15: **     than UNIX itself).  This allows special delays, automatic
                     16: **     tabs, etc.
                     17: **
                     18: **     Erase and Kill characters can be set to whatever you want.
                     19: **     Default is to change erase to control-H on a terminal which
                     20: **     can overstrike, and leave it alone on anything else.  Kill
                     21: **     is always left alone unless specifically requested.  These
                     22: **     characters can be represented as "^X" meaning control-X;
                     23: **     X is any character.
                     24: **
                     25: **     Terminals which are dialups or plugboard types can be aliased
                     26: **     to whatever type you may have in your home or office.  Thus,
                     27: **     if you know that when you dial up you will always be on a
                     28: **     TI 733, you can specify that fact to tset.  You can represent
                     29: **     a type as "?type".  This will ask you what type you want it
                     30: **     to be -- if you reply with just a newline, it will default
                     31: **     to the type given.
                     32: **
                     33: **     The htmp file, used by ex, etc., can be updated.
                     34: **
                     35: **     The current terminal type can be queried.
                     36: **
                     37: **     Usage:
                     38: **             tset [-] [-EC] [-eC] [-kC] [-s] [-h] [-u] 
                     39: **                     [-d type] [-p type] [-b type] [-a type]
                     40: **                     [-Q] [-I] [type]
                     41: **
                     42: **             In systems with environments, use:
                     43: **                     `tset -s ...`
                     44: **             Actually, this doesn't work because of a shell bug.
                     45: **             Instead, use:
                     46: **                     tset -s ... > tset.tmp
                     47: **                     source tset.tmp
                     48: **                     rm tset.tmp
                     49: **
                     50: **     Positional Parameters:
                     51: **             type -- the terminal type to force.  If this is
                     52: **                     specified, initialization is for this
                     53: **                     terminal type.
                     54: **
                     55: **     Flags:
                     56: **             - -- report terminal type.  Whatever type is
                     57: **                     decided on is reported.  If no other flags
                     58: **                     are stated, the only affect is to write
                     59: **                     the terminal type on the standard output.
                     60: **             -EC -- set the erase character to C on all terminals
                     61: **                     except those which cannot backspace (e.g.,
                     62: **                     a TTY 33).  C defaults to control-H.
                     63: **             -eC -- set the erase character to C on all terminals.
                     64: **                     C defaults to control-H.  If neither -E or -e
                     65: **                     are specified, the erase character is set to
                     66: **                     control-H if the terminal can both backspace
                     67: **                     and not overstrike (e.g., a CRT).  If the erase
                     68: **                     character is NULL (zero byte), it will be reset
                     69: **                     to '#' if nothing else is specified.
                     70: **             -kC -- set the kill character to C on all terminals.
                     71: **                     Default for C is control-X.  If not specified,
                     72: **                     the kill character is untouched; however, if
                     73: **                     not specified and the kill character is NULL
                     74: **                     (zero byte), the kill character is set to '@'.
                     75: **             -iC -- reserved for setable interrupt character.
                     76: **             -qC -- reserved for setable quit character.
                     77: **             -d type -- set the dialup type to be type.  If the
                     78: **                     terminal type seems to be dialup, make it
                     79: **                     'type' instead.  There need not be a space
                     80: **                     between 'd' and 'type'.
                     81: **             -p type -- ditto for a plugboard.
                     82: **             -b type -- ditto for a bussiplexor.
                     83: **             -a type -- ditto for an arpanet link.
                     84: **             -h -- don't read htmp file.  Normally the terminal type
                     85: **                     is determined by reading the htmp file (unless
                     86: **                     -d or -p are specified).  This forces a read
                     87: **                     of the ttytype file -- useful when htmp is
                     88: **                     somehow wrong.
                     89: **             -u -- don't update htmp.  It seemed like this should
                     90: **                     be put in.  Note that htmp is never actually
                     91: **                     written if there are no changes, so don't bother
                     92: **                     bother using this for efficiency reasons alone.
                     93: **             -s -- output setenv commands for TERM.  This can be
                     94: **                     used with
                     95: **                             `tset -s ...`
                     96: **                     and is to be prefered to:
                     97: **                             setenv TERM `tset - ...`
                     98: **                     because -s sets the TERMCAP variable also.
                     99: **             -Q -- be quiet.  don't output 'Erase set to' etc.
                    100: **             -I -- don't do terminal initialization (is & if
                    101: **                     strings).
                    102: **
                    103: **     Files:
                    104: **             /etc/ttytype
                    105: **                     contains a terminal id -> terminal type
                    106: **                     mapping; used when -h, -d, or -p is used.
                    107: **             /etc/termcap
                    108: **                     a terminal_type -> terminal_capabilities
                    109: **                     mapping.
                    110: **
                    111: **     Return Codes:
                    112: **             -1 -- couldn't open ttycap.
                    113: **             1 -- bad terminal type, or standard output not tty.
                    114: **             0 -- ok.
                    115: **
                    116: **     Defined Constants:
                    117: **             DIALUP -- the type code for a dialup port
                    118: **             PLUGBOARD -- the code for a plugboard port.
                    119: **             BUSSIPLEXER -- the code for a bussiplexer port.
                    120: **             ARPANET -- the code for an arpanet port.
                    121: **             BACKSPACE -- control-H, the default for -e.
                    122: **             CONTROLX -- control-X, the default for -k.
                    123: **             OLDERASE -- the system default erase character.
                    124: **             OLDKILL -- the system default kill character.
                    125: **             FILEDES -- the file descriptor to do the operation
                    126: **                     on, nominally 1 or 2.
                    127: **             STDOUT -- the standard output file descriptor.
                    128: **             UIDMASK -- the bit pattern to mask with the getuid()
                    129: **                     call to get just the user id.
                    130: **
                    131: **     Requires:
                    132: **             Routines to handle htmp, ttytype, and ttycap.
                    133: **
                    134: **     Compilation Flags:
                    135: **             PLUGBOARD -- if defined, accept the -p flag.
                    136: **             BUSSIPLEXER -- if defined, accept the -b flag.
                    137: **             FULLLOGIN -- if defined, login sets the ttytype from
                    138: **                     /etc/ttytype file.
                    139: **             V6 -- if clear, use environments, not htmp.
                    140: **                     also use TIOCSETN rather than stty to avoid flushing
                    141: **             GTTYN -- if set, uses generalized tty names.
                    142: **
                    143: **     Trace Flags:
                    144: **             none
                    145: **
                    146: **     Diagnostics:
                    147: **             Bad flag
                    148: **                     An incorrect option was specified.
                    149: **             Cannot open ...
                    150: **                     The specified file could not be openned.
                    151: **             Type ... unknown
                    152: **                     An unknown terminal type was specified.
                    153: **             Cannot update htmp
                    154: **                     Cannot update htmp file when the standard
                    155: **                     output is not a terminal.
                    156: **             Erase set to ...
                    157: **                     Telling that the erase character has been
                    158: **                     set to the specified character.
                    159: **             Kill set to ...
                    160: **                     Ditto for kill
                    161: **             Erase is ...    Kill is ...
                    162: **                     Tells that the erase/kill characters were
                    163: **                     wierd before, but they are being left as-is.
                    164: **             Not a terminal
                    165: **                     Set if FILEDES is not a terminal.
                    166: **
                    167: **     Compilation Instructions:
                    168: **             cc -n -O tset.c -lX
                    169: **             mv a.out tset
                    170: **             chown bin tset
                    171: **             chmod 4755 tset
                    172: **
                    173: **             where 'bin' should be whoever owns the 'htmp' file.
                    174: **             If 'htmp' is 666, then tset need not be setuid.
                    175: **
                    176: **     Author:
                    177: **             Eric Allman
                    178: **             Electronics Research Labs
                    179: **             U.C. Berkeley
                    180: **
                    181: **     History:
                    182: **             10/79 -- '-s' option extended to handle TERMCAP
                    183: **                     variable, set noglob, quote the entry,
                    184: **                     and know about the Bourne shell.  Terminal
                    185: **                     initialization moved to before any information
                    186: **                     output so screen clears would not screw you.
                    187: **                     '-Q' option added.
                    188: **             8/79 -- '-' option alone changed to only output
                    189: **                     type.  '-s' option added.  'VERSION7'
                    190: **                     changed to 'V6' for compatibility.
                    191: **             12/78 -- modified for eventual migration to VAX/UNIX,
                    192: **                     so the '-' option is changed to output only
                    193: **                     the terminal type to STDOUT instead of
                    194: **                     FILEDES.  FULLLOGIN flag added.
                    195: **             9/78 -- '-' and '-p' options added (now fully
                    196: **                     compatible with ttytype!), and spaces are
                    197: **                     permitted between the -d and the type.
                    198: **             8/78 -- The sense of -h and -u were reversed, and the
                    199: **                     -f flag is dropped -- same effect is available
                    200: **                     by just stating the terminal type.
                    201: **             10/77 -- Written.
                    202: */
                    203: 
                    204: /*
                    205: # define       FULLLOGIN       1
                    206: */
                    207: # ifndef V6
                    208: # define       GTTYN           1
                    209: # endif
                    210: 
                    211: # include      <sgtty.h>
                    212: # include      <stdio.h>
                    213: 
                    214: # define       BACKSPACE       ('H' & 037)
                    215: # define       CONTROLX        ('X' & 037)
                    216: # define       OLDERASE        '#'
                    217: # define       OLDKILL         '@'
                    218: 
                    219: # define       FILEDES         2
                    220: # define       STDOUT          1
                    221: 
                    222: # ifdef V6
                    223: # define       UIDMASK         0377
                    224: # else
                    225: # define       UIDMASK         -1
                    226: # endif
                    227: 
                    228: # define       DIALUP          "sd"
                    229: # define       PLUGBOARD       "sp"
                    230: # define       BUSSIPLEXER     "sb"
                    231: # define       ARPANET         "sa"
                    232: 
                    233: # ifdef GTTYN
                    234: typedef char   *ttyid_t;
                    235: # define       NOTTY           0
                    236: # else
                    237: typedef char   ttyid_t;
                    238: # define       NOTTY           'x'
                    239: # endif
                    240: 
                    241: 
                    242: 
                    243: 
                    244: 
                    245: 
                    246: char   Erase_char;             /* new erase character */
                    247: char   Kill_char;              /* new kill character */
                    248: char   Specialerase;           /* set => Erase_char only on terminals with backspace */
                    249: 
                    250: ttyid_t        Ttyid = NOTTY;          /* terminal identifier */
                    251: char   *TtyType;               /* type of terminal */
                    252: char   *DefType;               /* default type if none other computed */
                    253: char   *DialType;              /* override type if dialup port */
                    254: char   *PlugType;              /* override type if plugboard port */
                    255: char   *BxType;                /* override type if bussiplexer port */
                    256: char   *AnType;                /* override type if arpanet port */
                    257: int    Dash_u;                 /* don't update htmp */
                    258: int    Dash_h;                 /* don't read htmp */
                    259: int    DoSetenv;               /* output setenv commands */
                    260: int    BeQuiet;                /* be quiet */
                    261: int    NoInit;                 /* don't output initialization string */
                    262: int    Report;                 /* report current type */
                    263: int    Ureport;                /* report to user */
                    264: int    RepOnly;                /* report only */
                    265: 
                    266: char   Usage[] = "usage: tset [-] [-r] [-s] [-eC] [-kC] [-d T] [-p T] [-b T] [-a T]\n\t[-Q] [-I] [-h] [-u] [type]\n";
                    267: 
                    268: char   Capbuf[1024];           /* line from /etc/termcap for this TtyType */
                    269: char   *Ttycap;                /* termcap line from termcap or environ */
                    270: 
                    271: struct delay
                    272: {
                    273:        int     d_delay;
                    274:        int     d_bits;
                    275: };
                    276: 
                    277: # include      "tset.delays.h"
                    278: 
                    279: 
                    280: 
                    281: main(argc, argv)
                    282: int    argc;
                    283: char   *argv[];
                    284: {
                    285:        struct sgttyb   mode;
                    286:        struct sgttyb   oldmode;
                    287:        char            buf[256];
                    288:        auto char       *bufp;
                    289:        register char   *p;
                    290:        char            *command;
                    291:        register int    i;
                    292:        register int    error;
                    293:        extern char     *stypeof();
                    294: # ifdef V6
                    295:        extern char     *hsgettype();
                    296: # else
                    297:        extern char     *getenv();
                    298: # endif
                    299: # ifdef GTTYN
                    300:        extern char     *ttyname();
                    301:        extern char     *tgetstr();
                    302: # endif
                    303:        char            bs_char;
                    304:        int             csh;
                    305: 
                    306:        /* scan argument list and collect flags */
                    307:        error = 0;
                    308:        command = argv[0];
                    309:        if (argc == 2 && argv[1][0] == '-' && argv[1][1] == '\0')
                    310:                RepOnly++;
                    311:        argc--;
                    312:        while (--argc >= 0)
                    313:        {
                    314:                p = *++argv;
                    315:                if (p[0] == '-')
                    316:                {
                    317:                        switch (p[1])
                    318:                        {
                    319: 
                    320:                          case 0:       /* report current terminal type */
                    321:                                Report++;
                    322:                                continue;
                    323: 
                    324:                          case 'r':     /* report to user */
                    325:                                Ureport++;
                    326:                                continue;
                    327: 
                    328:                          case 'E':     /* special erase: operate on all but TTY33 */
                    329:                                Specialerase++;
                    330:                                /* explicit fall-through to -e case */
                    331: 
                    332:                          case 'e':     /* erase character */
                    333:                                if (p[2] == 0)
                    334:                                        Erase_char = -1;
                    335:                                else if (p[2] == '^' && p[3] != '\0')
                    336:                                        Erase_char = p[3] & 037;
                    337:                                else
                    338:                                        Erase_char = p[2];
                    339:                                continue;
                    340: 
                    341:                          case 'k':     /* kill character */
                    342:                                if (p[2] == 0)
                    343:                                        Kill_char = CONTROLX;
                    344:                                else if (p[2] == '^' && p[3] != '\0')
                    345:                                        Kill_char = p[3] & 037;
                    346:                                else
                    347:                                        Kill_char = p[2];
                    348:                                continue;
                    349: 
                    350:                          case 'd':     /* dialup type */
                    351:                                if (p[2] != 0)
                    352:                                        DialType = &p[2];
                    353:                                else if (--argc < 0 || argv[1][0] == '-')
                    354:                                        error++;
                    355:                                else
                    356:                                        DialType = *++argv;
                    357:                                continue;
                    358: 
                    359: # ifdef PLUGBOARD
                    360:                          case 'p':     /* plugboard type */
                    361:                                if (p[2] != 0)
                    362:                                        PlugType = &p[2];
                    363:                                else if (--argc < 0 || argv[1][0] == '-')
                    364:                                        error++;
                    365:                                else
                    366:                                        PlugType = *++argv;
                    367:                                continue;
                    368: # endif
                    369: 
                    370: # ifdef BUSSIPLEXER
                    371:                          case 'b':     /* bussiplexer type */
                    372:                                if (p[2] != 0)
                    373:                                        BxType = &p[2];
                    374:                                else if (--argc < 0 || argv[1][0] == '-')
                    375:                                        error++;
                    376:                                else
                    377:                                        BxType = *++argv;
                    378: # endif
                    379: 
                    380: # ifdef ARPANET
                    381:                          case 'a':     /* arpanet type */
                    382:                                if (p[2] != 0)
                    383:                                        AnType = &p[2];
                    384:                                else if (--argc < 0 || argv[1][0] == '-')
                    385:                                        error++;
                    386:                                else
                    387:                                        AnType = *++argv;
                    388: # endif
                    389: 
                    390:                          case 'h':     /* don't get type from htmp or env */
                    391:                                Dash_h++;
                    392:                                continue;
                    393: 
                    394:                          case 'u':     /* don't update htmp */
                    395:                                Dash_u++;
                    396:                                continue;
                    397:                          
                    398:                          case 's':     /* output setenv commands */
                    399:                                DoSetenv++;
                    400:                                continue;
                    401:                          
                    402:                          case 'Q':     /* be quiet */
                    403:                                BeQuiet++;
                    404:                                continue;
                    405:                          
                    406:                          case 'I':     /* no initialization */
                    407:                                NoInit++;
                    408:                                continue;
                    409: 
                    410:                          default:
                    411:                                prs("Bad flag ");
                    412:                                prs(p);
                    413:                                prs("\n");
                    414:                                error++;
                    415: 
                    416:                        }
                    417:                }
                    418:                else
                    419:                {
                    420:                        /* terminal type */
                    421:                        DefType = p;
                    422:                }
                    423:        }
                    424: 
                    425:        if (error)
                    426:        {
                    427:                prs(Usage);
                    428:                exit(1);
                    429:        }
                    430: 
                    431:        /* if dialup is specified, check ttytype not htmp */
                    432:        if (DialType == 0 && PlugType == 0 && BxType == 0 && AnType == 0)
                    433:                TtyType = DefType;
                    434: # ifndef FULLLOGIN
                    435:        else
                    436:                Dash_h++;
                    437: # endif
                    438:        
                    439:        /* if report only, say that we won't update htmp */
                    440:        if (RepOnly)
                    441:                Dash_u++;
                    442: 
                    443: # ifndef V6
                    444:        /* get current idea of terminal type from environment */
                    445:        if (!Dash_h && TtyType == 0)
                    446:                TtyType = getenv("TERM");
                    447: # endif
                    448: 
                    449:        /* determine terminal id if needed */
                    450: # ifdef V6
                    451:        if (Ttyid == NOTTY && (TtyType == 0 || !Dash_h || !Dash_u))
                    452:                Ttyid = ttyn(FILEDES);
                    453: # else
                    454:        if (!RepOnly && Ttyid == NOTTY && (TtyType == 0 || !Dash_h))
                    455:                Ttyid = ttyname(FILEDES);
                    456: # endif
                    457: 
                    458: # ifdef V6
                    459:        /* get htmp if ever used */
                    460:        if (!Dash_u || (TtyType == 0 && !Dash_h))
                    461:        {
                    462:                /* get htmp entry -- if error or wrong user use ttytype */
                    463:                if (Ttyid == NOTTY || hget(Ttyid) < 0 ||
                    464:                    hgettype() == 0 || hgetuid() != (getuid() & UIDMASK))
                    465:                        Dash_h++;
                    466:        }
                    467: # endif
                    468: 
                    469:        /* find terminal type (if not already known) */
                    470:        if (TtyType == 0)
                    471:        {
                    472:                /* get type from /etc/ttytype or /etc/htmp */
                    473:                if (!Dash_h)
                    474:                {
                    475: # ifdef V6
                    476:                        TtyType = hsgettype();
                    477: # else
                    478:                        TtyType = getenv("TERM");
                    479: # endif
                    480:                }
                    481:                if (TtyType == 0)
                    482:                {
                    483:                        TtyType = stypeof(Ttyid);
                    484:                }
                    485: 
                    486:                /* check for dialup or plugboard override */
                    487:                if (DialType != 0 && bequal(TtyType, DIALUP, 2))
                    488:                        TtyType = DialType;
                    489: # ifdef PLUGBOARD
                    490:                else if (PlugType != 0 && bequal(TtyType, PLUGBOARD, 2))
                    491:                        TtyType = PlugType;
                    492: # endif
                    493: # ifdef BUSSIPLEXER
                    494:                else if (BxType != 0 && bequal(TtyType, BUSSIPLEXER, 2))
                    495:                        TtyType = BxType;
                    496: # endif
                    497: # ifdef ARPANET
                    498:                else if (AnType != 0 && bequal(TtyType, ARPANET, 2))
                    499:                        TtyType = AnType;
                    500: # endif
                    501:                else if (DefType != 0)
                    502:                        TtyType = DefType;
                    503:        }
                    504: 
                    505:        /* TtyType now contains a pointer to the type of the terminal */
                    506:        /* If the first character is '?', ask the user */
                    507:        if (TtyType[0] == '?')
                    508:        {
                    509:                if (*++TtyType == '\0')
                    510:                        TtyType = "dumb";
                    511:                prs("TERM = (");
                    512:                prs(TtyType);
                    513:                prs(") ");
                    514: 
                    515:                /* read the terminal.  If not empty, set type */
                    516:                i = read(2, buf, sizeof buf - 1);
                    517:                if (i >= 0)
                    518:                {
                    519:                        if (buf[i - 1] == '\n')
                    520:                                i--;
                    521:                        buf[i] = '\0';
                    522:                        if (buf[0] != '\0')
                    523:                                TtyType = buf;
                    524:                }
                    525:        }
                    526: 
                    527:        if (Ttycap == 0)
                    528:        {
                    529:                /* get terminal capabilities */
                    530:                switch (tgetent(Capbuf, TtyType))
                    531:                {
                    532:                  case -1:
                    533:                        prs("Cannot open termcap file\n");
                    534:                        exit(-1);
                    535: 
                    536:                  case 0:
                    537:                        prs("Type ");
                    538:                        prs(TtyType);
                    539:                        prs(" unknown\n");
                    540:                        exit(1);
                    541:                }
                    542:                Ttycap = Capbuf;
                    543:        }
                    544: 
                    545:        /* output startup string */
                    546:        if (!RepOnly && !NoInit)
                    547:        {
                    548:                bufp = buf;
                    549:                if (tgetstr("is", &bufp) != 0)
                    550:                        prs(buf);
                    551:                bufp = buf;
                    552:                if (tgetstr("if", &bufp) != 0)
                    553:                        cat(buf);
                    554:                sleep(1);       /* let terminal settle down */
                    555:        }
                    556: 
                    557:        /* set up environment for the shell we are using */
                    558:        /* (this code is rather heuristic) */
                    559:        csh = 0;
                    560:        if (DoSetenv)
                    561:        {
                    562: # ifndef V6
                    563:                if (bequal(getenv("SHELL"), "/bin/csh", 9))
                    564:                {
                    565: # endif
                    566:                        /* running csh */
                    567:                        csh++;
                    568:                        write(STDOUT, "set noglob;\n", 12);
                    569: # ifndef V6
                    570:                }
                    571:                else
                    572:                {
                    573:                        /* running system shell */
                    574:                        write(STDOUT, "export TERMCAP TERM;\n", 21);
                    575:                }
                    576: # endif
                    577:        }
                    578: 
                    579:        /* report type if appropriate */
                    580:        if (DoSetenv || Report || Ureport)
                    581:        {
                    582:                /* find first alias (if any) */
                    583:                for (p = Ttycap; *p != 0 && *p != '|' && *p != ':'; p++)
                    584:                        continue;
                    585:                if (*p == 0 || *p == ':')
                    586:                        p = Ttycap;
                    587:                else
                    588:                        p++;
                    589:                bufp = p;
                    590:                while (*p != '|' && *p != ':' && *p != 0)
                    591:                        p++;
                    592:                i = *p;
                    593:                if (DoSetenv)
                    594:                {
                    595:                        if (csh)
                    596:                                write(STDOUT, "setenv TERM ", 12);
                    597:                        else
                    598:                                write(STDOUT, "TERM=", 5);
                    599:                }
                    600:                if (Report || DoSetenv)
                    601:                {
                    602:                        write(STDOUT, bufp, p - bufp);
                    603:                        if (DoSetenv)
                    604:                                write(STDOUT, ";", 1);
                    605:                        write(STDOUT, "\n", 1);
                    606:                }
                    607:                if (Ureport)
                    608:                {
                    609:                        *p = '\0';
                    610:                        prs("Terminal type is ");
                    611:                        prs(bufp);
                    612:                        prs("\n");
                    613:                }
                    614:                *p = i;
                    615:                if (DoSetenv)
                    616:                {
                    617:                        for (p = Ttycap; *p != '\0'; p++)
                    618:                                continue;
                    619:                        if (csh)
                    620:                                write(STDOUT, "setenv TERMCAP '", 16);
                    621:                        else
                    622:                                write(STDOUT, "TERMCAP='", 9);
                    623:                        write(STDOUT, Ttycap, p - Ttycap);
                    624:                        write(STDOUT, "';\n", 3);
                    625: 
                    626:                        /* reset noglob */
                    627:                        if (csh)
                    628:                                write(STDOUT, "unset noglob;\n", 14);
                    629:                }
                    630:        }
                    631: 
                    632:        /* exit if report only mode */
                    633:        if (RepOnly)
                    634:                exit(0);
                    635: 
                    636:        if (gtty(FILEDES, &mode) < 0)
                    637:        {
                    638:                prs("Not a terminal\n");
                    639:                exit(1);
                    640:        }
                    641:        bmove(&mode, &oldmode, sizeof mode);
                    642: 
                    643:        /* determine erase and kill characters */
                    644:        if (Specialerase && !tgetflag("bs"))
                    645:                Erase_char = 0;
                    646:        bufp = buf;
                    647:        p = tgetstr("bc", &bufp);
                    648:        if (p != NULL)
                    649:                bs_char = p[0];
                    650:        else if (tgetflag("bs"))
                    651:                bs_char = BACKSPACE;
                    652:        else
                    653:                bs_char = 0;
                    654:        if (Erase_char == 0 && !tgetflag("os"))
                    655:        {
                    656:                if (tgetflag("bs") || bs_char != 0)
                    657:                        Erase_char = -1;
                    658:        }
                    659:        if (Erase_char < 0)
                    660:                Erase_char = (bs_char != 0) ? bs_char : BACKSPACE;
                    661: 
                    662:        if (mode.sg_erase == 0)
                    663:                mode.sg_erase = OLDERASE;
                    664:        if (Erase_char != 0)
                    665:                mode.sg_erase = Erase_char;
                    666: 
                    667:        if (mode.sg_kill == 0)
                    668:                mode.sg_kill = OLDKILL;
                    669:        if (Kill_char != 0)
                    670:                mode.sg_kill = Kill_char;
                    671: 
                    672:        /* set modes */
                    673:        setdelay("dC", CRdelay, CRbits, &mode.sg_flags);
                    674:        setdelay("dN", NLdelay, NLbits, &mode.sg_flags);
                    675:        setdelay("dB", BSdelay, BSbits, &mode.sg_flags);
                    676:        setdelay("dF", FFdelay, FFbits, &mode.sg_flags);
                    677:        setdelay("dT", TBdelay, TBbits, &mode.sg_flags);
                    678:        if (tgetflag("UC") || command[0] == 'T')
                    679:                mode.sg_flags |= LCASE;
                    680:        else if (tgetflag("LC"))
                    681:                mode.sg_flags &= ~LCASE;
                    682:        mode.sg_flags &= ~(EVENP | ODDP | RAW);
                    683: # ifndef V6
                    684:        mode.sg_flags &= ~CBREAK;
                    685: # endif
                    686:        if (tgetflag("EP"))
                    687:                mode.sg_flags |= EVENP;
                    688:        if (tgetflag("OP"))
                    689:                mode.sg_flags |= ODDP;
                    690:        if ((mode.sg_flags & (EVENP | ODDP)) == 0)
                    691:                mode.sg_flags |= EVENP | ODDP;
                    692:        mode.sg_flags |= CRMOD | ECHO | XTABS;
                    693:        if (tgetflag("NL"))     /* new line, not line feed */
                    694:                mode.sg_flags &= ~CRMOD;
                    695:        if (tgetflag("HD"))     /* half duplex */
                    696:                mode.sg_flags &= ~ECHO;
                    697:        if (tgetflag("pt"))     /* print tabs */
                    698:                mode.sg_flags &= ~XTABS;
                    699:        if (!bequal(&mode, &oldmode, sizeof mode))
                    700: # ifndef V6
                    701:                ioctl(FILEDES, TIOCSETN, &mode);
                    702: # else
                    703:                stty(FILEDES, &mode);
                    704: # endif
                    705: 
                    706:        /* tell about changing erase and kill characters */
                    707:        reportek("Erase", mode.sg_erase, oldmode.sg_erase, OLDERASE);
                    708:        reportek("Kill", mode.sg_kill, oldmode.sg_kill, OLDKILL);
                    709: 
                    710: # ifdef V6
                    711:        /* update htmp */
                    712:        if (!Dash_u)
                    713:        {
                    714:                if (Ttyid == 0)
                    715:                        Ttyid = ttyn(FILEDES);
                    716:                if (Ttyid == 'x')
                    717:                        prs("Cannot update htmp\n");
                    718:                else
                    719:                {
                    720:                        /* update htmp file only if changed */
                    721:                        if (!bequal(Capbuf, hsgettype(), 2))
                    722:                        {
                    723:                                hsettype(Capbuf[0] | (Capbuf[1] << 8));
                    724:                                hput(Ttyid);
                    725:                        }
                    726:                }
                    727:        }
                    728: # endif
                    729: 
                    730:        exit(0);
                    731: }
                    732: 
                    733: 
                    734: reportek(name, new, old, def)
                    735: char   *name;
                    736: char   old;
                    737: char   new;
                    738: char   def;
                    739: {
                    740:        register char   o;
                    741:        register char   n;
                    742:        register char   *p;
                    743: 
                    744:        if (BeQuiet)
                    745:                return;
                    746:        o = old;
                    747:        n = new;
                    748: 
                    749:        if (o == n && n == def)
                    750:                return;
                    751:        prs(name);
                    752:        if (o == n)
                    753:                prs(" is ");
                    754:        else
                    755:                prs(" set to ");
                    756:        if (n < 040)
                    757:        {
                    758:                prs("control-");
                    759:                n = (n & 037) | 0100;
                    760:        }
                    761:        p = "x\n";
                    762:        p[0] = n;
                    763:        prs(p);
                    764: }
                    765: 
                    766: 
                    767: 
                    768: 
                    769: setdelay(cap, dtab, bits, flags)
                    770: char           *cap;
                    771: struct delay   dtab[];
                    772: int            bits;
                    773: int            *flags;
                    774: {
                    775:        register int    i;
                    776:        register struct delay   *p;
                    777: 
                    778:        /* see if this capability exists at all */
                    779:        i = tgetnum(cap);
                    780:        if (i < 0)
                    781:                i = 0;
                    782: 
                    783:        /* clear out the bits, replace with new ones */
                    784:        *flags &= ~bits;
                    785: 
                    786:        /* scan dtab for first entry with adequate delay */
                    787:        for (p = dtab; p->d_delay >= 0; p++)
                    788:        {
                    789:                if (p->d_delay >= i)
                    790:                {
                    791:                        p++;
                    792:                        break;
                    793:                }
                    794:        }
                    795: 
                    796:        /* use last entry if none will do */
                    797:        *flags |= (--p)->d_bits;
                    798: }
                    799: 
                    800: 
                    801: prs(s)
                    802: char   *s;
                    803: {
                    804:        register char   *p;
                    805:        register char   *q;
                    806:        register int    i;
                    807: 
                    808:        p = q = s;
                    809:        i = 0;
                    810:        while (*q++ != 0)
                    811:                i++;
                    812: 
                    813:        if (i > 0)
                    814:                write(FILEDES, p, i);
                    815: }
                    816: 
                    817: 
                    818: cat(file)
                    819: char   *file;
                    820: {
                    821:        register int    fd;
                    822:        register int    i;
                    823:        char            buf[BUFSIZ];
                    824: 
                    825:        fd = open(file, 0);
                    826:        if (fd < 0)
                    827:        {
                    828:                prs("Cannot open ");
                    829:                prs(file);
                    830:                prs("\n");
                    831:                exit(-1);
                    832:        }
                    833: 
                    834:        while ((i = read(fd, buf, BUFSIZ)) > 0)
                    835:                write(FILEDES, buf, i);
                    836: 
                    837:        close(fd);
                    838: }
                    839: 
                    840: 
                    841: 
                    842: bmove(from, to, length)
                    843: char   *from;
                    844: char   *to;
                    845: int    length;
                    846: {
                    847:        register char   *p, *q;
                    848:        register int    i;
                    849: 
                    850:        i = length;
                    851:        p = from;
                    852:        q = to;
                    853: 
                    854:        while (i-- > 0)
                    855:                *q++ = *p++;
                    856: }
                    857: 
                    858: 
                    859: 
                    860: bequal(a, b, len)
                    861: char   *a;
                    862: char   *b;
                    863: int    len;
                    864: {
                    865:        register char   *p, *q;
                    866:        register int    i;
                    867: 
                    868:        i = len;
                    869:        p = a;
                    870:        q = b;
                    871: 
                    872:        while (i-- > 0)
                    873:                if (*p++ != *q++)
                    874:                        return (0);
                    875:        return (1);
                    876: }
                    877: 
                    878: # ifdef GTTYN
                    879: char *
                    880: stypeof(ttyid)
                    881: char   *ttyid;
                    882: {
                    883:        static char     typebuf[3];
                    884:        char            buf[50];
                    885:        register char   *p;
                    886:        register FILE   *f;
                    887:        register char   *t;
                    888:        register char   *q;
                    889: 
                    890:        if (ttyid == NOTTY)
                    891:                return ("un");
                    892:        f = fopen("/etc/ttytype", "r");
                    893:        if (f == NULL)
                    894:                return ("un");
                    895: 
                    896:        /* split off end of name */
                    897:        for (p = q = ttyid; *p != 0; p++)
                    898:                if (*p == '/')
                    899:                        q = p + 1;
                    900: 
                    901:        /* scan the file */
                    902:        while (fgets(buf, sizeof buf, f) != NULL)
                    903:        {
                    904:                for (p = q, t = &buf[3]; *p != '\0'; p++, t++)
                    905:                        if (*p != *t)
                    906:                                break;
                    907:                if (*p == '\0' && (*t == '\n' || *t == '\t'))
                    908:                {
                    909:                        typebuf[0] = buf[0];
                    910:                        typebuf[1] = buf[1];
                    911:                        typebuf[2] = '\0';
                    912:                        fclose(f);
                    913:                        return (typebuf);
                    914:                }
                    915:        }
                    916:        fclose (f);
                    917:        return ("un");
                    918: }
                    919: # endif

unix.superglobalmegacorp.com

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