[BACK]Return to tset.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tset

Annotation of src/usr.bin/tset/tset.c, Revision 1.15

1.7       millert     1: /****************************************************************************
                      2:  * Copyright (c) 1998 Free Software Foundation, Inc.                        *
                      3:  *                                                                          *
                      4:  * Permission is hereby granted, free of charge, to any person obtaining a  *
                      5:  * copy of this software and associated documentation files (the            *
                      6:  * "Software"), to deal in the Software without restriction, including      *
                      7:  * without limitation the rights to use, copy, modify, merge, publish,      *
                      8:  * distribute, distribute with modifications, sublicense, and/or sell       *
                      9:  * copies of the Software, and to permit persons to whom the Software is    *
                     10:  * furnished to do so, subject to the following conditions:                 *
                     11:  *                                                                          *
                     12:  * The above copyright notice and this permission notice shall be included  *
                     13:  * in all copies or substantial portions of the Software.                   *
                     14:  *                                                                          *
                     15:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
                     16:  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
                     17:  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
                     18:  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
                     19:  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
                     20:  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
                     21:  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
                     22:  *                                                                          *
                     23:  * Except as contained in this notice, the name(s) of the above copyright   *
                     24:  * holders shall not be used in advertising or otherwise to promote the     *
                     25:  * sale, use or other dealings in this Software without prior written       *
                     26:  * authorization.                                                           *
                     27:  ****************************************************************************/
                     28:
                     29: /****************************************************************************
                     30:  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
                     31:  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
                     32:  ****************************************************************************/
1.1       deraadt    33:
1.7       millert    34:
                     35: /*
                     36:  * tset.c - terminal initialization utility
                     37:  *
                     38:  * This code was mostly swiped from 4.4BSD tset, with some obsolescent
                     39:  * cruft removed and substantial portions rewritten.  A Regents of the
                     40:  * University of California copyright applies to some portions of the
                     41:  * code, and is reproduced below:
                     42:  */
1.1       deraadt    43: /*-
                     44:  * Copyright (c) 1980, 1991, 1993
                     45:  *     The Regents of the University of California.  All rights reserved.
                     46:  *
                     47:  * Redistribution and use in source and binary forms, with or without
                     48:  * modification, are permitted provided that the following conditions
                     49:  * are met:
                     50:  * 1. Redistributions of source code must retain the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer.
                     52:  * 2. Redistributions in binary form must reproduce the above copyright
                     53:  *    notice, this list of conditions and the following disclaimer in the
                     54:  *    documentation and/or other materials provided with the distribution.
                     55:  * 3. All advertising materials mentioning features or use of this software
                     56:  *    must display the following acknowledgement:
                     57:  *     This product includes software developed by the University of
                     58:  *     California, Berkeley and its contributors.
                     59:  * 4. Neither the name of the University nor the names of its contributors
                     60:  *    may be used to endorse or promote products derived from this software
                     61:  *    without specific prior written permission.
                     62:  *
                     63:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     64:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     65:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     66:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     67:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     68:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     69:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     70:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     71:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     72:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     73:  * SUCH DAMAGE.
                     74:  */
                     75:
1.7       millert    76: #define __INTERNAL_CAPS_VISIBLE        /* we need to see has_hardware_tabs */
                     77: #include <progs.priv.h>
                     78:
1.1       deraadt    79: #include <errno.h>
                     80: #include <stdio.h>
1.7       millert    81: #include <termcap.h>
                     82: #include <fcntl.h>
                     83:
                     84: #if HAVE_GETTTYNAM && HAVE_TTYENT_H
                     85: #include <ttyent.h>
                     86: #endif
                     87: #ifdef NeXT
                     88: char *ttyname(int fd);
                     89: #endif
                     90:
                     91: /* this is just to stifle a missing-prototype warning */
                     92: #ifdef linux
                     93: # include <sys/ioctl.h>
                     94: #endif
                     95:
                     96: #if NEED_PTEM_H
                     97: /* they neglected to define struct winsize in termios.h -- it's only
                     98:    in termio.h */
                     99: #include       <sys/stream.h>
                    100: #include       <sys/ptem.h>
                    101: #endif
                    102:
                    103: #include <curses.h>    /* for bool typedef */
                    104: #include <dump_entry.h>
                    105:
1.13      millert   106: MODULE_ID("$From: tset.c,v 0.37 1999/03/14 12:30:02 tom Exp $")
1.7       millert   107:
                    108: extern char **environ;
                    109:
                    110: #undef CTRL
                    111: #define CTRL(x)        ((x) & 0x1f)
                    112:
                    113: const char *_nc_progname = "tset";
                    114:
                    115: static TTY mode, oldmode;
                    116:
                    117: static int     terasechar = -1;        /* new erase character */
                    118: static int     intrchar = -1;          /* new interrupt character */
                    119: static int     isreset;                /* invoked as reset */
                    120: static int     tkillchar = -1;         /* new kill character */
                    121: static int     tlines, tcolumns;               /* window size */
                    122:
                    123: #define LOWERCASE(c) ((isalpha(c) && isupper(c)) ? tolower(c) : (c))
                    124:
                    125: static int
                    126: CaselessCmp(const char *a, const char *b) /* strcasecmp isn't portable */
                    127: {
                    128:        while (*a && *b) {
                    129:                int cmp = LOWERCASE(*a) - LOWERCASE(*b);
                    130:                if (cmp != 0)
                    131:                        break;
                    132:                a++, b++;
                    133:        }
                    134:        return LOWERCASE(*a) - LOWERCASE(*b);
                    135: }
                    136:
                    137: #if !HAVE_STRDUP
1.13      millert   138: #define strdup _nc_strdup
                    139: extern char *_nc_strdup(const char *);
1.7       millert   140: #endif /* not HAVE_STRDUP */
                    141:
                    142: static void
                    143: err(const char *fmt, ...)
                    144: {
                    145:        va_list ap;
                    146:        va_start(ap, fmt);
                    147:        (void)fprintf(stderr, "tset: ");
                    148:        (void)vfprintf(stderr, fmt, ap);
                    149:        va_end(ap);
                    150:        (void)fprintf(stderr, "\n");
                    151:        exit(EXIT_FAILURE);
                    152:        /* NOTREACHED */
                    153: }
                    154:
                    155: static void
                    156: failed(const char *msg)
                    157: {
1.15    ! millert   158:        (void)fputs("tset: ", stderr);
        !           159:        perror(msg);
1.7       millert   160:        exit(EXIT_FAILURE);
                    161:        /* NOTREACHED */
                    162: }
                    163:
                    164: static void
                    165: cat(char *file)
                    166: {
                    167:        register int fd, nr, nw;
                    168:        char buf[BUFSIZ];
                    169:
                    170:        if ((fd = open(file, O_RDONLY, 0)) < 0)
                    171:                failed(file);
                    172:
                    173:        while ((nr = read(fd, buf, sizeof(buf))) > 0)
                    174:                if ((nw = write(STDERR_FILENO, buf, (size_t)nr)) == -1)
                    175:                        failed("write to stderr");
                    176:        if (nr != 0)
                    177:                failed(file);
                    178:        (void)close(fd);
                    179: }
                    180:
                    181: static int
                    182: outc(int c)
                    183: {
                    184:        return putc(c, stderr);
                    185: }
                    186:
                    187: /* Prompt the user for a terminal type. */
                    188: static const char *
                    189: askuser(const char *dflt)
                    190: {
                    191:        static char answer[256];
                    192:        char *p;
                    193:
                    194:        /* We can get recalled; if so, don't continue uselessly. */
                    195:        if (feof(stdin) || ferror(stdin)) {
                    196:                (void)fprintf(stderr, "\n");
                    197:                exit(EXIT_FAILURE);
                    198:        }
                    199:        for (;;) {
                    200:                if (dflt)
                    201:                        (void)fprintf(stderr, "Terminal type? [%s] ", dflt);
                    202:                else
                    203:                        (void)fprintf(stderr, "Terminal type? ");
                    204:                (void)fflush(stderr);
                    205:
                    206:                if (fgets(answer, sizeof(answer), stdin) == 0) {
                    207:                        if (dflt == 0) {
                    208:                                (void)fprintf(stderr, "\n");
                    209:                                exit(EXIT_FAILURE);
                    210:                        }
                    211:                        return (dflt);
                    212:                }
                    213:
                    214:                if ((p = strchr(answer, '\n')) != 0)
                    215:                        *p = '\0';
                    216:                if (answer[0])
                    217:                        return (answer);
                    218:                if (dflt != 0)
                    219:                        return (dflt);
                    220:        }
                    221: }
                    222:
                    223: /**************************************************************************
                    224:  *
                    225:  * Mapping logic begins here
                    226:  *
                    227:  **************************************************************************/
                    228:
                    229: /* Baud rate conditionals for mapping. */
                    230: #define        GT              0x01
                    231: #define        EQ              0x02
                    232: #define        LT              0x04
                    233: #define        NOT             0x08
                    234: #define        GE              (GT | EQ)
                    235: #define        LE              (LT | EQ)
                    236:
                    237: typedef struct map {
                    238:        struct map *next;       /* Linked list of maps. */
                    239:        const char *porttype;   /* Port type, or "" for any. */
                    240:        const char *type;       /* Terminal type to select. */
                    241:        int conditional;        /* Baud rate conditionals bitmask. */
                    242:        speed_t speed;          /* Baud rate to compare against. */
                    243: } MAP;
                    244:
                    245: static MAP *cur, *maplist;
                    246:
                    247: typedef struct speeds {
                    248:        const char *string;
                    249:        int     speed;
                    250: } SPEEDS;
                    251:
                    252: static const SPEEDS speeds[] = {
                    253:        { "0",          B0 },
                    254:        { "50",         B50 },
                    255:        { "75",         B75 },
                    256:        { "110",        B110 },
                    257:        { "134",        B134 },
                    258:        { "134.5",      B134 },
                    259:        { "150",        B150 },
                    260:        { "200",        B200 },
                    261:        { "300",        B300 },
                    262:        { "600",        B600 },
                    263:        { "1200",       B1200 },
                    264:        { "1800",       B1800 },
                    265:        { "2400",       B2400 },
                    266:        { "4800",       B4800 },
                    267:        { "9600",       B9600 },
                    268:        { "19200",      B19200 },
                    269:        { "38400",      B38400 },
                    270:        { "19200",      B19200 },
                    271:        { "38400",      B38400 },
                    272: #ifdef B19200
                    273:        { "19200",      B19200 },
                    274: #else
                    275: #ifdef EXTA
                    276:        { "19200",      EXTA },
                    277: #endif
                    278: #endif
                    279: #ifdef B38400
                    280:        { "38400",      B38400 },
                    281: #else
                    282: #ifdef EXTB
                    283:        { "38400",      EXTB },
                    284: #endif
                    285: #endif
                    286: #ifdef B57600
                    287:        { "57600",      B57600 },
                    288: #endif
                    289: #ifdef B115200
                    290:        { "115200",     B115200 },
                    291: #endif
                    292: #ifdef B230400
                    293:        { "230400",     B230400 },
                    294: #endif
                    295: #ifdef B460800
                    296:        { "460800",     B460800 },
                    297: #endif
                    298:        { (char *)0,    0 }
                    299: };
                    300:
                    301: static int
                    302: tbaudrate(char *rate)
                    303: {
                    304:        const SPEEDS *sp;
                    305:        int found = FALSE;
                    306:
                    307:        /* The baudrate number can be preceded by a 'B', which is ignored. */
                    308:        if (*rate == 'B')
                    309:                ++rate;
                    310:
                    311:        for (sp = speeds; sp->string; ++sp) {
                    312:                if (!CaselessCmp(rate, sp->string)) {
                    313:                        found = TRUE;
                    314:                        break;
                    315:                }
                    316:        }
                    317:        if (!found)
                    318:                err("unknown baud rate %s", rate);
                    319:        return (sp->speed);
                    320: }
                    321:
                    322: /*
                    323:  * Syntax for -m:
                    324:  * [port-type][test baudrate]:terminal-type
                    325:  * The baud rate tests are: >, <, @, =, !
                    326:  */
                    327: static void
                    328: add_mapping(const char *port, char *arg)
                    329: {
                    330:        MAP *mapp;
                    331:        char *copy, *p;
                    332:        const char *termp;
                    333:        char *base = 0;
                    334:
                    335:        copy = strdup(arg);
1.11      millert   336:        mapp = malloc(sizeof(MAP));
1.7       millert   337:        if (copy == 0 || mapp == 0)
                    338:                failed("malloc");
                    339:        mapp->next = 0;
                    340:        if (maplist == 0)
                    341:                cur = maplist = mapp;
                    342:        else {
                    343:                cur->next = mapp;
                    344:                cur =  mapp;
                    345:        }
                    346:
                    347:        mapp->porttype = arg;
                    348:        mapp->conditional = 0;
                    349:
                    350:        arg = strpbrk(arg, "><@=!:");
                    351:
                    352:        if (arg == 0) {                 /* [?]term */
                    353:                mapp->type = mapp->porttype;
                    354:                mapp->porttype = 0;
                    355:                goto done;
                    356:        }
                    357:
                    358:        if (arg == mapp->porttype)              /* [><@=! baud]:term */
                    359:                termp = mapp->porttype = 0;
                    360:        else
                    361:                termp = base = arg;
                    362:
                    363:        for (;; ++arg)                          /* Optional conditionals. */
                    364:                switch(*arg) {
                    365:                case '<':
                    366:                        if (mapp->conditional & GT)
                    367:                                goto badmopt;
                    368:                        mapp->conditional |= LT;
                    369:                        break;
                    370:                case '>':
                    371:                        if (mapp->conditional & LT)
                    372:                                goto badmopt;
                    373:                        mapp->conditional |= GT;
                    374:                        break;
                    375:                case '@':
                    376:                case '=':                       /* Not documented. */
                    377:                        mapp->conditional |= EQ;
                    378:                        break;
                    379:                case '!':
                    380:                        mapp->conditional |= NOT;
                    381:                        break;
                    382:                default:
                    383:                        goto next;
                    384:                }
                    385:
                    386: next:  if (*arg == ':') {
                    387:                if (mapp->conditional)
                    388:                        goto badmopt;
                    389:                ++arg;
                    390:        } else {                                /* Optional baudrate. */
                    391:                arg = strchr(p = arg, ':');
                    392:                if (arg == 0)
                    393:                        goto badmopt;
                    394:                *arg++ = '\0';
                    395:                mapp->speed = tbaudrate(p);
                    396:        }
                    397:
                    398:        if (arg == (char *)0)           /* Non-optional type. */
                    399:                goto badmopt;
                    400:
                    401:        mapp->type = arg;
                    402:
                    403:        /* Terminate porttype, if specified. */
                    404:        if (termp != 0)
                    405:                *base = '\0';
                    406:
                    407:        /* If a NOT conditional, reverse the test. */
                    408:        if (mapp->conditional & NOT)
                    409:                mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
                    410:
                    411:        /* If user specified a port with an option flag, set it. */
                    412: done:  if (port) {
                    413:                if (mapp->porttype)
                    414: badmopt:               err("illegal -m option format: %s", copy);
                    415:                mapp->porttype = port;
                    416:        }
                    417:
                    418: #ifdef MAPDEBUG
                    419:        (void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
                    420:        (void)printf("type: %s\n", mapp->type);
                    421:        (void)printf("conditional: ");
                    422:        p = "";
                    423:        if (mapp->conditional & GT) {
                    424:                (void)printf("GT");
                    425:                p = "/";
                    426:        }
                    427:        if (mapp->conditional & EQ) {
                    428:                (void)printf("%sEQ", p);
                    429:                p = "/";
                    430:        }
                    431:        if (mapp->conditional & LT)
                    432:                (void)printf("%sLT", p);
                    433:        (void)printf("\nspeed: %d\n", mapp->speed);
                    434: #endif
                    435: }
                    436:
                    437: /*
                    438:  * Return the type of terminal to use for a port of type 'type', as specified
                    439:  * by the first applicable mapping in 'map'.  If no mappings apply, return
                    440:  * 'type'.
                    441:  */
                    442: static const char *
                    443: mapped(const char *type)
                    444: {
                    445:        MAP *mapp;
                    446:        int match;
                    447:
                    448:        for (mapp = maplist; mapp; mapp = mapp->next)
                    449:                if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
                    450:                        switch (mapp->conditional) {
                    451:                        case 0:                 /* No test specified. */
                    452:                                match = TRUE;
                    453:                                break;
                    454:                        case EQ:
                    455:                                match = (ospeed == mapp->speed);
                    456:                                break;
                    457:                        case GE:
                    458:                                match = (ospeed >= mapp->speed);
                    459:                                break;
                    460:                        case GT:
                    461:                                match = (ospeed > mapp->speed);
                    462:                                break;
                    463:                        case LE:
                    464:                                match = (ospeed <= mapp->speed);
                    465:                                break;
                    466:                        case LT:
                    467:                                match = (ospeed < mapp->speed);
                    468:                                break;
                    469:                        default:
                    470:                                match = FALSE;
                    471:                        }
                    472:                        if (match)
                    473:                                return (mapp->type);
                    474:                }
                    475:        /* No match found; return given type. */
                    476:        return (type);
                    477: }
                    478:
                    479: /**************************************************************************
                    480:  *
                    481:  * Entry fetching
                    482:  *
                    483:  **************************************************************************/
                    484:
                    485: /*
                    486:  * Figure out what kind of terminal we're dealing with, and then read in
                    487:  * its termcap entry.
                    488:  */
                    489: static const char *
                    490: get_termcap_entry(char *userarg)
                    491: {
                    492:        int rval, errret;
                    493:        char *p;
                    494:        const char *ttype;
                    495: #if HAVE_GETTTYNAM
                    496:        struct ttyent *t;
                    497: #else
                    498:        FILE *fp;
                    499: #endif
                    500:        char *ttypath;
                    501:
                    502:        if (userarg) {
                    503:                ttype = userarg;
                    504:                goto found;
                    505:        }
                    506:
                    507:        /* Try the environment. */
                    508:        if ((ttype = getenv("TERM")) != 0)
                    509:                goto map;
                    510:
                    511:        if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
                    512:                if ((p = strrchr(ttypath, '/')) != 0)
                    513:                        ++p;
                    514:                else
                    515:                        p = ttypath;
                    516: #if HAVE_GETTTYNAM
                    517:                /*
                    518:                 * We have the 4.3BSD library call getttynam(3); that means
                    519:                 * there's an /etc/ttys to look up device-to-type mappings in.
                    520:                 * Try ttyname(3); check for dialup or other mapping.
                    521:                 */
                    522:                if ((t = getttynam(p))) {
                    523:                        ttype = t->ty_type;
                    524:                        goto map;
                    525:                }
                    526: #else
                    527:                if ((fp = fopen("/etc/ttytype", "r")) != 0
                    528:                 || (fp = fopen("/etc/ttys", "r")) != 0) {
                    529:                        char buffer[BUFSIZ];
                    530:                        char *s, *t, *d;
                    531:
                    532:                        while (fgets(buffer, sizeof(buffer)-1, fp) != 0) {
                    533:                                for (s = buffer, t = d = 0; *s; s++) {
                    534:                                        if (isspace(*s))
                    535:                                                *s = '\0';
                    536:                                        else if (t == 0)
                    537:                                                t = s;
                    538:                                        else if (d == 0 && s != buffer && s[-1] == '\0')
                    539:                                                d = s;
                    540:                                }
                    541:                                if (t != 0 && d != 0 && !strcmp(d,p)) {
                    542:                                        ttype = strdup(t);
                    543:                                        fclose(fp);
                    544:                                        goto map;
                    545:                                }
                    546:                        }
                    547:                        fclose(fp);
                    548:                }
                    549: #endif /* HAVE_GETTTYNAM */
                    550:        }
                    551:
                    552:        /* If still undefined, use "unknown". */
                    553:        ttype = "unknown";
                    554:
                    555: map:   ttype = mapped(ttype);
                    556:
                    557:        /*
                    558:         * If not a path, remove TERMCAP from the environment so we get a
                    559:         * real entry from /etc/termcap.  This prevents us from being fooled
                    560:         * by out of date stuff in the environment.
                    561:         */
                    562: found: if ((p = getenv("TERMCAP")) != 0 && *p != '/') {
                    563:                /* 'unsetenv("TERMCAP")' is not portable.
                    564:                 * The 'environ' array is better.
                    565:                 */
                    566:                int n;
                    567:                for (n = 0; environ[n] != 0; n++) {
                    568:                        if (!strncmp("TERMCAP=", environ[n], 8)) {
                    569:                                while ((environ[n] = environ[n+1]) != 0) {
                    570:                                        n++;
                    571:                                }
                    572:                                break;
                    573:                        }
                    574:                }
                    575:        }
                    576:
                    577:        /*
                    578:         * ttype now contains a pointer to the type of the terminal.
                    579:         * If the first character is '?', ask the user.
                    580:         */
                    581:        if (ttype[0] == '?') {
                    582:                if (ttype[1] != '\0')
                    583:                        ttype = askuser(ttype + 1);
                    584:                else
                    585:                        ttype = askuser(0);
                    586:        }
                    587:        /* Find the terminfo entry.  If it doesn't exist, ask the user. */
1.11      millert   588:        while ((rval = setupterm((NCURSES_CONST char *)ttype, STDOUT_FILENO, &errret)) != OK) {
1.7       millert   589:                if (errret == 0) {
                    590:                        (void)fprintf(stderr, "tset: unknown terminal type %s\n",
                    591:                            ttype);
                    592:                        ttype = 0;
                    593:                }
                    594:                else {
1.12      millert   595:                        (void)fprintf(stderr, "tset: can't initialize terminal type %s (error %d)\n", ttype, errret);
1.7       millert   596:                        ttype = 0;
                    597:                }
                    598:                ttype = askuser(ttype);
                    599:        }
                    600: #if BROKEN_LINKER
                    601:        tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */
                    602: #endif
                    603:        return (ttype);
                    604: }
                    605:
                    606: /**************************************************************************
                    607:  *
                    608:  * Mode-setting logic
                    609:  *
                    610:  **************************************************************************/
                    611:
                    612: /* some BSD systems have these built in, some systems are missing
                    613:  * one or more definitions. The safest solution is to override.
                    614:  */
                    615: #undef CEOF
                    616: #undef CERASE
                    617: #undef CINTR
                    618: #undef CKILL
                    619: #undef CLNEXT
                    620: #undef CRPRNT
                    621: #undef CQUIT
                    622: #undef CSTART
                    623: #undef CSTOP
                    624: #undef CSUSP
                    625:
                    626: /* control-character defaults */
                    627: #define CEOF   CTRL('D')
                    628: #define CERASE CTRL('H')
                    629: #define CINTR  127             /* ^? */
                    630: #define CKILL  CTRL('U')
                    631: #define CLNEXT  CTRL('v')
                    632: #define CRPRNT  CTRL('r')
                    633: #define CQUIT  CTRL('\\')
                    634: #define CSTART CTRL('Q')
                    635: #define CSTOP  CTRL('S')
                    636: #define CSUSP  CTRL('Z')
                    637:
                    638: #define        CHK(val, dft)   ((int)val <= 0 ? dft : val)
                    639:
                    640: static bool    set_tabs (void);
                    641:
                    642: /*
                    643:  * Reset the terminal mode bits to a sensible state.  Very useful after
                    644:  * a child program dies in raw mode.
                    645:  */
                    646: static void
                    647: reset_mode(void)
                    648: {
                    649: #ifdef TERMIOS
                    650:        tcgetattr(STDERR_FILENO, &mode);
                    651: #else
                    652:        stty(STDERR_FILENO,&mode);
                    653: #endif
                    654:
                    655: #ifdef TERMIOS
                    656: #if defined(VDISCARD) && defined(CDISCARD)
                    657:        mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
                    658: #endif
                    659:        mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
                    660:        mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
                    661: #if defined(VFLUSH) && defined(CFLUSH)
                    662:        mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
                    663: #endif
                    664:        mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
                    665:        mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
                    666: #if defined(VLNEXT) && defined(CLNEXT)
                    667:        mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
                    668: #endif
                    669:        mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
                    670: #if defined(VREPRINT) && defined(CRPRNT)
                    671:        mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
                    672: #endif
                    673: #if defined(VSTART) && defined(CSTART)
                    674:        mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
                    675: #endif
                    676: #if defined(VSTOP) && defined(CSTOP)
                    677:        mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
                    678: #endif
                    679: #if defined(VSUSP) && defined(CSUSP)
                    680:        mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
                    681: #endif
                    682: #if defined(VWERASE) && defined(CWERASE)
                    683:        mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
                    684: #endif
                    685:
                    686:        mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
                    687: #ifdef IUCLC
                    688:                          | IUCLC
                    689: #endif
                    690: #ifdef IXANY
                    691:                          | IXANY
                    692: #endif
                    693:                          | IXOFF);
                    694:
                    695:        mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
                    696: #ifdef IMAXBEL
                    697:                         | IMAXBEL
                    698: #endif
                    699:                         );
                    700:
                    701:        mode.c_oflag &= ~(0
                    702: #ifdef OLCUC
                    703:                          | OLCUC
                    704: #endif
                    705: #ifdef OCRNL
                    706:                          | OCRNL
                    707: #endif
                    708: #ifdef ONOCR
                    709:                          | ONOCR
                    710: #endif
                    711: #ifdef ONLRET
                    712:                          | ONLRET
                    713: #endif
                    714: #ifdef OFILL
                    715:                          | OFILL
                    716: #endif
                    717: #ifdef OFDEL
                    718:                          | OFDEL
                    719: #endif
                    720: #ifdef NLDLY
                    721:                          | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY
                    722: #endif
                    723:                          );
                    724:
                    725:        mode.c_oflag |= (OPOST
                    726: #ifdef ONLCR
                    727:                         | ONLCR
                    728: #endif
                    729:                         );
                    730:
                    731:        mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
                    732:        mode.c_cflag |= (CS8 | CREAD);
                    733:        mode.c_lflag &= ~(ECHONL | NOFLSH
                    734: #ifdef TOSTOP
                    735:                          | TOSTOP
                    736: #endif
                    737: #ifdef ECHOPTR
                    738:                          | ECHOPRT
                    739: #endif
                    740: #ifdef XCASE
                    741:                          | XCASE
                    742: #endif
                    743:                          );
                    744:
                    745:        mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
                    746: #ifdef ECHOCTL
                    747:                         | ECHOCTL
                    748: #endif
                    749: #ifdef ECHOKE
                    750:                         | ECHOKE
                    751: #endif
                    752:                         );
                    753: #endif
                    754:
                    755: #ifdef TERMIOS
                    756:        tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
                    757: #else
                    758:        stty(STDERR_FILENO, &mode);
                    759: #endif
                    760: }
                    761:
                    762: /*
                    763:  * Returns a "good" value for the erase character.  This is loosely based on
                    764:  * the BSD4.4 logic.
                    765:  */
                    766: static int
                    767: default_erase(void)
                    768: {
                    769:        int result;
                    770:
                    771:        if (over_strike
                    772:         && key_backspace != 0
                    773:         && strlen(key_backspace) == 1)
                    774:                result = key_backspace[0];
                    775:        else
                    776:                result = CERASE;
                    777:
                    778:        return result;
                    779: }
                    780:
                    781: /*
                    782:  * Update the values of the erase, interrupt, and kill characters in 'mode'.
                    783:  *
                    784:  * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
                    785:  * characters if they're unset, or if we specify them as options.  This differs
                    786:  * from BSD 4.4 tset, which always sets erase.
                    787:  */
                    788: static void
                    789: set_control_chars(void)
                    790: {
                    791: #ifdef TERMIOS
                    792:        if (mode.c_cc[VERASE] == 0 || terasechar >= 0)
                    793:                mode.c_cc[VERASE] = terasechar >= 0 ? terasechar : default_erase();
                    794:
                    795:        if (mode.c_cc[VINTR] == 0 || intrchar >= 0)
                    796:                 mode.c_cc[VINTR] = intrchar >= 0 ? intrchar : CINTR;
                    797:
                    798:        if (mode.c_cc[VKILL] == 0 || tkillchar >= 0)
                    799:                mode.c_cc[VKILL] = tkillchar >= 0 ? tkillchar : CKILL;
                    800: #endif
                    801: }
                    802:
                    803: /*
                    804:  * Set up various conversions in 'mode', including parity, tabs, returns,
                    805:  * echo, and case, according to the termcap entry.  If the program we're
                    806:  * running was named with a leading upper-case character, map external
                    807:  * uppercase to internal lowercase.
                    808:  */
                    809: static void
                    810: set_conversions(void)
                    811: {
                    812: #ifdef __OBSOLETE__
                    813:        /*
                    814:         * Conversion logic for some *really* ancient terminal glitches,
                    815:         * not supported in terminfo.  Left here for succeeding generations
                    816:         * to marvel at.
                    817:         */
                    818:        if (tgetflag("UC")) {
                    819: #ifdef IUCLC
                    820:                mode.c_iflag |= IUCLC;
                    821:                mode.c_oflag |= OLCUC;
                    822: #endif
                    823:        } else if (tgetflag("LC")) {
                    824: #ifdef IUCLC
                    825:                mode.c_iflag &= ~IUCLC;
                    826:                mode.c_oflag &= ~OLCUC;
                    827: #endif
                    828:        }
                    829:        mode.c_iflag &= ~(PARMRK | INPCK);
                    830:        mode.c_lflag |= ICANON;
                    831:        if (tgetflag("EP")) {
                    832:                mode.c_cflag |= PARENB;
                    833:                mode.c_cflag &= ~PARODD;
                    834:        }
                    835:        if (tgetflag("OP")) {
                    836:                mode.c_cflag |= PARENB;
                    837:                mode.c_cflag |= PARODD;
                    838:        }
                    839: #endif /* __OBSOLETE__ */
                    840:
                    841: #ifdef TERMIOS
                    842: #ifdef ONLCR
                    843:        mode.c_oflag |= ONLCR;
                    844: #endif
                    845:        mode.c_iflag |= ICRNL;
                    846:        mode.c_lflag |= ECHO;
                    847: #ifdef OXTABS
                    848:        mode.c_oflag |= OXTABS;
                    849: #endif /* OXTABS */
                    850:
                    851:        /* test used to be tgetflag("NL") */
                    852:        if (newline != (char *)0 && newline[0] == '\n' && !newline[1]) {
                    853:                /* Newline, not linefeed. */
                    854: #ifdef ONLCR
                    855:                mode.c_oflag &= ~ONLCR;
                    856: #endif
                    857:                mode.c_iflag &= ~ICRNL;
                    858:        }
                    859: #ifdef __OBSOLETE__
                    860:        if (tgetflag("HD"))                     /* Half duplex. */
                    861:                mode.c_lflag &= ~ECHO;
                    862: #endif /* __OBSOLETE__ */
                    863: #ifdef OXTABS
                    864:        /* test used to be tgetflag("pt") */
                    865:        if (has_hardware_tabs)                  /* Print tabs. */
                    866:                mode.c_oflag &= ~OXTABS;
                    867: #endif /* OXTABS */
                    868:        mode.c_lflag |= (ECHOE | ECHOK);
                    869: #endif
                    870: }
                    871:
                    872: /* Output startup string. */
                    873: static void
                    874: set_init(void)
                    875: {
                    876:        char    *p;
                    877:        bool settle;
                    878:
                    879: #ifdef __OBSOLETE__
                    880:        if (pad_char != (char *)0)              /* Get/set pad character. */
                    881:                PC = pad_char[0];
                    882: #endif /* OBSOLETE */
                    883:
                    884: #ifdef TAB3
                    885:        if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
                    886:                oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
                    887:                tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode);
                    888:        }
                    889: #endif
                    890:        settle = set_tabs();
                    891:
                    892:        if (isreset) {
                    893:                if ((p = reset_1string) != 0) {
                    894:                        tputs(p, 0, outc);
                    895:                        settle = TRUE;
                    896:                }
                    897:                if ((p = reset_2string) != 0) {
                    898:                        tputs(p, 0, outc);
                    899:                        settle = TRUE;
                    900:                }
                    901:                /* What about rf, rs3, as per terminfo man page? */
                    902:                /* also might be nice to send rmacs, rmul, rmm */
                    903:                if ((p = reset_file) != 0
                    904:                 || (p = init_file) != 0) {
                    905:                        cat(p);
                    906:                        settle = TRUE;
                    907:                }
                    908:        }
                    909:
                    910:        if (settle) {
                    911:                (void)putc('\r', stderr);
                    912:                (void)fflush(stderr);
                    913:                (void)napms(1000);      /* Settle the terminal. */
                    914:        }
                    915: }
                    916:
                    917: /*
                    918:  * Set the hardware tabs on the terminal, using the ct (clear all tabs),
                    919:  * st (set one tab) and ch (horizontal cursor addressing) capabilities.
                    920:  * This is done before if and is, so they can patch in case we blow this.
                    921:  * Return TRUE if we set any tab stops, FALSE if not.
                    922:  */
                    923: static bool
                    924: set_tabs()
                    925: {
                    926:        if (set_tab && clear_all_tabs) {
                    927:                int c;
                    928:
                    929:                (void)putc('\r', stderr);       /* Force to left margin. */
                    930:                tputs(clear_all_tabs, 0, outc);
                    931:
                    932:                for (c = 8; c < tcolumns; c += 8) {
                    933:                        /* Get to the right column.  In BSD tset, this
                    934:                         * used to try a bunch of half-clever things
                    935:                         * with cup and hpa, for an average saving of
                    936:                         * somewhat less than two character times per
                    937:                         * tab stop, less that .01 sec at 2400cps. We
                    938:                         * lost all this cruft because it seemed to be
                    939:                         * introducing some odd bugs.
                    940:                         * ----------12345678----------- */
                    941:                        (void)fputs("        ", stderr);
                    942:                        tputs(set_tab, 0, outc);
                    943:                }
                    944:                putc('\r', stderr);
                    945:                return (TRUE);
                    946:        }
                    947:        return (FALSE);
                    948: }
                    949:
                    950: /**************************************************************************
                    951:  *
                    952:  * Main sequence
                    953:  *
                    954:  **************************************************************************/
                    955:
                    956: /*
                    957:  * Tell the user if a control key has been changed from the default value.
                    958:  */
                    959: static void
1.11      millert   960: report(const char *name, int which, unsigned def)
1.7       millert   961: {
                    962: #ifdef TERMIOS
1.11      millert   963:        unsigned older, newer;
1.7       millert   964:        char *p;
                    965:
                    966:        newer = mode.c_cc[which];
                    967:        older = oldmode.c_cc[which];
                    968:
                    969:        if (older == newer && older == def)
                    970:                return;
                    971:
                    972:        (void)fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to");
                    973:
                    974:        /*
                    975:         * Check 'delete' before 'backspace', since the key_backspace value
                    976:         * is ambiguous.
                    977:         */
                    978:        if (newer == 0177)
                    979:                (void)fprintf(stderr, "delete.\n");
                    980:        else if ((p = key_backspace) != 0
1.11      millert   981:         && newer == (unsigned char)p[0]
1.7       millert   982:         && p[1] == '\0')
                    983:                (void)fprintf(stderr, "backspace.\n");
                    984:        else if (newer < 040) {
                    985:                newer ^= 0100;
                    986:                (void)fprintf(stderr, "control-%c (^%c).\n", newer, newer);
                    987:        } else
                    988:                (void)fprintf(stderr, "%c.\n", newer);
                    989: #endif
                    990: }
                    991:
                    992: /*
                    993:  * Convert the obsolete argument forms into something that getopt can handle.
                    994:  * This means that -e, -i and -k get default arguments supplied for them.
                    995:  */
                    996: static void
                    997: obsolete(char **argv)
                    998: {
                    999:        for (; *argv; ++argv) {
                   1000:                char *parm = argv[0];
                   1001:
                   1002:                if (parm[0] == '-' && parm[1] == '\0')
                   1003:                {
                   1004:                    argv[0] = strdup("-q");
                   1005:                    continue;
                   1006:                }
                   1007:
                   1008:                if ((parm[0] != '-')
                   1009:                 || (argv[1] && argv[1][0] != '-')
                   1010:                 || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
                   1011:                 || (parm[2] != '\0'))
                   1012:                        continue;
                   1013:                switch(argv[0][1]) {
                   1014:                case 'e':
                   1015:                        argv[0] = strdup("-e^H");
                   1016:                        break;
                   1017:                case 'i':
                   1018:                        argv[0] = strdup("-i^C");
                   1019:                        break;
                   1020:                case 'k':
                   1021:                        argv[0] = strdup("-k^U");
                   1022:                        break;
                   1023:                }
                   1024:        }
                   1025: }
                   1026:
                   1027: static void
                   1028: usage(const char* pname)
                   1029: {
                   1030:        (void)fprintf(stderr,
                   1031: "usage: %s [-IQrs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n", pname);
                   1032:        exit(EXIT_FAILURE);
                   1033: }
                   1034:
                   1035: static char arg_to_char(void)
                   1036: {
                   1037:        return (optarg[0] == '^' && optarg[1] != '\0')
                   1038:                ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
                   1039:                : optarg[0];
                   1040: }
1.1       deraadt  1041:
                   1042: int
1.7       millert  1043: main(int argc, char **argv)
1.1       deraadt  1044: {
1.7       millert  1045: #if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
1.1       deraadt  1046:        struct winsize win;
                   1047: #endif
1.7       millert  1048:        int ch, noinit, noset, quiet, Sflag, sflag, showterm;
1.11      millert  1049:        const char *p;
1.7       millert  1050:        const char *ttype;
                   1051: #ifdef __OpenBSD__
1.11      millert  1052:        char tcapbuf[1024], *t;
1.7       millert  1053:        int tcgetent(char *, const char *);
                   1054:        void wrtermcap (char *);
                   1055: #endif
1.1       deraadt  1056:
1.7       millert  1057: #ifdef TERMIOS
1.1       deraadt  1058:        if (tcgetattr(STDERR_FILENO, &mode) < 0)
1.7       millert  1059:                failed("standard error");
1.1       deraadt  1060:
                   1061:        oldmode = mode;
                   1062:        ospeed = cfgetospeed(&mode);
1.7       millert  1063: #else
                   1064:        if (gtty(STDERR_FILENO, &mode) < 0)
                   1065:                failed("standard error");
                   1066:
                   1067:        oldmode = mode;
                   1068:        ospeed = mode.sg_ospeed;
                   1069: #endif
1.1       deraadt  1070:
1.7       millert  1071:        if ((p = strrchr(*argv, '/')) != 0)
1.1       deraadt  1072:                ++p;
                   1073:        else
                   1074:                p = *argv;
1.7       millert  1075:        if (!CaselessCmp(p, "reset")) {
1.1       deraadt  1076:                isreset = 1;
                   1077:                reset_mode();
                   1078:        }
                   1079:
                   1080:        obsolete(argv);
                   1081:        noinit = noset = quiet = Sflag = sflag = showterm = 0;
1.14      aaron    1082:        while ((ch = getopt(argc, argv, "a:d:e:Ii:k:m:np:qQSrs")) != -1) {
1.1       deraadt  1083:                switch (ch) {
1.7       millert  1084:                case 'q':               /* display term only */
1.1       deraadt  1085:                        noset = 1;
                   1086:                        break;
                   1087:                case 'a':               /* OBSOLETE: map identifier to type */
                   1088:                        add_mapping("arpanet", optarg);
                   1089:                        break;
                   1090:                case 'd':               /* OBSOLETE: map identifier to type */
                   1091:                        add_mapping("dialup", optarg);
                   1092:                        break;
                   1093:                case 'e':               /* erase character */
1.7       millert  1094:                        terasechar = arg_to_char();
1.1       deraadt  1095:                        break;
                   1096:                case 'I':               /* no initialization strings */
                   1097:                        noinit = 1;
                   1098:                        break;
                   1099:                case 'i':               /* interrupt character */
1.7       millert  1100:                        intrchar = arg_to_char();
1.1       deraadt  1101:                        break;
                   1102:                case 'k':               /* kill character */
1.7       millert  1103:                        tkillchar = arg_to_char();
1.1       deraadt  1104:                        break;
                   1105:                case 'm':               /* map identifier to type */
1.7       millert  1106:                        add_mapping(0, optarg);
1.1       deraadt  1107:                        break;
                   1108:                case 'n':               /* OBSOLETE: set new tty driver */
                   1109:                        break;
                   1110:                case 'p':               /* OBSOLETE: map identifier to type */
                   1111:                        add_mapping("plugboard", optarg);
                   1112:                        break;
                   1113:                case 'Q':               /* don't output control key settings */
1.10      tholo    1114:                        quiet = 1;
1.7       millert  1115:                        break;
                   1116:                case 'S':               /* OBSOLETE: output TERM & TERMCAP */
1.1       deraadt  1117:                        Sflag = 1;
                   1118:                        break;
                   1119:                case 'r':               /* display term on stderr */
                   1120:                        showterm = 1;
                   1121:                        break;
1.7       millert  1122:                case 's':               /* output TERM set command */
1.1       deraadt  1123:                        sflag = 1;
                   1124:                        break;
                   1125:                case '?':
                   1126:                default:
1.7       millert  1127:                        usage(*argv);
1.1       deraadt  1128:                }
                   1129:        }
                   1130:        argc -= optind;
                   1131:        argv += optind;
                   1132:
                   1133:        if (argc > 1)
1.7       millert  1134:                usage(*argv);
1.1       deraadt  1135:
1.7       millert  1136:        ttype = get_termcap_entry(*argv);
                   1137: #ifdef __OpenBSD__
                   1138:        if (tcgetent(tcapbuf, ttype) < 0)
                   1139:                tcapbuf[0] = '\0';
                   1140: #endif
1.1       deraadt  1141:
                   1142:        if (!noset) {
1.7       millert  1143:                tcolumns = columns;
                   1144:                tlines = lines;
1.1       deraadt  1145:
1.7       millert  1146: #if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
1.1       deraadt  1147:                /* Set window size */
                   1148:                (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
                   1149:                if (win.ws_row == 0 && win.ws_col == 0 &&
1.7       millert  1150:                    tlines > 0 && tcolumns > 0) {
                   1151:                        win.ws_row = tlines;
                   1152:                        win.ws_col = tcolumns;
1.1       deraadt  1153:                        (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
                   1154:                }
                   1155: #endif
                   1156:                set_control_chars();
1.7       millert  1157:                set_conversions();
1.1       deraadt  1158:
                   1159:                if (!noinit)
                   1160:                        set_init();
                   1161:
                   1162:                /* Set the modes if they've changed. */
                   1163:                if (memcmp(&mode, &oldmode, sizeof(mode)))
1.7       millert  1164: #ifdef TERMIOS
1.1       deraadt  1165:                        tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
1.7       millert  1166: #else
                   1167:                        stty(STDERR_FILENO, &mode);
                   1168: #endif
1.1       deraadt  1169:        }
                   1170:
                   1171:        /* Get the terminal name from the entry. */
1.7       millert  1172:        ttype = _nc_first_name(cur_term->type.term_names);
1.1       deraadt  1173:
                   1174:        if (noset)
                   1175:                (void)printf("%s\n", ttype);
                   1176:        else {
                   1177:                if (showterm)
                   1178:                        (void)fprintf(stderr, "Terminal type is %s.\n", ttype);
                   1179:                /*
                   1180:                 * If erase, kill and interrupt characters could have been
                   1181:                 * modified and not -Q, display the changes.
                   1182:                 */
                   1183:                if (!quiet) {
                   1184:                        report("Erase", VERASE, CERASE);
1.7       millert  1185:                        report("Kill", VKILL, CINTR);
                   1186:                        report("Interrupt", VINTR, CKILL);
1.1       deraadt  1187:                }
                   1188:        }
                   1189:
1.7       millert  1190: #ifdef __OpenBSD__
1.1       deraadt  1191:        if (Sflag) {
1.7       millert  1192:                if (tcapbuf[0]) {
                   1193:                        (void) printf("%s ", ttype);
1.6       millert  1194:                        wrtermcap(tcapbuf);
1.7       millert  1195:                } else
                   1196:                        err("No termcap entry for %s, only terminfo.", ttype);
1.1       deraadt  1197:        }
1.7       millert  1198: #else
                   1199:        if (Sflag)
                   1200:                err("The -S option is not supported under terminfo.");
                   1201: #endif /* __OpenBSD__ */
1.1       deraadt  1202:
1.7       millert  1203: #ifdef __OpenBSD__
1.1       deraadt  1204:        if (sflag) {
                   1205:                /*
                   1206:                 * Figure out what shell we're using.  A hack, we look for an
                   1207:                 * environmental variable SHELL ending in "csh".
                   1208:                 */
1.7       millert  1209:                if ((p = getenv("SHELL")) != 0
                   1210:                 && !strcmp(p + strlen(p) - 3, "csh")) {
                   1211:                        if (tcapbuf[0])
1.6       millert  1212:                                p = "set noglob histchars="";\nsetenv TERM %s;\nsetenv TERMCAP ";
                   1213:                        else
                   1214:                                p = "set noglob histchars="";\nsetenv TERM %s;\n";
1.7       millert  1215:                                t = "unset noglob histchars;\n";
1.1       deraadt  1216:                } else {
1.6       millert  1217:                        if (tcapbuf) {
                   1218:                                p = "TERM=%s;\nTERMCAP=";
                   1219:                                t = "export TERMCAP TERM;\n";
                   1220:                        } else {
1.7       millert  1221:                                if (tcapbuf) {
                   1222:                                        p = "TERM=%s;\nTERMCAP=";
                   1223:                                        t = "export TERMCAP TERM;\n";
                   1224:                                } else {
                   1225:                                        p = "TERM=%s;\n";
                   1226:                                        t = "export TERMCAP;\n";
                   1227:                                }
1.6       millert  1228:                        }
1.1       deraadt  1229:                }
1.7       millert  1230:                (void) printf(p, ttype);
                   1231:                if (tcapbuf[0]) {
1.6       millert  1232:                        putchar('\'');
                   1233:                        wrtermcap(tcapbuf);
                   1234:                        fputs("';\n", stdout);
                   1235:                }
1.9       millert  1236:                (void)printf(t);
1.1       deraadt  1237:        }
1.7       millert  1238: #else
                   1239:        if (sflag) {
                   1240:                /*
                   1241:                 * Figure out what shell we're using.  A hack, we look for an
                   1242:                 * environmental variable SHELL ending in "csh".
                   1243:                 */
                   1244:                if ((p = getenv("SHELL")) != 0
                   1245:                 && !strcmp(p + strlen(p) - 3, "csh"))
                   1246:                        p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
                   1247:                else
                   1248:                        p = "TERM=%s;\n";
                   1249:                (void) printf(p, ttype);
                   1250:        }
                   1251: #endif /* __OpenBSD__ */
1.1       deraadt  1252:
1.7       millert  1253:        return EXIT_SUCCESS;
1.1       deraadt  1254: }
                   1255:
1.7       millert  1256: /* tset.c ends here */