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

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