[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.18

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