ncurses 5.9 - patch 20110521
[ncurses.git] / progs / tset.c
index 1df3fd64986923cdb79957030eefbd81dd91b315..71a1845ff7d0b2512d5b4847bd1b54d2ed246c97 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998 Free Software Foundation, Inc.                        *
+ * Copyright (c) 1998-2010,2011 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.
  *
@@ -73,6 +85,7 @@
  * SUCH DAMAGE.
  */
 
+#define USE_LIBTINFO
 #define __INTERNAL_CAPS_VISIBLE        /* we need to see has_hardware_tabs */
 #include <progs.priv.h>
 
 char *ttyname(int fd);
 #endif
 
-/* this is just to stifle a missing-prototype warning */
-#ifdef linux
-# include <sys/ioctl.h>
+#if HAVE_SIZECHANGE
+# if !defined(sun) || !TERMIOS
+#  if HAVE_SYS_IOCTL_H
+#   include <sys/ioctl.h>
+#  endif
+# endif
 #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>
+#include <sys/stream.h>
+#include <sys/ptem.h>
 #endif
 
-#include <curses.h>    /* for bool typedef */
 #include <dump_entry.h>
+#include <transform.h>
+
+MODULE_ID("$Id: tset.c,v 1.84 2011/05/21 18:55:32 tom Exp $")
 
-MODULE_ID("$Id: tset.c,v 0.31 1998/02/11 12:14:02 tom Exp $")
+/*
+ * SCO defines TIOCGSIZE and the corresponding struct.  Other systems (SunOS,
+ * Solaris, IRIX) define TIOCGWINSZ and struct winsize.
+ */
+#ifdef TIOCGSIZE
+# define IOCTL_GET_WINSIZE TIOCGSIZE
+# define IOCTL_SET_WINSIZE TIOCSSIZE
+# define STRUCT_WINSIZE struct ttysize
+# define WINSIZE_ROWS(n) n.ts_lines
+# define WINSIZE_COLS(n) n.ts_cols
+#else
+# ifdef TIOCGWINSZ
+#  define IOCTL_GET_WINSIZE TIOCGWINSZ
+#  define IOCTL_SET_WINSIZE TIOCSWINSZ
+#  define STRUCT_WINSIZE struct winsize
+#  define WINSIZE_ROWS(n) n.ws_row
+#  define WINSIZE_COLS(n) n.ws_col
+# endif
+#endif
 
+#ifndef environ
 extern char **environ;
+#endif
 
 #undef CTRL
 #define CTRL(x)        ((x) & 0x1f)
 
+static void failed(const char *) GCC_NORETURN;
+static void exit_error(void) GCC_NORETURN;
+static void err(const char *,...) GCC_NORETURN;
+
 const char *_nc_progname = "tset";
 
-static TTY mode, oldmode;
+static TTY mode, oldmode, original;
+
+static bool opt_c;             /* set control-chars */
+static bool opt_w;             /* set window-size */
 
-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 */
+static bool can_restore = FALSE;
+static bool isreset = FALSE;   /* invoked as reset */
+static int terasechar = -1;    /* new erase character */
+static int intrchar = -1;      /* new interrupt character */
+static int tkillchar = -1;     /* new kill character */
+static int tlines, tcolumns;   /* window size */
 
-#define LOWERCASE(c) ((isalpha(c) && isupper(c)) ? tolower(c) : (c))
+#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
 
 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);
+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)
+static void
+exit_error(void)
 {
-  char *p;
-
-  p = malloc(strlen(s)+1);
-  if (p)
-    strcpy(p,s);
-  return(p);
+    if (can_restore)
+       SET_TTY(STDERR_FILENO, &original);
+    (void) fprintf(stderr, "\n");
+    fflush(stderr);
+    ExitProgram(EXIT_FAILURE);
+    /* NOTREACHED */
 }
-#endif /* not HAVE_STRDUP */
 
 static void
-err(const char *fmt, ...)
+err(const char *fmt,...)
 {
-       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 */
+    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
 failed(const char *msg)
 {
-       char    temp[BUFSIZ];
-       perror(strcat(strcpy(temp, "tset: "), msg));
-       exit(EXIT_FAILURE);
-       /* NOTREACHED */
+    char temp[BUFSIZ];
+    size_t len = strlen(_nc_progname) + 2;
+
+    if ((int) len < (int) sizeof(temp) - 12) {
+       strcpy(temp, _nc_progname);
+       strcat(temp, ": ");
+    } else {
+       strcpy(temp, "tset: ");
+    }
+    perror(strncat(temp, msg, sizeof(temp) - strlen(temp) - 2));
+    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);
+    FILE *fp;
+    size_t nr;
+    char buf[BUFSIZ];
+
+    if ((fp = fopen(file, "r")) == 0)
+       failed(file);
+
+    while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0)
+       if (fwrite(buf, sizeof(char), nr, stderr) != nr)
+             failed("write to stderr");
+    fclose(fp);
 }
 
 static int
 outc(int c)
 {
-       return putc(c, stderr);
+    return putc(c, stderr);
 }
 
 /* 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 +295,98 @@ 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;
 
 typedef struct speeds {
-       const char *string;
-       int     speed;
+    const char *string;
+    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[] =
+{
+    {"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},
+    /* sgttyb may define up to this point */
 #ifdef B19200
-       { "19200",      B19200 },
+    {"19200", B19200},
+#endif
+#ifdef B38400
+    {"38400", B38400},
+#endif
+#ifdef B19200
+    {"19200", B19200},
+#endif
+#ifdef B38400
+    {"38400", B38400},
+#endif
+#ifdef B19200
+    {"19200", B19200},
 #else
 #ifdef EXTA
-       { "19200",      EXTA },
+    {"19200", EXTA},
 #endif
 #endif
 #ifdef B38400
-       { "38400",      B38400 },
+    {"38400", B38400},
 #else
 #ifdef EXTB
-       { "38400",      EXTB },
+    {"38400", EXTB},
 #endif
 #endif
 #ifdef B57600
-       { "57600",      B57600 },
+    {"57600", B57600},
 #endif
 #ifdef B115200
-       { "115200",     B115200 },
+    {"115200", B115200},
 #endif
 #ifdef B230400
-       { "230400",     B230400 },
+    {"230400", B230400},
 #endif
 #ifdef B460800
-       { "460800",     B460800 },
+    {"460800", B460800},
 #endif
-       { (char *)0,    0 }
+    {(char *) 0, 0}
 };
 
 static int
 tbaudrate(char *rate)
 {
-       const SPEEDS *sp;
-       int found = FALSE;
+    const SPEEDS *sp;
+    int found = FALSE;
 
-       /* 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 (sp = speeds; sp->string; ++sp) {
+       if (!CaselessCmp(rate, sp->string)) {
+           found = TRUE;
+           break;
        }
-       if (!found)
-               err("unknown baud rate %s", rate);
-       return (sp->speed);
+    }
+    if (!found)
+       err("unknown baud rate %s", rate);
+    return (sp->speed);
 }
 
 /*
@@ -334,110 +397,119 @@ 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);
+    }
+
+    if (arg == (char *) 0)     /* Non-optional type. */
+       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);
        }
-       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 +521,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 = (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);
 }
 
 /**************************************************************************
@@ -496,119 +568,117 @@ mapped(const char *type)
 static const char *
 get_termcap_entry(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;
-       }
+    if (userarg) {
+       ttype = userarg;
+       goto found;
+    }
 
-       /* Try the environment. */
-       if ((ttype = getenv("TERM")) != 0)
-               goto map;
+    /* Try the environment. */
+    if ((ttype = getenv("TERM")) != 0)
+       goto map;
 
-       if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
-               if ((p = strrchr(ttypath, '/')) != 0)
-                       ++p;
-               else
-                       p = ttypath;
+    if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
+       p = _nc_basename(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;
-               }
+       /*
+        * 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);
+       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;
                }
-#endif /* HAVE_GETTTYNAM */
+               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";
+    /* If still undefined, use "unknown". */
+    ttype = "unknown";
 
-map:   ttype = mapped(ttype);
+  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.
+    /*
+     * 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.
         */
-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;
-                       }
+       int n;
+       for (n = 0; environ[n] != 0; n++) {
+           if (!strncmp("TERMCAP=", environ[n], 8)) {
+               while ((environ[n] = environ[n + 1]) != 0) {
+                   n++;
                }
+               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 ((rval = setupterm(ttype, STDOUT_FILENO, &errret)) != OK) {
-               if (errret == 0) {
-                       (void)fprintf(stderr, "tset: unknown terminal type %s\n",
-                           ttype);
-                       ttype = 0;
-               }
-               else {
-                       (void)fprintf(stderr, "tset: can't initialize terminal\
-                           type %s (error %d)\n", ttype, errret);
-                       ttype = 0;
-               }
-               ttype = askuser(ttype);
+    }
+
+    /*
+     * 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, STDOUT_FILENO, &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);
 }
 
 /**************************************************************************
@@ -618,8 +688,10 @@ found:     if ((p = getenv("TERMCAP")) != 0 && *p != '/') {
  **************************************************************************/
 
 /* some BSD systems have these built in, some systems are missing
- * one or more definitions. The safest solution is to override.
+ * one or more definitions. The safest solution is to override unless the
+ * commonly-altered ones are defined.
  */
+#if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT))
 #undef CEOF
 #undef CERASE
 #undef CINTR
@@ -630,22 +702,51 @@ found:    if ((p = getenv("TERMCAP")) != 0 && *p != '/') {
 #undef CSTART
 #undef CSTOP
 #undef CSUSP
+#endif
 
 /* control-character defaults */
+#ifndef CEOF
 #define CEOF   CTRL('D')
+#endif
+#ifndef CERASE
 #define CERASE CTRL('H')
+#endif
+#ifndef CINTR
 #define CINTR  127             /* ^? */
+#endif
+#ifndef CKILL
 #define CKILL  CTRL('U')
+#endif
+#ifndef CLNEXT
 #define CLNEXT  CTRL('v')
+#endif
+#ifndef CRPRNT
 #define CRPRNT  CTRL('r')
+#endif
+#ifndef CQUIT
 #define CQUIT  CTRL('\\')
+#endif
+#ifndef CSTART
 #define CSTART CTRL('Q')
+#endif
+#ifndef CSTOP
 #define CSTOP  CTRL('S')
+#endif
+#ifndef CSUSP
 #define CSUSP  CTRL('Z')
+#endif
 
-#define        CHK(val, dft)   ((int)val <= 0 ? dft : val)
+#if defined(_POSIX_VDISABLE)
+#define DISABLED(val)   (((_POSIX_VDISABLE != -1) \
+                      && ((val) == _POSIX_VDISABLE)) \
+                     || ((val) <= 0))
+#else
+#define DISABLED(val)   ((int)(val) <= 0)
+#endif
 
-static bool    set_tabs (void);
+#define CHK(val, dft)   (DISABLED(val) ? dft : val)
+
+static bool set_tabs(void);
 
 /*
  * Reset the terminal mode bits to a sensible state.  Very useful after
@@ -655,136 +756,149 @@ static void
 reset_mode(void)
 {
 #ifdef TERMIOS
-       tcgetattr(STDERR_FILENO, &mode);
+    tcgetattr(STDERR_FILENO, &mode);
 #else
-       stty(STDERR_FILENO,&mode);
+    stty(STDERR_FILENO, &mode);
 #endif
 
 #ifdef TERMIOS
 #if defined(VDISCARD) && defined(CDISCARD)
-       mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], 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);
+    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);
+    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);
+    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);
+    mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
 #endif
-       mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
+    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);
+    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);
+    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);
+    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);
+    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);
+    mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
 #endif
 
-       mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
+    mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
 #ifdef IUCLC
-                         | IUCLC
+                     | IUCLC
 #endif
 #ifdef IXANY
-                         | IXANY
+                     | IXANY
 #endif
-                         | IXOFF);
+                     | IXOFF);
 
-       mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
+    mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
 #ifdef IMAXBEL
-                        | IMAXBEL
+                    | IMAXBEL
 #endif
-                        );
+       );
 
-       mode.c_oflag &= ~(0
+    mode.c_oflag &= ~(0
 #ifdef OLCUC
-                         | OLCUC
+                     | OLCUC
 #endif
 #ifdef OCRNL
-                         | OCRNL
+                     | OCRNL
 #endif
 #ifdef ONOCR
-                         | ONOCR
+                     | ONOCR
 #endif
 #ifdef ONLRET
-                         | ONLRET
+                     | ONLRET
 #endif
 #ifdef OFILL
-                         | OFILL
+                     | OFILL
 #endif
 #ifdef OFDEL
-                         | OFDEL
+                     | OFDEL
 #endif
 #ifdef NLDLY
-                         | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY
+                     | NLDLY
+#endif
+#ifdef CRDLY
+                     | CRDLY
+#endif
+#ifdef TABDLY
+                     | TABDLY
+#endif
+#ifdef BSDLY
+                     | BSDLY
+#endif
+#ifdef VTDLY
+                     | VTDLY
 #endif
-                         );
+#ifdef FFDLY
+                     | FFDLY
+#endif
+       );
 
-       mode.c_oflag |= (OPOST
+    mode.c_oflag |= (OPOST
 #ifdef ONLCR
-                        | ONLCR
+                    | ONLCR
 #endif
-                        );
+       );
 
-       mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
-       mode.c_cflag |= (CS8 | CREAD);
-       mode.c_lflag &= ~(ECHONL | NOFLSH
+    mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
+    mode.c_cflag |= (CS8 | CREAD);
+    mode.c_lflag &= ~(ECHONL | NOFLSH
 #ifdef TOSTOP
-                         | TOSTOP
+                     | TOSTOP
 #endif
 #ifdef ECHOPTR
-                         | ECHOPRT
+                     | ECHOPRT
 #endif
 #ifdef XCASE
-                         | XCASE
+                     | XCASE
 #endif
-                         );
+       );
 
-       mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
+    mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
 #ifdef ECHOCTL
-                        | ECHOCTL
+                    | ECHOCTL
 #endif
 #ifdef ECHOKE
-                        | ECHOKE
+                    | ECHOKE
 #endif
-                        );
+       );
 #endif
 
-#ifdef TERMIOS
-       tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
-#else
-       stty(STDERR_FILENO, &mode);
-#endif
+    SET_TTY(STDERR_FILENO, &mode);
 }
 
 /*
  * Returns a "good" value for the erase character.  This is loosely based on
  * the BSD4.4 logic.
  */
+#ifdef TERMIOS
 static int
 default_erase(void)
 {
-       int result;
+    int result;
 
-       if (over_strike
-        && key_backspace != 0
-        && strlen(key_backspace) == 1)
-               result = key_backspace[0];
-       else
-               result = CERASE;
+    if (over_strike
+       && key_backspace != 0
+       && strlen(key_backspace) == 1)
+       result = key_backspace[0];
+    else
+       result = CERASE;
 
-       return result;
+    return result;
 }
+#endif
 
 /*
  * Update the values of the erase, interrupt, and kill characters in 'mode'.
@@ -797,14 +911,14 @@ static void
 set_control_chars(void)
 {
 #ifdef TERMIOS
-       if (mode.c_cc[VERASE] == 0 || terasechar >= 0)
-               mode.c_cc[VERASE] = terasechar >= 0 ? terasechar : default_erase();
+    if (DISABLED(mode.c_cc[VERASE]) || 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 (DISABLED(mode.c_cc[VINTR]) || 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;
+    if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0)
+       mode.c_cc[VKILL] = (tkillchar >= 0) ? tkillchar : CKILL;
 #endif
 }
 
@@ -818,62 +932,62 @@ 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")) {
+    /*
+     * 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;
+       mode.c_iflag |= IUCLC;
+       mode.c_oflag |= OLCUC;
 #endif
-       } else if (tgetflag("LC")) {
+    } else if (tgetflag("LC")) {
 #ifdef IUCLC
-               mode.c_iflag &= ~IUCLC;
-               mode.c_oflag &= ~OLCUC;
+       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 (tgetflag("OP")) {
-               mode.c_cflag |= PARENB;
-               mode.c_cflag |= PARODD;
-       }
+    }
+    mode.c_iflag &= ~(PARMRK | INPCK);
+    mode.c_lflag |= ICANON;
+    if (tgetflag("EP")) {
+       mode.c_cflag |= PARENB;
+       mode.c_cflag &= ~PARODD;
+    }
+    if (tgetflag("OP")) {
+       mode.c_cflag |= PARENB;
+       mode.c_cflag |= PARODD;
+    }
 #endif /* __OBSOLETE__ */
 
 #ifdef TERMIOS
 #ifdef ONLCR
-       mode.c_oflag |= ONLCR;
+    mode.c_oflag |= ONLCR;
 #endif
-       mode.c_iflag |= ICRNL;
-       mode.c_lflag |= ECHO;
+    mode.c_iflag |= ICRNL;
+    mode.c_lflag |= ECHO;
 #ifdef OXTABS
-       mode.c_oflag |= 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. */
+    /* test used to be tgetflag("NL") */
+    if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) {
+       /* Newline, not linefeed. */
 #ifdef ONLCR
-               mode.c_oflag &= ~ONLCR;
+       mode.c_oflag &= ~ONLCR;
 #endif
-               mode.c_iflag &= ~ICRNL;
-       }
+       mode.c_iflag &= ~ICRNL;
+    }
 #ifdef __OBSOLETE__
-       if (tgetflag("HD"))                     /* Half duplex. */
-               mode.c_lflag &= ~ECHO;
+    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;
+    /* test used to be tgetflag("pt") */
+    if (has_hardware_tabs)     /* Print tabs. */
+       mode.c_oflag &= ~OXTABS;
 #endif /* OXTABS */
-       mode.c_lflag |= (ECHOE | ECHOK);
+    mode.c_lflag |= (ECHOE | ECHOK);
 #endif
 }
 
@@ -881,45 +995,45 @@ set_conversions(void)
 static void
 set_init(void)
 {
-       char    *p;
-       bool settle;
+    char *p;
+    bool settle;
 
 #ifdef __OBSOLETE__
-       if (pad_char != (char *)0)              /* Get/set pad character. */
-               PC = pad_char[0];
+    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);
-       }
+    if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
+       oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
+       SET_TTY(STDERR_FILENO, &oldmode);
+    }
 #endif
-       settle = set_tabs();
+    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 (isreset) {
+       if ((p = reset_1string) != 0) {
+           tputs(p, 0, outc);
+           settle = TRUE;
        }
-
-       if (settle) {
-               (void)putc('\r', stderr);
-               (void)fflush(stderr);
-               (void)napms(1000);      /* Settle the terminal. */
+       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. */
+    }
 }
 
 /*
@@ -929,30 +1043,30 @@ set_init(void)
  * Return TRUE if we set any tab stops, FALSE if not.
  */
 static bool
-set_tabs()
+set_tabs(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);
+    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 than .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);
        }
-       return (FALSE);
+       putc('\r', stderr);
+       return (TRUE);
+    }
+    return (FALSE);
 }
 
 /**************************************************************************
@@ -964,38 +1078,40 @@ set_tabs()
 /*
  * Tell the user if a control key has been changed from the default value.
  */
+#ifdef TERMIOS
 static void
-report(const char *name, int which, u_int def)
+report(const char *name, int which, unsigned def)
 {
-#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
+    unsigned 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");
+
+    if (DISABLED(newer))
+       (void) fprintf(stderr, "undef.\n");
+    /*
+     * Check 'delete' before 'backspace', since the key_backspace value
+     * is ambiguous.
+     */
+    else if (newer == 0177)
+       (void) fprintf(stderr, "delete.\n");
+    else if ((p = key_backspace) != 0
+            && newer == (unsigned char) p[0]
+            && p[1] == '\0')
+       (void) fprintf(stderr, "backspace.\n");
+    else if (newer < 040) {
+       newer ^= 0100;
+       (void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer));
+    } else
+       (void) fprintf(stderr, "%c.\n", UChar(newer));
 }
+#endif
 
 /*
  * Convert the obsolete argument forms into something that getopt can handle.
@@ -1004,205 +1120,234 @@ report(const char *name, int which, u_int def)
 static void
 obsolete(char **argv)
 {
-       for (; *argv; ++argv) {
-               char *parm = argv[0];
+    for (; *argv; ++argv) {
+       char *parm = argv[0];
 
-               if (parm[0] == '-' && parm[1] == '\0')
-               {
-                   argv[0] = strdup("-q");
-                   continue;
-               }
+       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;
-               }
+       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;
        }
+    }
 }
 
 static void
-usage(const char* pname)
+usage(void)
 {
-       (void)fprintf(stderr,
-"usage: %s [-IQrs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n", pname);
-       exit(EXIT_FAILURE);
+    static const char *tbl[] =
+    {
+       ""
+       ,"Options:"
+       ,"  -c          set control characters"
+       ,"  -e ch       erase character"
+       ,"  -I          no initialization strings"
+       ,"  -i ch       interrupt character"
+       ,"  -k ch       kill character"
+       ,"  -m mapping  map identifier to type"
+       ,"  -Q          do not output control key settings"
+       ,"  -r          display term on stderr"
+       ,"  -s          output TERM set command"
+       ,"  -V          print curses-version"
+       ,"  -w          set window-size"
+    };
+    unsigned n;
+    (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
+    for (n = 0; n < sizeof(tbl) / sizeof(tbl[0]); ++n)
+       fprintf(stderr, "%s\n", tbl[n]);
+    exit_error();
+    /* NOTREACHED */
 }
 
-static char arg_to_char(void)
+static char
+arg_to_char(void)
 {
-       return (optarg[0] == '^' && optarg[1] != '\0')
-               ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
-               : optarg[0];
+    return (char) ((optarg[0] == '^' && optarg[1] != '\0')
+                  ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
+                  : optarg[0]);
 }
 
 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;
+    int ch, noinit, noset, quiet, Sflag, sflag, showterm;
+    const char *p;
+    const char *ttype;
+
+    obsolete(argv);
+    noinit = noset = quiet = Sflag = sflag = showterm = 0;
+    while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:np: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 '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 '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();
+       }
+    }
 
-#ifdef TERMIOS
-       if (tcgetattr(STDERR_FILENO, &mode) < 0)
-               failed("standard error");
+    _nc_progname = _nc_rootname(*argv);
+    argc -= optind;
+    argv += optind;
 
-       oldmode = mode;
-       ospeed = cfgetospeed(&mode);
-#else
-       if (gtty(STDERR_FILENO, &mode) < 0)
-               failed("standard error");
+    if (argc > 1)
+       usage();
+
+    if (!opt_c && !opt_w)
+       opt_c = opt_w = TRUE;
 
-       oldmode = mode;
-       ospeed = mode.sg_ospeed;
+    if (GET_TTY(STDERR_FILENO, &mode) < 0)
+       failed("standard error");
+    can_restore = TRUE;
+    original = oldmode = mode;
+#ifdef TERMIOS
+    ospeed = (NCURSES_OSPEED) cfgetospeed(&mode);
+#else
+    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)) {
+       isreset = TRUE;
+       reset_mode();
+    }
+
+    (void) get_termcap_entry(*argv);
+
+    if (!noset) {
+       tcolumns = columns;
+       tlines = lines;
+
+#if HAVE_SIZECHANGE
+       if (opt_w) {
+           STRUCT_WINSIZE win;
+           /* Set window size if not set already */
+           (void) ioctl(STDERR_FILENO, IOCTL_GET_WINSIZE, &win);
+           if (WINSIZE_ROWS(win) == 0 &&
+               WINSIZE_COLS(win) == 0 &&
+               tlines > 0 && tcolumns > 0) {
+               WINSIZE_ROWS(win) = tlines;
+               WINSIZE_COLS(win) = tcolumns;
+               (void) ioctl(STDERR_FILENO, IOCTL_SET_WINSIZE, &win);
+           }
        }
+#endif
+       if (opt_c) {
+           set_control_chars();
+           set_conversions();
 
-       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);
-               }
+           if (!noinit)
+               set_init();
+
+           /* Set the modes if they've changed. */
+           if (memcmp(&mode, &oldmode, sizeof(mode))) {
+               SET_TTY(STDERR_FILENO, &mode);
+           }
        }
-       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 (!noinit)
-                       set_init();
+    /* Get the terminal name from the entry. */
+    ttype = _nc_first_name(cur_term->type.term_names);
 
-               /* Set the modes if they've changed. */
-               if (memcmp(&mode, &oldmode, sizeof(mode)))
+    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.
+        */
 #ifdef TERMIOS
-                       tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
-#else
-                       stty(STDERR_FILENO, &mode);
-#endif
+       if (!quiet) {
+           report("Erase", VERASE, CERASE);
+           report("Kill", VKILL, CKILL);
+           report("Interrupt", VINTR, CINTR);
        }
+#endif
+    }
 
-       /* 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 (Sflag)
+       err("The -S option is not supported under terminfo.");
 
-       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) {
+       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);
+    }
 
-       return EXIT_SUCCESS;
+    ExitProgram(EXIT_SUCCESS);
 }
-
-/* tset.c ends here */