]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - progs/tset.c
ncurses 6.0 - patch 20170729
[ncurses.git] / progs / tset.c
index 1df3fd64986923cdb79957030eefbd81dd91b315..d660d84d0f21787787eb24dccaee93a0d1e25bf9 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998 Free Software Foundation, Inc.                        *
+ * Copyright (c) 1998-2016,2017 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
 /****************************************************************************
  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
+ *     and: Thomas E. Dickey                        1996-on                 *
  ****************************************************************************/
 
+/*
+ * Notes:
+ * The initial adaptation from 4.4BSD Lite sources in September 1995 used 686
+ * lines from that version, and made changes/additions for 150 lines.  There
+ * was no reformatting, so with/without ignoring whitespace, the amount of
+ * change is the same.
+ *
+ * Comparing with current (2009) source, excluding this comment:
+ * a) 209 lines match identically to the 4.4BSD Lite sources, with 771 lines
+ *    changed/added.
+ * a) Ignoring whitespace, the current version still uses 516 lines from the
+ *    4.4BSD Lite sources, with 402 lines changed/added.
+ *
+ * Raymond's original comment on this follows...
+ */
 
 /*
  * tset.c - terminal initialization utility
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * SUCH DAMAGE.
  */
 
-#define __INTERNAL_CAPS_VISIBLE        /* we need to see has_hardware_tabs */
-#include <progs.priv.h>
-
-#include <errno.h>
-#include <stdio.h>
+#include <reset_cmd.h>
 #include <termcap.h>
-#include <fcntl.h>
+#include <transform.h>
+#include <tty_settings.h>
 
 #if HAVE_GETTTYNAM && HAVE_TTYENT_H
 #include <ttyent.h>
 char *ttyname(int fd);
 #endif
 
-/* this is just to stifle a missing-prototype warning */
-#ifdef linux
-# include <sys/ioctl.h>
-#endif
-
-#if NEED_PTEM_H
-/* they neglected to define struct winsize in termios.h -- it's only
-   in termio.h */
-#include       <sys/stream.h>
-#include       <sys/ptem.h>
-#endif
-
-#include <curses.h>    /* for bool typedef */
-#include <dump_entry.h>
-
-MODULE_ID("$Id: tset.c,v 0.31 1998/02/11 12:14:02 tom Exp $")
+MODULE_ID("$Id: tset.c,v 1.116 2017/01/07 22:48:20 tom Exp $")
 
+#ifndef environ
 extern char **environ;
-
-#undef CTRL
-#define CTRL(x)        ((x) & 0x1f)
+#endif
 
 const char *_nc_progname = "tset";
 
-static TTY mode, oldmode;
+#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
 
-static int     terasechar = -1;        /* new erase character */
-static int     intrchar = -1;          /* new interrupt character */
-static int     isreset;                /* invoked as reset */
-static int     tkillchar = -1;         /* new kill character */
-static int     tlines, tcolumns;               /* window size */
-
-#define LOWERCASE(c) ((isalpha(c) && isupper(c)) ? tolower(c) : (c))
+static void exit_error(void) GCC_NORETURN;
 
 static int
-CaselessCmp(const char *a, const char *b) /* strcasecmp isn't portable */
-{
-       while (*a && *b) {
-               int cmp = LOWERCASE(*a) - LOWERCASE(*b);
-               if (cmp != 0)
-                       break;
-               a++, b++;
-       }
-       return LOWERCASE(*a) - LOWERCASE(*b);
-}
-
-#if !HAVE_STRDUP
-static char *strdup (char *s)
-{
-  char *p;
-
-  p = malloc(strlen(s)+1);
-  if (p)
-    strcpy(p,s);
-  return(p);
+CaselessCmp(const char *a, const char *b)
+{                              /* strcasecmp isn't portable */
+    while (*a && *b) {
+       int cmp = LOWERCASE(*a) - LOWERCASE(*b);
+       if (cmp != 0)
+           break;
+       a++, b++;
+    }
+    return LOWERCASE(*a) - LOWERCASE(*b);
 }
-#endif /* not HAVE_STRDUP */
 
 static void
-err(const char *fmt, ...)
+exit_error(void)
 {
-       va_list ap;
-       va_start(ap, fmt);
-       (void)fprintf(stderr, "tset: ");
-       (void)vfprintf(stderr, fmt, ap);
-       va_end(ap);
-       (void)fprintf(stderr, "\n");
-       exit(EXIT_FAILURE);
-       /* NOTREACHED */
+    restore_tty_settings();
+    (void) fprintf(stderr, "\n");
+    fflush(stderr);
+    ExitProgram(EXIT_FAILURE);
+    /* NOTREACHED */
 }
 
 static void
-failed(const char *msg)
+err(const char *fmt,...)
 {
-       char    temp[BUFSIZ];
-       perror(strcat(strcpy(temp, "tset: "), msg));
-       exit(EXIT_FAILURE);
-       /* NOTREACHED */
+    va_list ap;
+    va_start(ap, fmt);
+    (void) fprintf(stderr, "%s: ", _nc_progname);
+    (void) vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    exit_error();
+    /* NOTREACHED */
 }
 
 static void
-cat(char *file)
-{
-       register int fd, nr, nw;
-       char buf[BUFSIZ];
-
-       if ((fd = open(file, O_RDONLY, 0)) < 0)
-               failed(file);
-
-       while ((nr = read(fd, buf, sizeof(buf))) > 0)
-               if ((nw = write(STDERR_FILENO, buf, (size_t)nr)) == -1)
-                       failed("write to stderr");
-       if (nr != 0)
-               failed(file);
-       (void)close(fd);
-}
-
-static int
-outc(int c)
+failed(const char *msg)
 {
-       return putc(c, stderr);
+    char temp[BUFSIZ];
+    size_t len = strlen(_nc_progname) + 2;
+
+    if ((int) len < (int) sizeof(temp) - 12) {
+       _nc_STRCPY(temp, _nc_progname, sizeof(temp));
+       _nc_STRCAT(temp, ": ", sizeof(temp));
+    } else {
+       _nc_STRCPY(temp, "tset: ", sizeof(temp));
+    }
+    _nc_STRNCAT(temp, msg, sizeof(temp), sizeof(temp) - strlen(temp) - 2);
+    perror(temp);
+    exit_error();
+    /* NOTREACHED */
 }
 
 /* Prompt the user for a terminal type. */
 static const char *
 askuser(const char *dflt)
 {
-       static char answer[256];
-       char *p;
-
-       /* We can get recalled; if so, don't continue uselessly. */
-       if (feof(stdin) || ferror(stdin)) {
-               (void)fprintf(stderr, "\n");
-               exit(EXIT_FAILURE);
+    static char answer[256];
+    char *p;
+
+    /* We can get recalled; if so, don't continue uselessly. */
+    clearerr(stdin);
+    if (feof(stdin) || ferror(stdin)) {
+       (void) fprintf(stderr, "\n");
+       exit_error();
+       /* NOTREACHED */
+    }
+    for (;;) {
+       if (dflt)
+           (void) fprintf(stderr, "Terminal type? [%s] ", dflt);
+       else
+           (void) fprintf(stderr, "Terminal type? ");
+       (void) fflush(stderr);
+
+       if (fgets(answer, sizeof(answer), stdin) == 0) {
+           if (dflt == 0) {
+               exit_error();
+               /* NOTREACHED */
+           }
+           return (dflt);
        }
-       for (;;) {
-               if (dflt)
-                       (void)fprintf(stderr, "Terminal type? [%s] ", dflt);
-               else
-                       (void)fprintf(stderr, "Terminal type? ");
-               (void)fflush(stderr);
-
-               if (fgets(answer, sizeof(answer), stdin) == 0) {
-                       if (dflt == 0) {
-                               (void)fprintf(stderr, "\n");
-                               exit(EXIT_FAILURE);
-                       }
-                       return (dflt);
-               }
 
-               if ((p = strchr(answer, '\n')) != 0)
-                       *p = '\0';
-               if (answer[0])
-                       return (answer);
-               if (dflt != 0)
-                       return (dflt);
-       }
+       if ((p = strchr(answer, '\n')) != 0)
+           *p = '\0';
+       if (answer[0])
+           return (answer);
+       if (dflt != 0)
+           return (dflt);
+    }
 }
 
 /**************************************************************************
@@ -242,88 +214,146 @@ askuser(const char *dflt)
 #define        LE              (LT | EQ)
 
 typedef struct map {
-       struct map *next;       /* Linked list of maps. */
-       const char *porttype;   /* Port type, or "" for any. */
-       const char *type;       /* Terminal type to select. */
-       int conditional;        /* Baud rate conditionals bitmask. */
-       int speed;              /* Baud rate to compare against. */
+    struct map *next;          /* Linked list of maps. */
+    const char *porttype;      /* Port type, or "" for any. */
+    const char *type;          /* Terminal type to select. */
+    int conditional;           /* Baud rate conditionals bitmask. */
+    int speed;                 /* Baud rate to compare against. */
 } MAP;
 
 static MAP *cur, *maplist;
 
+#define DATA(name,value) { { name }, value }
+
 typedef struct speeds {
-       const char *string;
-       int     speed;
+    const char string[7];
+    int speed;
 } SPEEDS;
 
-static const SPEEDS speeds[] = {
-       { "0",          B0 },
-       { "50",         B50 },
-       { "75",         B75 },
-       { "110",        B110 },
-       { "134",        B134 },
-       { "134.5",      B134 },
-       { "150",        B150 },
-       { "200",        B200 },
-       { "300",        B300 },
-       { "600",        B600 },
-       { "1200",       B1200 },
-       { "1800",       B1800 },
-       { "2400",       B2400 },
-       { "4800",       B4800 },
-       { "9600",       B9600 },
-       { "19200",      B19200 },
-       { "38400",      B38400 },
-       { "19200",      B19200 },
-       { "38400",      B38400 },
+static const SPEEDS speeds[] =
+{
+    DATA("0", B0),
+    DATA("50", B50),
+    DATA("75", B75),
+    DATA("110", B110),
+    DATA("134", B134),
+    DATA("134.5", B134),
+    DATA("150", B150),
+    DATA("200", B200),
+    DATA("300", B300),
+    DATA("600", B600),
+    DATA("1200", B1200),
+    DATA("1800", B1800),
+    DATA("2400", B2400),
+    DATA("4800", B4800),
+    DATA("9600", B9600),
+    /* sgttyb may define up to this point */
+#ifdef B19200
+    DATA("19200", B19200),
+#endif
+#ifdef B38400
+    DATA("38400", B38400),
+#endif
+#ifdef B19200
+    DATA("19200", B19200),
+#endif
+#ifdef B38400
+    DATA("38400", B38400),
+#endif
 #ifdef B19200
-       { "19200",      B19200 },
+    DATA("19200", B19200),
 #else
 #ifdef EXTA
-       { "19200",      EXTA },
+    DATA("19200", EXTA),
 #endif
 #endif
 #ifdef B38400
-       { "38400",      B38400 },
+    DATA("38400", B38400),
 #else
 #ifdef EXTB
-       { "38400",      EXTB },
+    DATA("38400", EXTB),
 #endif
 #endif
 #ifdef B57600
-       { "57600",      B57600 },
+    DATA("57600", B57600),
+#endif
+#ifdef B76800
+    DATA("76800", B57600),
 #endif
 #ifdef B115200
-       { "115200",     B115200 },
+    DATA("115200", B115200),
+#endif
+#ifdef B153600
+    DATA("153600", B153600),
 #endif
 #ifdef B230400
-       { "230400",     B230400 },
+    DATA("230400", B230400),
+#endif
+#ifdef B307200
+    DATA("307200", B307200),
 #endif
 #ifdef B460800
-       { "460800",     B460800 },
+    DATA("460800", B460800),
+#endif
+#ifdef B500000
+    DATA("500000", B500000),
+#endif
+#ifdef B576000
+    DATA("576000", B576000),
+#endif
+#ifdef B921600
+    DATA("921600", B921600),
+#endif
+#ifdef B1000000
+    DATA("1000000", B1000000),
+#endif
+#ifdef B1152000
+    DATA("1152000", B1152000),
+#endif
+#ifdef B1500000
+    DATA("1500000", B1500000),
+#endif
+#ifdef B2000000
+    DATA("2000000", B2000000),
+#endif
+#ifdef B2500000
+    DATA("2500000", B2500000),
+#endif
+#ifdef B3000000
+    DATA("3000000", B3000000),
+#endif
+#ifdef B3500000
+    DATA("3500000", B3500000),
+#endif
+#ifdef B4000000
+    DATA("4000000", B4000000),
 #endif
-       { (char *)0,    0 }
 };
+#undef DATA
 
 static int
 tbaudrate(char *rate)
 {
-       const SPEEDS *sp;
-       int found = FALSE;
+    const SPEEDS *sp = 0;
+    size_t n;
 
-       /* The baudrate number can be preceded by a 'B', which is ignored. */
-       if (*rate == 'B')
-               ++rate;
+    /* The baudrate number can be preceded by a 'B', which is ignored. */
+    if (*rate == 'B')
+       ++rate;
 
-       for (sp = speeds; sp->string; ++sp) {
-               if (!CaselessCmp(rate, sp->string)) {
-                       found = TRUE;
-                       break;
-               }
+    for (n = 0; n < SIZEOF(speeds); ++n) {
+       if (n > 0 && (speeds[n].speed <= speeds[n - 1].speed)) {
+           /* if the speeds are not increasing, likely a numeric overflow */
+           break;
+       }
+       if (!CaselessCmp(rate, speeds[n].string)) {
+           sp = speeds + n;
+           break;
        }
-       if (!found)
-               err("unknown baud rate %s", rate);
-       return (sp->speed);
+    }
+    if (sp == 0)
+       err("unknown baud rate %s", rate);
+    return (sp->speed);
 }
 
 /*
@@ -334,110 +364,116 @@ tbaudrate(char *rate)
 static void
 add_mapping(const char *port, char *arg)
 {
-       MAP *mapp;
-       char *copy, *p;
-       const char *termp;
-       char *base = 0;
-
-       copy = strdup(arg);
-       mapp = malloc((u_int)sizeof(MAP));
-       if (copy == 0 || mapp == 0)
-               failed("malloc");
-       mapp->next = 0;
-       if (maplist == 0)
-               cur = maplist = mapp;
-       else {
-               cur->next = mapp;
-               cur =  mapp;
-       }
-
-       mapp->porttype = arg;
-       mapp->conditional = 0;
-
-       arg = strpbrk(arg, "><@=!:");
-
-       if (arg == 0) {                 /* [?]term */
-               mapp->type = mapp->porttype;
-               mapp->porttype = 0;
-               goto done;
-       }
-
-       if (arg == mapp->porttype)              /* [><@=! baud]:term */
-               termp = mapp->porttype = 0;
-       else
-               termp = base = arg;
-
-       for (;; ++arg)                          /* Optional conditionals. */
-               switch(*arg) {
-               case '<':
-                       if (mapp->conditional & GT)
-                               goto badmopt;
-                       mapp->conditional |= LT;
-                       break;
-               case '>':
-                       if (mapp->conditional & LT)
-                               goto badmopt;
-                       mapp->conditional |= GT;
-                       break;
-               case '@':
-               case '=':                       /* Not documented. */
-                       mapp->conditional |= EQ;
-                       break;
-               case '!':
-                       mapp->conditional |= NOT;
-                       break;
-               default:
-                       goto next;
-               }
-
-next:  if (*arg == ':') {
-               if (mapp->conditional)
-                       goto badmopt;
-               ++arg;
-       } else {                                /* Optional baudrate. */
-               arg = strchr(p = arg, ':');
-               if (arg == 0)
-                       goto badmopt;
-               *arg++ = '\0';
-               mapp->speed = tbaudrate(p);
-       }
-
-       if (arg == (char *)0)           /* Non-optional type. */
+    MAP *mapp;
+    char *copy, *p;
+    const char *termp;
+    char *base = 0;
+
+    copy = strdup(arg);
+    mapp = typeMalloc(MAP, 1);
+    if (copy == 0 || mapp == 0)
+       failed("malloc");
+
+    assert(copy != 0);
+    assert(mapp != 0);
+
+    mapp->next = 0;
+    if (maplist == 0)
+       cur = maplist = mapp;
+    else {
+       cur->next = mapp;
+       cur = mapp;
+    }
+
+    mapp->porttype = arg;
+    mapp->conditional = 0;
+
+    arg = strpbrk(arg, "><@=!:");
+
+    if (arg == 0) {            /* [?]term */
+       mapp->type = mapp->porttype;
+       mapp->porttype = 0;
+       goto done;
+    }
+
+    if (arg == mapp->porttype) /* [><@=! baud]:term */
+       termp = mapp->porttype = 0;
+    else
+       termp = base = arg;
+
+    for (;; ++arg) {           /* Optional conditionals. */
+       switch (*arg) {
+       case '<':
+           if (mapp->conditional & GT)
                goto badmopt;
-
-       mapp->type = arg;
-
-       /* Terminate porttype, if specified. */
-       if (termp != 0)
-               *base = '\0';
-
-       /* If a NOT conditional, reverse the test. */
-       if (mapp->conditional & NOT)
-               mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
-
-       /* If user specified a port with an option flag, set it. */
-done:  if (port) {
-               if (mapp->porttype)
-badmopt:               err("illegal -m option format: %s", copy);
-               mapp->porttype = port;
-       }
-
-#ifdef MAPDEBUG
-       (void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
-       (void)printf("type: %s\n", mapp->type);
-       (void)printf("conditional: ");
-       p = "";
-       if (mapp->conditional & GT) {
-               (void)printf("GT");
-               p = "/";
+           mapp->conditional |= LT;
+           break;
+       case '>':
+           if (mapp->conditional & LT)
+               goto badmopt;
+           mapp->conditional |= GT;
+           break;
+       case '@':
+       case '=':               /* Not documented. */
+           mapp->conditional |= EQ;
+           break;
+       case '!':
+           mapp->conditional |= NOT;
+           break;
+       default:
+           goto next;
        }
-       if (mapp->conditional & EQ) {
-               (void)printf("%sEQ", p);
-               p = "/";
+    }
+
+  next:
+    if (*arg == ':') {
+       if (mapp->conditional)
+           goto badmopt;
+       ++arg;
+    } else {                   /* Optional baudrate. */
+       arg = strchr(p = arg, ':');
+       if (arg == 0)
+           goto badmopt;
+       *arg++ = '\0';
+       mapp->speed = tbaudrate(p);
+    }
+
+    mapp->type = arg;
+
+    /* Terminate porttype, if specified. */
+    if (termp != 0)
+       *base = '\0';
+
+    /* If a NOT conditional, reverse the test. */
+    if (mapp->conditional & NOT)
+       mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
+
+    /* If user specified a port with an option flag, set it. */
+  done:
+    if (port) {
+       if (mapp->porttype) {
+         badmopt:
+           err("illegal -m option format: %s", copy);
        }
-       if (mapp->conditional & LT)
-               (void)printf("%sLT", p);
-       (void)printf("\nspeed: %d\n", mapp->speed);
+       mapp->porttype = port;
+    }
+    free(copy);
+#ifdef MAPDEBUG
+    (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
+    (void) printf("type: %s\n", mapp->type);
+    (void) printf("conditional: ");
+    p = "";
+    if (mapp->conditional & GT) {
+       (void) printf("GT");
+       p = "/";
+    }
+    if (mapp->conditional & EQ) {
+       (void) printf("%sEQ", p);
+       p = "/";
+    }
+    if (mapp->conditional & LT)
+       (void) printf("%sLT", p);
+    (void) printf("\nspeed: %d\n", mapp->speed);
 #endif
 }
 
@@ -449,38 +485,38 @@ badmopt:          err("illegal -m option format: %s", copy);
 static const char *
 mapped(const char *type)
 {
-       MAP *mapp;
-       int match;
-
-       for (mapp = maplist; mapp; mapp = mapp->next)
-               if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
-                       switch (mapp->conditional) {
-                       case 0:                 /* No test specified. */
-                               match = TRUE;
-                               break;
-                       case EQ:
-                               match = (ospeed == mapp->speed);
-                               break;
-                       case GE:
-                               match = (ospeed >= mapp->speed);
-                               break;
-                       case GT:
-                               match = (ospeed > mapp->speed);
-                               break;
-                       case LE:
-                               match = (ospeed <= mapp->speed);
-                               break;
-                       case LT:
-                               match = (ospeed < mapp->speed);
-                               break;
-                       default:
-                               match = FALSE;
-                       }
-                       if (match)
-                               return (mapp->type);
-               }
-       /* No match found; return given type. */
-       return (type);
+    MAP *mapp;
+    int match;
+
+    for (mapp = maplist; mapp; mapp = mapp->next)
+       if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
+           switch (mapp->conditional) {
+           case 0:             /* No test specified. */
+               match = TRUE;
+               break;
+           case EQ:
+               match = ((int) ospeed == mapp->speed);
+               break;
+           case GE:
+               match = ((int) ospeed >= mapp->speed);
+               break;
+           case GT:
+               match = ((int) ospeed > mapp->speed);
+               break;
+           case LE:
+               match = ((int) ospeed <= mapp->speed);
+               break;
+           case LT:
+               match = ((int) ospeed < mapp->speed);
+               break;
+           default:
+               match = FALSE;
+           }
+           if (match)
+               return (mapp->type);
+       }
+    /* No match found; return given type. */
+    return (type);
 }
 
 /**************************************************************************
@@ -494,715 +530,360 @@ mapped(const char *type)
  * its termcap entry.
  */
 static const char *
-get_termcap_entry(char *userarg)
+get_termcap_entry(int fd, char *userarg)
 {
-       int rval, errret;
-       char *p;
-       const char *ttype;
+    int errret;
+    char *p;
+    const char *ttype;
 #if HAVE_GETTTYNAM
-       struct ttyent *t;
+    struct ttyent *t;
 #else
-       FILE *fp;
+    FILE *fp;
 #endif
-       char *ttypath;
+    char *ttypath;
 
-       if (userarg) {
-               ttype = userarg;
-               goto found;
-       }
+    (void) fd;
 
-       /* Try the environment. */
-       if ((ttype = getenv("TERM")) != 0)
-               goto map;
+    if (userarg) {
+       ttype = userarg;
+       goto found;
+    }
 
-       if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
-               if ((p = strrchr(ttypath, '/')) != 0)
-                       ++p;
-               else
-                       p = ttypath;
-#if HAVE_GETTTYNAM
-               /*
-                * We have the 4.3BSD library call getttynam(3); that means
-                * there's an /etc/ttys to look up device-to-type mappings in.
-                * Try ttyname(3); check for dialup or other mapping.
-                */
-               if ((t = getttynam(p))) {
-                       ttype = t->ty_type;
-                       goto map;
-               }
-#else
-               if ((fp = fopen("/etc/ttytype", "r")) != 0
-                || (fp = fopen("/etc/ttys", "r")) != 0) {
-                       char buffer[BUFSIZ];
-                       char *s, *t, *d;
-
-                       while (fgets(buffer, sizeof(buffer)-1, fp) != 0) {
-                               for (s = buffer, t = d = 0; *s; s++) {
-                                       if (isspace(*s))
-                                               *s = '\0';
-                                       else if (t == 0)
-                                               t = s;
-                                       else if (d == 0 && s != buffer && s[-1] == '\0')
-                                               d = s;
-                               }
-                               if (t != 0 && d != 0 && !strcmp(d,p)) {
-                                       ttype = strdup(t);
-                                       fclose(fp);
-                                       goto map;
-                               }
-                       }
-                       fclose(fp);
-               }
-#endif /* HAVE_GETTTYNAM */
-       }
-
-       /* If still undefined, use "unknown". */
-       ttype = "unknown";
-
-map:   ttype = mapped(ttype);
+    /* Try the environment. */
+    if ((ttype = getenv("TERM")) != 0)
+       goto map;
 
+    if ((ttypath = ttyname(fd)) != 0) {
+       p = _nc_basename(ttypath);
+#if HAVE_GETTTYNAM
        /*
-        * If not a path, remove TERMCAP from the environment so we get a
-        * real entry from /etc/termcap.  This prevents us from being fooled
-        * by out of date stuff in the environment.
+        * We have the 4.3BSD library call getttynam(3); that means
+        * there's an /etc/ttys to look up device-to-type mappings in.
+        * Try ttyname(3); check for dialup or other mapping.
         */
-found: if ((p = getenv("TERMCAP")) != 0 && *p != '/') {
-               /* 'unsetenv("TERMCAP")' is not portable.
-                * The 'environ' array is better.
-                */
-               int n;
-               for (n = 0; environ[n] != 0; n++) {
-                       if (!strncmp("TERMCAP=", environ[n], 8)) {
-                               while ((environ[n] = environ[n+1]) != 0) {
-                                       n++;
-                               }
-                               break;
-                       }
+       if ((t = getttynam(p))) {
+           ttype = t->ty_type;
+           goto map;
+       }
+#else
+       if ((fp = fopen("/etc/ttytype", "r")) != 0
+           || (fp = fopen("/etc/ttys", "r")) != 0) {
+           char buffer[BUFSIZ];
+           char *s, *t, *d;
+
+           while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) {
+               for (s = buffer, t = d = 0; *s; s++) {
+                   if (isspace(UChar(*s)))
+                       *s = '\0';
+                   else if (t == 0)
+                       t = s;
+                   else if (d == 0 && s != buffer && s[-1] == '\0')
+                       d = s;
+               }
+               if (t != 0 && d != 0 && !strcmp(d, p)) {
+                   ttype = strdup(t);
+                   fclose(fp);
+                   goto map;
                }
+           }
+           fclose(fp);
        }
-
-       /*
-        * ttype now contains a pointer to the type of the terminal.
-        * If the first character is '?', ask the user.
+#endif /* HAVE_GETTTYNAM */
+    }
+
+    /* If still undefined, use "unknown". */
+    ttype = "unknown";
+
+  map:ttype = mapped(ttype);
+
+    /*
+     * If not a path, remove TERMCAP from the environment so we get a
+     * real entry from /etc/termcap.  This prevents us from being fooled
+     * by out of date stuff in the environment.
+     */
+  found:
+    if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) {
+       /* 'unsetenv("TERMCAP")' is not portable.
+        * The 'environ' array is better.
         */
-       if (ttype[0] == '?')
-               if (ttype[1] != '\0')
-                       ttype = askuser(ttype + 1);
-               else
-                       ttype = askuser(0);
-
-       /* Find the terminfo entry.  If it doesn't exist, ask the user. */
-       while ((rval = setupterm(ttype, STDOUT_FILENO, &errret)) != OK) {
-               if (errret == 0) {
-                       (void)fprintf(stderr, "tset: unknown terminal type %s\n",
-                           ttype);
-                       ttype = 0;
+       int n;
+       for (n = 0; environ[n] != 0; n++) {
+           if (!strncmp("TERMCAP=", environ[n], (size_t) 8)) {
+               while ((environ[n] = environ[n + 1]) != 0) {
+                   n++;
                }
-               else {
-                       (void)fprintf(stderr, "tset: can't initialize terminal\
-                           type %s (error %d)\n", ttype, errret);
-                       ttype = 0;
-               }
-               ttype = askuser(ttype);
+               break;
+           }
+       }
+    }
+
+    /*
+     * ttype now contains a pointer to the type of the terminal.
+     * If the first character is '?', ask the user.
+     */
+    if (ttype[0] == '?') {
+       if (ttype[1] != '\0')
+           ttype = askuser(ttype + 1);
+       else
+           ttype = askuser(0);
+    }
+    /* Find the terminfo entry.  If it doesn't exist, ask the user. */
+    while (setupterm((NCURSES_CONST char *) ttype, fd, &errret)
+          != OK) {
+       if (errret == 0) {
+           (void) fprintf(stderr, "%s: unknown terminal type %s\n",
+                          _nc_progname, ttype);
+           ttype = 0;
+       } else {
+           (void) fprintf(stderr,
+                          "%s: can't initialize terminal type %s (error %d)\n",
+                          _nc_progname, ttype, errret);
+           ttype = 0;
        }
+       ttype = askuser(ttype);
+    }
 #if BROKEN_LINKER
-       tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */
+    tgetflag("am");            /* force lib_termcap.o to be linked for 'ospeed' */
 #endif
-       return (ttype);
+    return (ttype);
 }
 
 /**************************************************************************
  *
- * Mode-setting logic
+ * Main sequence
  *
  **************************************************************************/
 
-/* some BSD systems have these built in, some systems are missing
- * one or more definitions. The safest solution is to override.
- */
-#undef CEOF
-#undef CERASE
-#undef CINTR
-#undef CKILL
-#undef CLNEXT
-#undef CRPRNT
-#undef CQUIT
-#undef CSTART
-#undef CSTOP
-#undef CSUSP
-
-/* control-character defaults */
-#define CEOF   CTRL('D')
-#define CERASE CTRL('H')
-#define CINTR  127             /* ^? */
-#define CKILL  CTRL('U')
-#define CLNEXT  CTRL('v')
-#define CRPRNT  CTRL('r')
-#define CQUIT  CTRL('\\')
-#define CSTART CTRL('Q')
-#define CSTOP  CTRL('S')
-#define CSUSP  CTRL('Z')
-
-#define        CHK(val, dft)   ((int)val <= 0 ? dft : val)
-
-static bool    set_tabs (void);
-
-/*
- * Reset the terminal mode bits to a sensible state.  Very useful after
- * a child program dies in raw mode.
- */
-static void
-reset_mode(void)
-{
-#ifdef TERMIOS
-       tcgetattr(STDERR_FILENO, &mode);
-#else
-       stty(STDERR_FILENO,&mode);
-#endif
-
-#ifdef TERMIOS
-#if defined(VDISCARD) && defined(CDISCARD)
-       mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
-#endif
-       mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
-       mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
-#if defined(VFLUSH) && defined(CFLUSH)
-       mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
-#endif
-       mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
-       mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
-#if defined(VLNEXT) && defined(CLNEXT)
-       mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
-#endif
-       mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
-#if defined(VREPRINT) && defined(CRPRNT)
-       mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
-#endif
-#if defined(VSTART) && defined(CSTART)
-       mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
-#endif
-#if defined(VSTOP) && defined(CSTOP)
-       mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
-#endif
-#if defined(VSUSP) && defined(CSUSP)
-       mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
-#endif
-#if defined(VWERASE) && defined(CWERASE)
-       mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
-#endif
-
-       mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
-#ifdef IUCLC
-                         | IUCLC
-#endif
-#ifdef IXANY
-                         | IXANY
-#endif
-                         | IXOFF);
-
-       mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
-#ifdef IMAXBEL
-                        | IMAXBEL
-#endif
-                        );
-
-       mode.c_oflag &= ~(0
-#ifdef OLCUC
-                         | OLCUC
-#endif
-#ifdef OCRNL
-                         | OCRNL
-#endif
-#ifdef ONOCR
-                         | ONOCR
-#endif
-#ifdef ONLRET
-                         | ONLRET
-#endif
-#ifdef OFILL
-                         | OFILL
-#endif
-#ifdef OFDEL
-                         | OFDEL
-#endif
-#ifdef NLDLY
-                         | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY
-#endif
-                         );
-
-       mode.c_oflag |= (OPOST
-#ifdef ONLCR
-                        | ONLCR
-#endif
-                        );
-
-       mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
-       mode.c_cflag |= (CS8 | CREAD);
-       mode.c_lflag &= ~(ECHONL | NOFLSH
-#ifdef TOSTOP
-                         | TOSTOP
-#endif
-#ifdef ECHOPTR
-                         | ECHOPRT
-#endif
-#ifdef XCASE
-                         | XCASE
-#endif
-                         );
-
-       mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
-#ifdef ECHOCTL
-                        | ECHOCTL
-#endif
-#ifdef ECHOKE
-                        | ECHOKE
-#endif
-                        );
-#endif
-
-#ifdef TERMIOS
-       tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
-#else
-       stty(STDERR_FILENO, &mode);
-#endif
-}
-
-/*
- * Returns a "good" value for the erase character.  This is loosely based on
- * the BSD4.4 logic.
- */
-static int
-default_erase(void)
-{
-       int result;
-
-       if (over_strike
-        && key_backspace != 0
-        && strlen(key_backspace) == 1)
-               result = key_backspace[0];
-       else
-               result = CERASE;
-
-       return result;
-}
-
 /*
- * Update the values of the erase, interrupt, and kill characters in 'mode'.
- *
- * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
- * characters if they're unset, or if we specify them as options.  This differs
- * from BSD 4.4 tset, which always sets erase.
+ * Convert the obsolete argument forms into something that getopt can handle.
+ * This means that -e, -i and -k get default arguments supplied for them.
  */
 static void
-set_control_chars(void)
+obsolete(char **argv)
 {
-#ifdef TERMIOS
-       if (mode.c_cc[VERASE] == 0 || terasechar >= 0)
-               mode.c_cc[VERASE] = terasechar >= 0 ? terasechar : default_erase();
-
-       if (mode.c_cc[VINTR] == 0 || intrchar >= 0)
-                mode.c_cc[VINTR] = intrchar >= 0 ? intrchar : CINTR;
-
-       if (mode.c_cc[VKILL] == 0 || tkillchar >= 0)
-               mode.c_cc[VKILL] = tkillchar >= 0 ? tkillchar : CKILL;
-#endif
-}
+    for (; *argv; ++argv) {
+       char *parm = argv[0];
 
-/*
- * Set up various conversions in 'mode', including parity, tabs, returns,
- * echo, and case, according to the termcap entry.  If the program we're
- * running was named with a leading upper-case character, map external
- * uppercase to internal lowercase.
- */
-static void
-set_conversions(void)
-{
-#ifdef __OBSOLETE__
-       /*
-        * Conversion logic for some *really* ancient terminal glitches,
-        * not supported in terminfo.  Left here for succeeding generations
-        * to marvel at.
-        */
-       if (tgetflag("UC")) {
-#ifdef IUCLC
-               mode.c_iflag |= IUCLC;
-               mode.c_oflag |= OLCUC;
-#endif
-       } else if (tgetflag("LC")) {
-#ifdef IUCLC
-               mode.c_iflag &= ~IUCLC;
-               mode.c_oflag &= ~OLCUC;
-#endif
-       }
-       mode.c_iflag &= ~(PARMRK | INPCK);
-       mode.c_lflag |= ICANON;
-       if (tgetflag("EP")) {
-               mode.c_cflag |= PARENB;
-               mode.c_cflag &= ~PARODD;
+       if (parm[0] == '-' && parm[1] == '\0') {
+           argv[0] = strdup("-q");
+           continue;
        }
-       if (tgetflag("OP")) {
-               mode.c_cflag |= PARENB;
-               mode.c_cflag |= PARODD;
-       }
-#endif /* __OBSOLETE__ */
 
-#ifdef TERMIOS
-#ifdef ONLCR
-       mode.c_oflag |= ONLCR;
-#endif
-       mode.c_iflag |= ICRNL;
-       mode.c_lflag |= ECHO;
-#ifdef OXTABS
-       mode.c_oflag |= OXTABS;
-#endif /* OXTABS */
-
-       /* test used to be tgetflag("NL") */
-       if (newline != (char *)0 && newline[0] == '\n' && !newline[1]) {
-               /* Newline, not linefeed. */
-#ifdef ONLCR
-               mode.c_oflag &= ~ONLCR;
-#endif
-               mode.c_iflag &= ~ICRNL;
+       if ((parm[0] != '-')
+           || (argv[1] && argv[1][0] != '-')
+           || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
+           || (parm[2] != '\0'))
+           continue;
+       switch (argv[0][1]) {
+       case 'e':
+           argv[0] = strdup("-e^H");
+           break;
+       case 'i':
+           argv[0] = strdup("-i^C");
+           break;
+       case 'k':
+           argv[0] = strdup("-k^U");
+           break;
        }
-#ifdef __OBSOLETE__
-       if (tgetflag("HD"))                     /* Half duplex. */
-               mode.c_lflag &= ~ECHO;
-#endif /* __OBSOLETE__ */
-#ifdef OXTABS
-       /* test used to be tgetflag("pt") */
-       if (has_hardware_tabs)                  /* Print tabs. */
-               mode.c_oflag &= ~OXTABS;
-#endif /* OXTABS */
-       mode.c_lflag |= (ECHOE | ECHOK);
-#endif
+    }
 }
 
-/* Output startup string. */
 static void
-set_init(void)
+print_shell_commands(const char *ttype)
 {
-       char    *p;
-       bool settle;
-
-#ifdef __OBSOLETE__
-       if (pad_char != (char *)0)              /* Get/set pad character. */
-               PC = pad_char[0];
-#endif /* OBSOLETE */
-
-#ifdef TAB3
-       if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
-               oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
-               tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode);
-       }
-#endif
-       settle = set_tabs();
-
-       if (isreset) {
-               if ((p = reset_1string) != 0) {
-                       tputs(p, 0, outc);
-                       settle = TRUE;
-               }
-               if ((p = reset_2string) != 0) {
-                       tputs(p, 0, outc);
-                       settle = TRUE;
-               }
-               /* What about rf, rs3, as per terminfo man page? */
-               /* also might be nice to send rmacs, rmul, rmm */
-               if ((p = reset_file) != 0
-                || (p = init_file) != 0) {
-                       cat(p);
-                       settle = TRUE;
-               }
-       }
-
-       if (settle) {
-               (void)putc('\r', stderr);
-               (void)fflush(stderr);
-               (void)napms(1000);      /* Settle the terminal. */
-       }
+    const char *p;
+    int len;
+    char *var;
+    char *leaf;
+    /*
+     * Figure out what shell we're using.  A hack, we look for an
+     * environmental variable SHELL ending in "csh".
+     */
+    if ((var = getenv("SHELL")) != 0
+       && ((len = (int) strlen(leaf = _nc_basename(var))) >= 3)
+       && !strcmp(leaf + len - 3, "csh"))
+       p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
+    else
+       p = "TERM=%s;\n";
+    (void) printf(p, ttype);
 }
 
-/*
- * Set the hardware tabs on the terminal, using the ct (clear all tabs),
- * st (set one tab) and ch (horizontal cursor addressing) capabilities.
- * This is done before if and is, so they can patch in case we blow this.
- * Return TRUE if we set any tab stops, FALSE if not.
- */
-static bool
-set_tabs()
+static void
+usage(void)
 {
-       if (set_tab && clear_all_tabs) {
-               int c;
-
-               (void)putc('\r', stderr);       /* Force to left margin. */
-               tputs(clear_all_tabs, 0, outc);
-
-               for (c = 8; c < tcolumns; c += 8) {
-                       /* Get to the right column.  In BSD tset, this
-                        * used to try a bunch of half-clever things
-                        * with cup and hpa, for an average saving of
-                        * somewhat less than two character times per
-                        * tab stop, less that .01 sec at 2400cps. We
-                        * lost all this cruft because it seemed to be
-                        * introducing some odd bugs.
-                        * ----------12345678----------- */
-                       (void)fputs("        ", stderr);
-                       tputs(set_tab, 0, outc);
-               }
-               putc('\r', stderr);
-               return (TRUE);
-       }
-       return (FALSE);
+#define DATA(s) s "\n"
+    static const char msg[] =
+    {
+       DATA("")
+       DATA("Options:")
+       DATA("  -c          set control characters")
+       DATA("  -e ch       erase character")
+       DATA("  -I          no initialization strings")
+       DATA("  -i ch       interrupt character")
+       DATA("  -k ch       kill character")
+       DATA("  -m mapping  map identifier to type")
+       DATA("  -Q          do not output control key settings")
+       DATA("  -r          display term on stderr")
+       DATA("  -s          output TERM set command")
+       DATA("  -V          print curses-version")
+       DATA("  -w          set window-size")
+    };
+#undef DATA
+    (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
+    fputs(msg, stderr);
+    exit_error();
+    /* NOTREACHED */
 }
 
-/**************************************************************************
- *
- * Main sequence
- *
- **************************************************************************/
-
-/*
- * Tell the user if a control key has been changed from the default value.
- */
-static void
-report(const char *name, int which, u_int def)
+static char
+arg_to_char(void)
 {
-#ifdef TERMIOS
-       u_int older, newer;
-       char *p;
-
-       newer = mode.c_cc[which];
-       older = oldmode.c_cc[which];
-
-       if (older == newer && older == def)
-               return;
-
-       (void)fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to");
-
-       /*
-        * Check 'delete' before 'backspace', since the key_backspace value
-        * is ambiguous.
-        */
-       if (newer == 0177)
-               (void)fprintf(stderr, "delete.\n");
-       else if ((p = key_backspace) != 0
-        && newer == (u_int)p[0]
-        && p[1] == '\0')
-               (void)fprintf(stderr, "backspace.\n");
-       else if (newer < 040) {
-               newer ^= 0100;
-               (void)fprintf(stderr, "control-%c (^%c).\n", newer, newer);
-       } else
-               (void)fprintf(stderr, "%c.\n", newer);
-#endif
+    return (char) ((optarg[0] == '^' && optarg[1] != '\0')
+                  ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
+                  : optarg[0]);
 }
 
-/*
- * Convert the obsolete argument forms into something that getopt can handle.
- * This means that -e, -i and -k get default arguments supplied for them.
- */
-static void
-obsolete(char **argv)
+int
+main(int argc, char **argv)
 {
-       for (; *argv; ++argv) {
-               char *parm = argv[0];
-
-               if (parm[0] == '-' && parm[1] == '\0')
-               {
-                   argv[0] = strdup("-q");
-                   continue;
-               }
-
-               if ((parm[0] != '-')
-                || (argv[1] && argv[1][0] != '-')
-                || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
-                || (parm[2] != '\0'))
-                       continue;
-               switch(argv[0][1]) {
-               case 'e':
-                       argv[0] = strdup("-e^H");
-                       break;
-               case 'i':
-                       argv[0] = strdup("-i^C");
-                       break;
-               case 'k':
-                       argv[0] = strdup("-k^U");
-                       break;
-               }
+    int ch, noinit, noset, quiet, Sflag, sflag, showterm;
+    const char *ttype;
+    int terasechar = -1;       /* new erase character */
+    int intrchar = -1;         /* new interrupt character */
+    int tkillchar = -1;                /* new kill character */
+    int my_fd = -1;
+    bool opt_c = FALSE;                /* set control-chars */
+    bool opt_w = FALSE;                /* set window-size */
+    TTY mode, oldmode;
+
+    my_fd = STDERR_FILENO;
+    obsolete(argv);
+    noinit = noset = quiet = Sflag = sflag = showterm = 0;
+    while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:p:qQSrsVw")) != -1) {
+       switch (ch) {
+       case 'c':               /* set control-chars */
+           opt_c = TRUE;
+           break;
+       case 'a':               /* OBSOLETE: map identifier to type */
+           add_mapping("arpanet", optarg);
+           break;
+       case 'd':               /* OBSOLETE: map identifier to type */
+           add_mapping("dialup", optarg);
+           break;
+       case 'e':               /* erase character */
+           terasechar = arg_to_char();
+           break;
+       case 'I':               /* no initialization strings */
+           noinit = 1;
+           break;
+       case 'i':               /* interrupt character */
+           intrchar = arg_to_char();
+           break;
+       case 'k':               /* kill character */
+           tkillchar = arg_to_char();
+           break;
+       case 'm':               /* map identifier to type */
+           add_mapping(0, optarg);
+           break;
+       case 'p':               /* OBSOLETE: map identifier to type */
+           add_mapping("plugboard", optarg);
+           break;
+       case 'Q':               /* don't output control key settings */
+           quiet = 1;
+           break;
+       case 'q':               /* display term only */
+           noset = 1;
+           break;
+       case 'r':               /* display term on stderr */
+           showterm = 1;
+           break;
+       case 'S':               /* OBSOLETE: output TERM & TERMCAP */
+           Sflag = 1;
+           break;
+       case 's':               /* output TERM set command */
+           sflag = 1;
+           break;
+       case 'V':               /* print curses-version */
+           puts(curses_version());
+           ExitProgram(EXIT_SUCCESS);
+       case 'w':               /* set window-size */
+           opt_w = TRUE;
+           break;
+       case '?':
+       default:
+           usage();
        }
-}
+    }
 
-static void
-usage(const char* pname)
-{
-       (void)fprintf(stderr,
-"usage: %s [-IQrs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n", pname);
-       exit(EXIT_FAILURE);
-}
+    _nc_progname = _nc_rootname(*argv);
+    argc -= optind;
+    argv += optind;
 
-static char arg_to_char(void)
-{
-       return (optarg[0] == '^' && optarg[1] != '\0')
-               ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
-               : optarg[0];
-}
+    if (argc > 1)
+       usage();
 
-int
-main(int argc, char **argv)
-{
-#if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
-       struct winsize win;
-#endif
-       int ch, noinit, noset, quiet, Sflag, sflag, showterm;
-       const char *p;
-       const char *ttype;
+    if (!opt_c && !opt_w)
+       opt_c = opt_w = TRUE;
 
+    my_fd = save_tty_settings(&mode);
+    oldmode = mode;
 #ifdef TERMIOS
-       if (tcgetattr(STDERR_FILENO, &mode) < 0)
-               failed("standard error");
-
-       oldmode = mode;
-       ospeed = cfgetospeed(&mode);
+    ospeed = (NCURSES_OSPEED) cfgetospeed(&mode);
 #else
-       if (gtty(STDERR_FILENO, &mode) < 0)
-               failed("standard error");
-
-       oldmode = mode;
-       ospeed = mode.sg_ospeed;
+    ospeed = (NCURSES_OSPEED) mode.sg_ospeed;
 #endif
 
-       if ((p = strrchr(*argv, '/')) != 0)
-               ++p;
-       else
-               p = *argv;
-       if (!CaselessCmp(p, "reset")) {
-               isreset = 1;
-               reset_mode();
-       }
+    if (same_program(_nc_progname, PROG_RESET)) {
+       reset_start(stderr, TRUE, FALSE);
+       reset_tty_settings(my_fd, &mode);
+    } else {
+       reset_start(stderr, FALSE, TRUE);
+    }
 
-       obsolete(argv);
-       noinit = noset = quiet = Sflag = sflag = showterm = 0;
-       while ((ch = getopt(argc, argv, "a:d:e:Ii:k:m:np:qQSrs")) != EOF) {
-               switch (ch) {
-               case 'q':               /* display term only */
-                       noset = 1;
-                       break;
-               case 'a':               /* OBSOLETE: map identifier to type */
-                       add_mapping("arpanet", optarg);
-                       break;
-               case 'd':               /* OBSOLETE: map identifier to type */
-                       add_mapping("dialup", optarg);
-                       break;
-               case 'e':               /* erase character */
-                       terasechar = arg_to_char();
-                       break;
-               case 'I':               /* no initialization strings */
-                       noinit = 1;
-                       break;
-               case 'i':               /* interrupt character */
-                       intrchar = arg_to_char();
-                       break;
-               case 'k':               /* kill character */
-                       tkillchar = arg_to_char();
-                       break;
-               case 'm':               /* map identifier to type */
-                       add_mapping(0, optarg);
-                       break;
-               case 'n':               /* OBSOLETE: set new tty driver */
-                       break;
-               case 'p':               /* OBSOLETE: map identifier to type */
-                       add_mapping("plugboard", optarg);
-                       break;
-               case 'Q':               /* don't output control key settings */
-                       quiet = 1;
-                       break;
-               case 'S':               /* OBSOLETE: output TERM & TERMCAP */
-                       Sflag = 1;
-                       break;
-               case 'r':               /* display term on stderr */
-                       showterm = 1;
-                       break;
-               case 's':               /* output TERM set command */
-                       sflag = 1;
-                       break;
-               case '?':
-               default:
-                       usage(*argv);
-               }
+    ttype = get_termcap_entry(my_fd, *argv);
+
+    if (!noset) {
+#if HAVE_SIZECHANGE
+       if (opt_w) {
+           set_window_size(my_fd, &lines, &columns);
        }
-       argc -= optind;
-       argv += optind;
-
-       if (argc > 1)
-               usage(*argv);
-
-       ttype = get_termcap_entry(*argv);
-
-       if (!noset) {
-               tcolumns = columns;
-               tlines = lines;
-
-#if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
-               /* Set window size */
-               (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
-               if (win.ws_row == 0 && win.ws_col == 0 &&
-                   tlines > 0 && tcolumns > 0) {
-                       win.ws_row = tlines;
-                       win.ws_col = tcolumns;
-                       (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
-               }
 #endif
-               set_control_chars();
-               set_conversions();
+       if (opt_c) {
+           set_control_chars(&mode, terasechar, intrchar, tkillchar);
+           set_conversions(&mode);
 
-               if (!noinit)
-                       set_init();
+           if (!noinit) {
+               if (send_init_strings(my_fd, &oldmode)) {
+                   (void) putc('\r', stderr);
+                   (void) fflush(stderr);
+                   (void) napms(1000);         /* Settle the terminal. */
+               }
+           }
 
-               /* Set the modes if they've changed. */
-               if (memcmp(&mode, &oldmode, sizeof(mode)))
-#ifdef TERMIOS
-                       tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
-#else
-                       stty(STDERR_FILENO, &mode);
-#endif
+           update_tty_settings(&oldmode, &mode);
        }
+    }
 
-       /* Get the terminal name from the entry. */
-       ttype = _nc_first_name(cur_term->type.term_names);
-
-       if (noset)
-               (void)printf("%s\n", ttype);
-       else {
-               if (showterm)
-                       (void)fprintf(stderr, "Terminal type is %s.\n", ttype);
-               /*
-                * If erase, kill and interrupt characters could have been
-                * modified and not -Q, display the changes.
-                */
-               if (!quiet) {
-                       report("Erase", VERASE, CERASE);
-                       report("Kill", VKILL, CINTR);
-                       report("Interrupt", VINTR, CKILL);
-               }
+    if (noset) {
+       (void) printf("%s\n", ttype);
+    } else {
+       if (showterm)
+           (void) fprintf(stderr, "Terminal type is %s.\n", ttype);
+       /*
+        * If erase, kill and interrupt characters could have been
+        * modified and not -Q, display the changes.
+        */
+       if (!quiet) {
+           print_tty_chars(&oldmode, &mode);
        }
+    }
 
-       if (Sflag)
-               err("The -S option is not supported under terminfo.");
-
-       if (sflag) {
-               /*
-                * Figure out what shell we're using.  A hack, we look for an
-                * environmental variable SHELL ending in "csh".
-                */
-               if ((p = getenv("SHELL")) != 0
-                && !strcmp(p + strlen(p) - 3, "csh"))
-                       p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
-               else
-                       p = "TERM=%s;\n";
-               (void) printf(p, ttype);
-       }
+    if (Sflag)
+       err("The -S option is not supported under terminfo.");
 
-       return EXIT_SUCCESS;
-}
+    if (sflag) {
+       print_shell_commands(ttype);
+    }
 
-/* tset.c ends here */
+    ExitProgram(EXIT_SUCCESS);
+}