/****************************************************************************
- * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. *
+ * Copyright 2020,2021 Thomas E. Dickey *
+ * Copyright 1998-2016,2017 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
/****************************************************************************
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
* and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey 1996-on *
****************************************************************************/
+/*
+ * Notes:
+ * The initial adaptation from 4.4BSD Lite sources in September 1995 used 686
+ * lines from that version, and made changes/additions for 150 lines. There
+ * was no reformatting, so with/without ignoring whitespace, the amount of
+ * change is the same.
+ *
+ * Comparing with current (2009) source, excluding this comment:
+ * a) 209 lines match identically to the 4.4BSD Lite sources, with 771 lines
+ * changed/added.
+ * a) Ignoring whitespace, the current version still uses 516 lines from the
+ * 4.4BSD Lite sources, with 402 lines changed/added.
+ *
+ * Raymond's original comment on this follows...
+ */
+
/*
* tset.c - terminal initialization utility
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* SUCH DAMAGE.
*/
-#define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */
-#include <progs.priv.h>
-
-#include <errno.h>
-#include <stdio.h>
+#include <reset_cmd.h>
#include <termcap.h>
-#include <fcntl.h>
+#include <transform.h>
+#include <tty_settings.h>
-#if HAVE_GETTTYNAM && HAVE_TTYENT_H
+#if HAVE_GETTTYNAM
#include <ttyent.h>
#endif
#ifdef NeXT
char *ttyname(int fd);
#endif
-/* this is just to stifle a missing-prototype warning */
-#ifdef linux
-# include <sys/ioctl.h>
-#endif
-
-#if NEED_PTEM_H
-/* they neglected to define struct winsize in termios.h -- it's only
- in termio.h */
-#include <sys/stream.h>
-#include <sys/ptem.h>
-#endif
-
-#include <curses.h> /* for bool typedef */
-#include <dump_entry.h>
-#include <transform.h>
-
-MODULE_ID("$Id: tset.c,v 0.47 2000/10/08 01:01:08 tom Exp $")
+MODULE_ID("$Id: tset.c,v 1.131 2021/12/04 23:02:13 tom Exp $")
+#ifndef environ
extern char **environ;
-
-#undef CTRL
-#define CTRL(x) ((x) & 0x1f)
+#endif
const char *_nc_progname = "tset";
-static TTY mode, oldmode;
+#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
-static 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))
+static GCC_NORETURN void exit_error(void);
static int
CaselessCmp(const char *a, const char *b)
return LOWERCASE(*a) - LOWERCASE(*b);
}
-static void
-err(const char *fmt,...)
+static GCC_NORETURN void
+exit_error(void)
+{
+ restore_tty_settings();
+ (void) fprintf(stderr, "\n");
+ fflush(stderr);
+ ExitProgram(EXIT_FAILURE);
+ /* NOTREACHED */
+}
+
+static GCC_NORETURN void
+err(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- (void) fprintf(stderr, "tset: ");
+ (void) fprintf(stderr, "%s: ", _nc_progname);
(void) vfprintf(stderr, fmt, ap);
va_end(ap);
- (void) fprintf(stderr, "\n");
- exit(EXIT_FAILURE);
+ exit_error();
/* NOTREACHED */
}
-static void
+static GCC_NORETURN void
failed(const char *msg)
{
char temp[BUFSIZ];
- perror(strncat(strcpy(temp, "tset: "), msg, sizeof(temp) - 10));
- exit(EXIT_FAILURE);
- /* 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);
-}
+ size_t len = strlen(_nc_progname) + 2;
-static int
-outc(int c)
-{
- return putc(c, stderr);
+ if ((int) len < (int) sizeof(temp) - 12) {
+ _nc_STRCPY(temp, _nc_progname, sizeof(temp));
+ _nc_STRCAT(temp, ": ", sizeof(temp));
+ } else {
+ _nc_STRCPY(temp, "tset: ", sizeof(temp));
+ }
+ _nc_STRNCAT(temp, msg, sizeof(temp), sizeof(temp) - strlen(temp) - 2);
+ perror(temp);
+ exit_error();
+ /* NOTREACHED */
}
/* Prompt the user for a terminal type. */
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(EXIT_FAILURE);
+ exit_error();
+ /* NOTREACHED */
}
+
for (;;) {
+ char *p;
+
if (dflt)
(void) fprintf(stderr, "Terminal type? [%s] ", dflt);
else
if (fgets(answer, sizeof(answer), stdin) == 0) {
if (dflt == 0) {
- (void) fprintf(stderr, "\n");
- exit(EXIT_FAILURE);
+ exit_error();
+ /* NOTREACHED */
}
return (dflt);
}
static MAP *cur, *maplist;
+#define DATA(name,value) { { name }, value }
+
typedef struct speeds {
- const char *string;
+ const char string[8];
int speed;
} SPEEDS;
+#if defined(EXP_WIN32_DRIVER)
+static const SPEEDS speeds[] =
+{
+ {"0", 0}
+};
+#else
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},
+ DATA("0", B0),
+ DATA("50", B50),
+ DATA("75", B75),
+ DATA("110", B110),
+ DATA("134", B134),
+ DATA("134.5", B134),
+ DATA("150", B150),
+ DATA("200", B200),
+ DATA("300", B300),
+ DATA("600", B600),
+ DATA("1200", B1200),
+ DATA("1800", B1800),
+ DATA("2400", B2400),
+ DATA("4800", B4800),
+ DATA("9600", B9600),
/* sgttyb may define up to this point */
#ifdef B19200
- {"19200", B19200},
+ DATA("19200", B19200),
#endif
#ifdef B38400
- {"38400", B38400},
+ DATA("38400", B38400),
#endif
#ifdef B19200
- {"19200", B19200},
+ DATA("19200", B19200),
#endif
#ifdef B38400
- {"38400", B38400},
+ DATA("38400", B38400),
#endif
#ifdef B19200
- {"19200", B19200},
+ DATA("19200", B19200),
#else
#ifdef EXTA
- {"19200", EXTA},
+ DATA("19200", EXTA),
#endif
#endif
#ifdef B38400
- {"38400", B38400},
+ DATA("38400", B38400),
#else
#ifdef EXTB
- {"38400", EXTB},
+ DATA("38400", EXTB),
#endif
#endif
#ifdef B57600
- {"57600", B57600},
+ DATA("57600", B57600),
+#endif
+#ifdef B76800
+ DATA("76800", B57600),
#endif
#ifdef B115200
- {"115200", B115200},
+ DATA("115200", B115200),
+#endif
+#ifdef B153600
+ DATA("153600", B153600),
#endif
#ifdef B230400
- {"230400", B230400},
+ DATA("230400", B230400),
+#endif
+#ifdef B307200
+ DATA("307200", B307200),
#endif
#ifdef B460800
- {"460800", B460800},
+ DATA("460800", B460800),
+#endif
+#ifdef B500000
+ DATA("500000", B500000),
+#endif
+#ifdef B576000
+ DATA("576000", B576000),
+#endif
+#ifdef B921600
+ DATA("921600", B921600),
+#endif
+#ifdef B1000000
+ DATA("1000000", B1000000),
+#endif
+#ifdef B1152000
+ DATA("1152000", B1152000),
+#endif
+#ifdef B1500000
+ DATA("1500000", B1500000),
+#endif
+#ifdef B2000000
+ DATA("2000000", B2000000),
+#endif
+#ifdef B2500000
+ DATA("2500000", B2500000),
+#endif
+#ifdef B3000000
+ DATA("3000000", B3000000),
+#endif
+#ifdef B3500000
+ DATA("3500000", B3500000),
+#endif
+#ifdef B4000000
+ DATA("4000000", B4000000),
#endif
- {(char *) 0, 0}
};
+#undef DATA
+#endif
static int
tbaudrate(char *rate)
{
- const SPEEDS *sp;
- int found = FALSE;
+ const SPEEDS *sp = 0;
+ size_t n;
/* The baudrate number can be preceded by a 'B', which is ignored. */
if (*rate == 'B')
++rate;
- for (sp = speeds; sp->string; ++sp) {
- if (!CaselessCmp(rate, sp->string)) {
- found = TRUE;
+ for (n = 0; n < SIZEOF(speeds); ++n) {
+ if (n > 0 && (speeds[n].speed <= speeds[n - 1].speed)) {
+ /* if the speeds are not increasing, likely a numeric overflow */
+ break;
+ }
+ if (!CaselessCmp(rate, speeds[n].string)) {
+ sp = speeds + n;
break;
}
}
- if (!found)
+ if (sp == 0)
err("unknown baud rate %s", rate);
return (sp->speed);
}
char *base = 0;
copy = strdup(arg);
- mapp = malloc(sizeof(MAP));
+ 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;
mapp->speed = tbaudrate(p);
}
- if (arg == (char *) 0) /* Non-optional type. */
- goto badmopt;
-
mapp->type = arg;
/* Terminate porttype, if specified. */
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);
+ 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);
match = TRUE;
break;
case EQ:
- match = (ospeed == mapp->speed);
+ match = ((int) ospeed == mapp->speed);
break;
case GE:
- match = (ospeed >= mapp->speed);
+ match = ((int) ospeed >= mapp->speed);
break;
case GT:
- match = (ospeed > mapp->speed);
+ match = ((int) ospeed > mapp->speed);
break;
case LE:
- match = (ospeed <= mapp->speed);
+ match = ((int) ospeed <= mapp->speed);
break;
case LT:
- match = (ospeed < mapp->speed);
+ match = ((int) ospeed < mapp->speed);
break;
default:
match = FALSE;
* its termcap entry.
*/
static const char *
-get_termcap_entry(char *userarg)
+get_termcap_entry(int fd, char *userarg)
{
- int rval, errret;
+ int errret;
char *p;
const char *ttype;
+#if HAVE_PATH_TTYS
#if HAVE_GETTTYNAM
struct ttyent *t;
#else
FILE *fp;
#endif
char *ttypath;
+#endif /* HAVE_PATH_TTYS */
+
+ (void) fd;
if (userarg) {
ttype = userarg;
if ((ttype = getenv("TERM")) != 0)
goto map;
- if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
+#if HAVE_PATH_TTYS
+ if ((ttypath = ttyname(fd)) != 0) {
p = _nc_basename(ttypath);
#if HAVE_GETTTYNAM
/*
while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) {
for (s = buffer, t = d = 0; *s; s++) {
- if (isspace(*s))
+ if (isspace(UChar(*s)))
*s = '\0';
else if (t == 0)
t = s;
}
#endif /* HAVE_GETTTYNAM */
}
+#endif /* HAVE_PATH_TTYS */
/* If still undefined, use "unknown". */
ttype = "unknown";
* 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 && *p != '/') {
+ 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)) {
+ if (!strncmp("TERMCAP=", environ[n], (size_t) 8)) {
while ((environ[n] = environ[n + 1]) != 0) {
n++;
}
ttype = askuser(0);
}
/* Find the terminfo entry. If it doesn't exist, ask the user. */
- while ((rval = setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO,
- &errret)) != OK) {
+ while (setupterm((NCURSES_CONST char *) ttype, fd, &errret)
+ != OK) {
if (errret == 0) {
- (void) fprintf(stderr, "tset: unknown terminal type %s\n",
- ttype);
+ (void) fprintf(stderr, "%s: unknown terminal type %s\n",
+ _nc_progname, ttype);
ttype = 0;
} else {
(void) fprintf(stderr,
- "tset: can't initialize terminal type %s (error %d)\n",
- ttype, errret);
+ "%s: can't initialize terminal type %s (error %d)\n",
+ _nc_progname, ttype, errret);
ttype = 0;
}
ttype = askuser(ttype);
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.
- */
-#undef CEOF
-#undef CERASE
-#undef CINTR
-#undef CKILL
-#undef CLNEXT
-#undef CRPRNT
-#undef CQUIT
-#undef CSTART
-#undef CSTOP
-#undef CSUSP
-
-/* control-character defaults */
-#define CEOF CTRL('D')
-#define CERASE CTRL('H')
-#define CINTR 127 /* ^? */
-#define CKILL CTRL('U')
-#define CLNEXT CTRL('v')
-#define CRPRNT CTRL('r')
-#define CQUIT CTRL('\\')
-#define CSTART CTRL('Q')
-#define CSTOP CTRL('S')
-#define CSUSP CTRL('Z')
-
-#define CHK(val, dft) ((int)val <= 0 ? dft : val)
-
-static bool set_tabs(void);
-
-/*
- * Reset the terminal mode bits to a sensible state. Very useful after
- * a child program dies in raw mode.
- */
-static void
-reset_mode(void)
-{
-#ifdef TERMIOS
- tcgetattr(STDERR_FILENO, &mode);
-#else
- stty(STDERR_FILENO, &mode);
-#endif
-
-#ifdef TERMIOS
-#if defined(VDISCARD) && defined(CDISCARD)
- mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
-#endif
- mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
- mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
-#if defined(VFLUSH) && defined(CFLUSH)
- mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
-#endif
- mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
- mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
-#if defined(VLNEXT) && defined(CLNEXT)
- mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
-#endif
- mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
-#if defined(VREPRINT) && defined(CRPRNT)
- mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
-#endif
-#if defined(VSTART) && defined(CSTART)
- mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
-#endif
-#if defined(VSTOP) && defined(CSTOP)
- mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
-#endif
-#if defined(VSUSP) && defined(CSUSP)
- mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
-#endif
-#if defined(VWERASE) && defined(CWERASE)
- mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
-#endif
-
- mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
-#ifdef IUCLC
- | IUCLC
-#endif
-#ifdef IXANY
- | IXANY
-#endif
- | IXOFF);
-
- mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
-#ifdef IMAXBEL
- | IMAXBEL
-#endif
- );
-
- mode.c_oflag &= ~(0
-#ifdef OLCUC
- | OLCUC
-#endif
-#ifdef OCRNL
- | OCRNL
-#endif
-#ifdef ONOCR
- | ONOCR
-#endif
-#ifdef ONLRET
- | ONLRET
-#endif
-#ifdef OFILL
- | OFILL
-#endif
-#ifdef OFDEL
- | OFDEL
-#endif
-#ifdef NLDLY
- | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY
-#endif
- );
-
- mode.c_oflag |= (OPOST
-#ifdef ONLCR
- | ONLCR
-#endif
- );
-
- mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
- mode.c_cflag |= (CS8 | CREAD);
- mode.c_lflag &= ~(ECHONL | NOFLSH
-#ifdef TOSTOP
- | TOSTOP
-#endif
-#ifdef ECHOPTR
- | ECHOPRT
-#endif
-#ifdef XCASE
- | XCASE
-#endif
- );
-
- mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
-#ifdef ECHOCTL
- | ECHOCTL
-#endif
-#ifdef ECHOKE
- | ECHOKE
-#endif
- );
-#endif
-
-#ifdef TERMIOS
- tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
-#else
- stty(STDERR_FILENO, &mode);
-#endif
-}
-
-/*
- * Returns a "good" value for the erase character. This is loosely based on
- * the BSD4.4 logic.
- */
-#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 (mode.c_cc[VERASE] == 0 || terasechar >= 0)
- mode.c_cc[VERASE] = terasechar >= 0 ? terasechar : default_erase();
-
- if (mode.c_cc[VINTR] == 0 || intrchar >= 0)
- mode.c_cc[VINTR] = intrchar >= 0 ? intrchar : CINTR;
-
- if (mode.c_cc[VKILL] == 0 || tkillchar >= 0)
- mode.c_cc[VKILL] = tkillchar >= 0 ? tkillchar : CKILL;
-#endif
-}
-
-/*
- * 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);
- tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode);
- }
-#endif
- settle = set_tabs();
-
- if (isreset) {
- if ((p = reset_1string) != 0) {
- tputs(p, 0, outc);
- settle = TRUE;
- }
- if ((p = reset_2string) != 0) {
- tputs(p, 0, outc);
- settle = TRUE;
- }
- /* What about rf, rs3, as per terminfo man page? */
- /* also might be nice to send rmacs, rmul, rmm */
- if ((p = reset_file) != 0
- || (p = init_file) != 0) {
- cat(p);
- settle = TRUE;
- }
- }
-
- if (settle) {
- (void) putc('\r', stderr);
- (void) fflush(stderr);
- (void) napms(1000); /* Settle the terminal. */
- }
-}
-
-/*
- * 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()
-{
- if (set_tab && clear_all_tabs) {
- int c;
-
- (void) putc('\r', stderr); /* Force to left margin. */
- tputs(clear_all_tabs, 0, outc);
-
- for (c = 8; c < tcolumns; c += 8) {
- /* Get to the right column. In BSD tset, this
- * used to try a bunch of half-clever things
- * with cup and hpa, for an average saving of
- * somewhat less than two character times per
- * tab stop, less that .01 sec at 2400cps. We
- * lost all this cruft because it seemed to be
- * introducing some odd bugs.
- * ----------12345678----------- */
- (void) fputs(" ", stderr);
- tputs(set_tab, 0, outc);
- }
- putc('\r', stderr);
- return (TRUE);
- }
- return (FALSE);
-}
-
/**************************************************************************
*
* 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");
-
- /*
- * 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 == (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", newer, newer);
- } else
- (void) fprintf(stderr, "%c.\n", 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
-usage(const char *pname)
+print_shell_commands(const char *ttype)
{
- (void) fprintf(stderr,
- "usage: %s [-IQVrs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n", pname);
- exit(EXIT_FAILURE);
+ const char *p;
+ int len;
+ char *var;
+ char *leaf;
+ /*
+ * Figure out what shell we're using. A hack, we look for an
+ * environmental variable SHELL ending in "csh".
+ */
+ if ((var = getenv("SHELL")) != 0
+ && ((len = (int) strlen(leaf = _nc_basename(var))) >= 3)
+ && !strcmp(leaf + len - 3, "csh"))
+ p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
+ else
+ p = "TERM=%s;\n";
+ (void) printf(p, ttype);
+}
+
+static void
+usage(void)
+{
+#define SKIP(s) /* nothing */
+#define KEEP(s) s "\n"
+ static const char msg[] =
+ {
+ KEEP("")
+ KEEP("Options:")
+ SKIP(" -a arpanet (obsolete)")
+ KEEP(" -c set control characters")
+ SKIP(" -d dialup (obsolete)")
+ KEEP(" -e ch erase character")
+ KEEP(" -I no initialization strings")
+ KEEP(" -i ch interrupt character")
+ KEEP(" -k ch kill character")
+ KEEP(" -m mapping map identifier to type")
+ SKIP(" -p plugboard (obsolete)")
+ KEEP(" -Q do not output control key settings")
+ KEEP(" -q display term only, do no changes")
+ KEEP(" -r display term on stderr")
+ SKIP(" -S (obsolete)")
+ KEEP(" -s output TERM set command")
+ KEEP(" -V print curses-version")
+ KEEP(" -w set window-size")
+ KEEP("")
+ KEEP("If neither -c/-w are given, both are assumed.")
+ };
+#undef KEEP
+#undef SKIP
+ (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
+ fputs(msg, stderr);
+ ExitProgram(EXIT_FAILURE);
+ /* NOTREACHED */
}
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;
-
- if (GET_TTY(STDERR_FILENO, &mode) < 0)
- failed("standard error");
- oldmode = mode;
-#ifdef TERMIOS
- ospeed = cfgetospeed(&mode);
-#else
- ospeed = mode.sg_ospeed;
-#endif
-
- p = _nc_basename(*argv);
- if (!strcmp(p, PROG_RESET)) {
- isreset = TRUE;
- reset_mode();
- }
-
+ int terasechar = -1; /* new erase character */
+ int intrchar = -1; /* new interrupt character */
+ int tkillchar = -1; /* new kill character */
+ int my_fd;
+ bool opt_c = FALSE; /* set control-chars */
+ bool opt_w = FALSE; /* set window-size */
+ TTY mode, oldmode;
+
+ _nc_progname = _nc_rootname(*argv);
obsolete(argv);
noinit = noset = quiet = Sflag = sflag = showterm = 0;
- while ((ch = getopt(argc, argv, "a:d:e:Ii:k:m:np:qQSrsV")) != EOF) {
+ while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:p:qQrSsVw")) != -1) {
switch (ch) {
- case 'q': /* display term only */
- noset = 1;
+ case 'c': /* set control-chars */
+ opt_c = TRUE;
break;
case 'a': /* OBSOLETE: map identifier to type */
add_mapping("arpanet", optarg);
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;
+ 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':
+ case 'V': /* print curses-version */
puts(curses_version());
- return EXIT_SUCCESS;
+ ExitProgram(EXIT_SUCCESS);
+ case 'w': /* set window-size */
+ opt_w = TRUE;
+ break;
case '?':
default:
- usage(*argv);
+ usage();
}
}
+
argc -= optind;
argv += optind;
if (argc > 1)
- usage(*argv);
+ usage();
- ttype = get_termcap_entry(*argv);
+ if (!opt_c && !opt_w)
+ opt_c = opt_w = TRUE;
+
+ my_fd = save_tty_settings(&mode, TRUE);
+ oldmode = mode;
+#ifdef TERMIOS
+ ospeed = (NCURSES_OSPEED) cfgetospeed(&mode);
+#elif defined(EXP_WIN32_DRIVER)
+ ospeed = 0;
+#else
+ ospeed = (NCURSES_OSPEED) mode.sg_ospeed;
+#endif
+
+ if (same_program(_nc_progname, PROG_RESET)) {
+ reset_start(stderr, TRUE, FALSE);
+ reset_tty_settings(my_fd, &mode, noset);
+ } else {
+ reset_start(stderr, FALSE, TRUE);
+ }
+
+ ttype = get_termcap_entry(my_fd, *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);
+#if HAVE_SIZECHANGE
+ if (opt_w) {
+ set_window_size(my_fd, &lines, &columns);
}
#endif
- set_control_chars();
- set_conversions();
+ if (opt_c) {
+ set_control_chars(&mode, terasechar, intrchar, tkillchar);
+ set_conversions(&mode);
- if (!noinit)
- set_init();
+ if (!noinit) {
+ if (send_init_strings(my_fd, &oldmode)) {
+ (void) putc('\r', stderr);
+ (void) fflush(stderr);
+ (void) napms(1000); /* Settle the terminal. */
+ }
+ }
- /* Set the modes if they've changed. */
- if (memcmp(&mode, &oldmode, sizeof(mode))) {
-#ifdef TERMIOS
- tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
-#else
- stty(STDERR_FILENO, &mode);
-#endif
+ update_tty_settings(&oldmode, &mode);
}
}
- /* Get the terminal name from the entry. */
- ttype = _nc_first_name(cur_term->type.term_names);
-
- if (noset)
+ if (noset) {
(void) printf("%s\n", ttype);
- else {
+ } 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, CINTR);
- report("Interrupt", VINTR, CKILL);
+ print_tty_chars(&oldmode, &mode);
}
-#endif
}
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);
+ print_shell_commands(ttype);
}
- return EXIT_SUCCESS;
+ ExitProgram(EXIT_SUCCESS);
}
-
-/* tset.c ends here */