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

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