Base version of ncurses-5.7 library
diff --git a/progs/tset.c b/progs/tset.c
new file mode 100644
index 0000000..6a4d2d6
--- /dev/null
+++ b/progs/tset.c
@@ -0,0 +1,1331 @@
+/****************************************************************************
+ * Copyright (c) 1998-2007,2008 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            *
+ * "Software"), to deal in the Software without restriction, including      *
+ * without limitation the rights to use, copy, modify, merge, publish,      *
+ * distribute, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
+ *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
+ *     and: Thomas E. Dickey                        1996-on                 *
+ ****************************************************************************/
+
+/*
+ * tset.c - terminal initialization utility
+ *
+ * This code was mostly swiped from 4.4BSD tset, with some obsolescent
+ * cruft removed and substantial portions rewritten.  A Regents of the
+ * University of California copyright applies to some portions of the
+ * code, and is reproduced below:
+ */
+/*-
+ * Copyright (c) 1980, 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 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
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define USE_LIBTINFO
+#define __INTERNAL_CAPS_VISIBLE	/* we need to see has_hardware_tabs */
+#include <progs.priv.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <termcap.h>
+#include <fcntl.h>
+
+#if HAVE_GETTTYNAM && HAVE_TTYENT_H
+#include <ttyent.h>
+#endif
+#ifdef NeXT
+char *ttyname(int fd);
+#endif
+
+#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>
+#endif
+
+#include <dump_entry.h>
+#include <transform.h>
+
+MODULE_ID("$Id: tset.c,v 1.76 2008/10/11 19:26:19 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
+
+extern char **environ;
+
+#undef CTRL
+#define CTRL(x)	((x) & 0x1f)
+
+const char *_nc_progname = "tset";
+
+static TTY mode, oldmode, original;
+
+static bool opt_c;		/* set control-chars */
+static bool opt_w;		/* set 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(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);
+}
+
+static void
+exit_error(void)
+{
+    if (can_restore)
+	SET_TTY(STDERR_FILENO, &original);
+    (void) fprintf(stderr, "\n");
+    fflush(stderr);
+    ExitProgram(EXIT_FAILURE);
+    /* NOTREACHED */
+}
+
+static void
+err(const char *fmt,...)
+{
+    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];
+    unsigned 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)
+{
+    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);
+}
+
+/* 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. */
+    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);
+	}
+
+	if ((p = strchr(answer, '\n')) != 0)
+	    *p = '\0';
+	if (answer[0])
+	    return (answer);
+	if (dflt != 0)
+	    return (dflt);
+    }
+}
+
+/**************************************************************************
+ *
+ * Mapping logic begins here
+ *
+ **************************************************************************/
+
+/* Baud rate conditionals for mapping. */
+#define	GT		0x01
+#define	EQ		0x02
+#define	LT		0x04
+#define	NOT		0x08
+#define	GE		(GT | EQ)
+#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. */
+} MAP;
+
+static MAP *cur, *maplist;
+
+typedef struct speeds {
+    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},
+    /* sgttyb may define up to this point */
+#ifdef 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},
+#endif
+#endif
+#ifdef B38400
+    {"38400", B38400},
+#else
+#ifdef EXTB
+    {"38400", EXTB},
+#endif
+#endif
+#ifdef B57600
+    {"57600", B57600},
+#endif
+#ifdef B115200
+    {"115200", B115200},
+#endif
+#ifdef B230400
+    {"230400", B230400},
+#endif
+#ifdef B460800
+    {"460800", B460800},
+#endif
+    {(char *) 0, 0}
+};
+
+static int
+tbaudrate(char *rate)
+{
+    const SPEEDS *sp;
+    int found = FALSE;
+
+    /* 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;
+	}
+    }
+    if (!found)
+	err("unknown baud rate %s", rate);
+    return (sp->speed);
+}
+
+/*
+ * Syntax for -m:
+ * [port-type][test baudrate]:terminal-type
+ * The baud rate tests are: >, <, @, =, !
+ */
+static void
+add_mapping(const char *port, char *arg)
+{
+    MAP *mapp;
+    char *copy, *p;
+    const char *termp;
+    char *base = 0;
+
+    copy = strdup(arg);
+    mapp = (MAP *) malloc(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. */
+	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;
+    }
+    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
+}
+
+/*
+ * Return the type of terminal to use for a port of type 'type', as specified
+ * by the first applicable mapping in 'map'.  If no mappings apply, return
+ * 'type'.
+ */
+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);
+}
+
+/**************************************************************************
+ *
+ * Entry fetching
+ *
+ **************************************************************************/
+
+/*
+ * Figure out what kind of terminal we're dealing with, and then read in
+ * its termcap entry.
+ */
+static const char *
+get_termcap_entry(char *userarg)
+{
+    int errret;
+    char *p;
+    const char *ttype;
+#if HAVE_GETTTYNAM
+    struct ttyent *t;
+#else
+    FILE *fp;
+#endif
+    char *ttypath;
+
+    if (userarg) {
+	ttype = userarg;
+	goto found;
+    }
+
+    /* Try the environment. */
+    if ((ttype = getenv("TERM")) != 0)
+	goto map;
+
+    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;
+	}
+#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);
+	}
+#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.
+	 */
+	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 (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' */
+#endif
+    return (ttype);
+}
+
+/**************************************************************************
+ *
+ * Mode-setting logic
+ *
+ **************************************************************************/
+
+/* some BSD systems have these built in, some systems are missing
+ * 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
+#undef CKILL
+#undef CLNEXT
+#undef CRPRNT
+#undef CQUIT
+#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
+
+#if defined(_POSIX_VDISABLE)
+#define DISABLED(val)   (((_POSIX_VDISABLE != -1) \
+		       && ((val) == _POSIX_VDISABLE)) \
+		      || ((val) <= 0))
+#else
+#define DISABLED(val)   ((int)(val) <= 0)
+#endif
+
+#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
+ * 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
+#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
+#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
+
+    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;
+
+    if (over_strike
+	&& key_backspace != 0
+	&& strlen(key_backspace) == 1)
+	result = key_backspace[0];
+    else
+	result = CERASE;
+
+    return result;
+}
+#endif
+
+/*
+ * 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.
+ */
+static void
+set_control_chars(void)
+{
+#ifdef TERMIOS
+    if (DISABLED(mode.c_cc[VERASE]) || terasechar >= 0)
+	mode.c_cc[VERASE] = (terasechar >= 0) ? terasechar : default_erase();
+
+    if (DISABLED(mode.c_cc[VINTR]) || intrchar >= 0)
+	mode.c_cc[VINTR] = (intrchar >= 0) ? intrchar : CINTR;
+
+    if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0)
+	mode.c_cc[VKILL] = (tkillchar >= 0) ? tkillchar : CKILL;
+#endif
+}
+
+/*
+ * 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 (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;
+    }
+#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)
+{
+    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);
+	SET_TTY(STDERR_FILENO, &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. */
+    }
+}
+
+/*
+ * 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(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 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);
+	}
+	putc('\r', stderr);
+	return (TRUE);
+    }
+    return (FALSE);
+}
+
+/**************************************************************************
+ *
+ * Main sequence
+ *
+ **************************************************************************/
+
+/*
+ * Tell the user if a control key has been changed from the default value.
+ */
+#ifdef TERMIOS
+static void
+report(const char *name, int which, unsigned def)
+{
+    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.
+ * This means that -e, -i and -k get default arguments supplied for them.
+ */
+static void
+obsolete(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;
+	}
+    }
+}
+
+static void
+usage(void)
+{
+    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)
+{
+    return (char) ((optarg[0] == '^' && optarg[1] != '\0')
+		   ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
+		   : optarg[0]);
+}
+
+int
+main(int argc, char **argv)
+{
+    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();
+	}
+    }
+
+    _nc_progname = _nc_rootname(*argv);
+    argc -= optind;
+    argv += optind;
+
+    if (argc > 1)
+	usage();
+
+    if (!opt_c && !opt_w)
+	opt_c = opt_w = TRUE;
+
+    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 (!strcmp(_nc_progname, PROG_RESET)) {
+	isreset = TRUE;
+	reset_mode();
+    }
+
+    ttype = 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();
+
+	    if (!noinit)
+		set_init();
+
+	    /* Set the modes if they've changed. */
+	    if (memcmp(&mode, &oldmode, sizeof(mode))) {
+		SET_TTY(STDERR_FILENO, &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.
+	 */
+#ifdef TERMIOS
+	if (!quiet) {
+	    report("Erase", VERASE, CERASE);
+	    report("Kill", VKILL, CKILL);
+	    report("Interrupt", VINTR, CINTR);
+	}
+#endif
+    }
+
+    if (Sflag)
+	err("The -S option is not supported under terminfo.");
+
+    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);
+    }
+
+    ExitProgram(EXIT_SUCCESS);
+}