X-Git-Url: http://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=progs%2Ftset.c;h=084e41d6db249c6812efe8d71eca30b0dbab9ccd;hp=e6a075d9b6f83bba47f1480015685059f915618a;hb=70322aa06a4a97ebff76d2869ad923cdf51ee0a9;hpb=3a9b6a3bf0269231bef7de74757a910dedd04e0c diff --git a/progs/tset.c b/progs/tset.c index e6a075d9..084e41d6 100644 --- a/progs/tset.c +++ b/progs/tset.c @@ -1,24 +1,52 @@ +/**************************************************************************** + * Copyright (c) 1998-2009,2010 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 1992,1995 * + * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + ****************************************************************************/ -/*************************************************************************** -* COPYRIGHT NOTICE * -**************************************************************************** -* ncurses is copyright (C) 1992-1995 * -* Zeyd M. Ben-Halim * -* zmbenhal@netcom.com * -* Eric S. Raymond * -* esr@snark.thyrsus.com * -* * -* Permission is hereby granted to reproduce and distribute ncurses * -* by any means and for any fee, whether alone or as part of a * -* larger distribution, in source or in binary form, PROVIDED * -* this notice is included with any such distribution, and is not * -* removed from any of its header files. Mention of ncurses in any * -* applications linked with it is highly appreciated. * -* * -* ncurses comes AS IS with no warranty, implied or expressed. * -* * -***************************************************************************/ - +/* + * 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 @@ -40,11 +68,7 @@ * 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. * @@ -61,12 +85,12 @@ * SUCH DAMAGE. */ +#define USE_LIBTINFO #define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */ #include #include #include -#include #include #include @@ -77,143 +101,179 @@ char *ttyname(int fd); #endif -/* this is just to stifle a missing-prototype warning */ -#ifdef linux -# include +#if HAVE_SIZECHANGE +# if !defined(sun) || !TERMIOS +# if HAVE_SYS_IOCTL_H +# include +# endif +# endif #endif -#if SYSTEM_LOOKS_LIKE_SCO +#if NEED_PTEM_H /* they neglected to define struct winsize in termios.h -- it's only in termio.h */ -#include -#include +#include +#include #endif -#include /* for bool typedef */ #include +#include -MODULE_ID("$Id: tset.c,v 0.23 1997/05/10 17:44:47 tom Exp $") +MODULE_ID("$Id: tset.c,v 1.82 2010/05/01 21:42:46 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) const char *_nc_progname = "tset"; -static TTY mode, oldmode; +static TTY mode, oldmode, original; -static int terasechar; /* new erase character */ -static int intrchar; /* new interrupt character */ -static int isreset; /* invoked as reset */ -static int tkillchar; /* new kill character */ -static int tlines, tcolumns; /* window size */ +static bool opt_c; /* set control-chars */ +static bool opt_w; /* set window-size */ -#define LOWERCASE(c) ((isalpha(c) && isupper(c)) ? tolower(c) : (c)) +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); +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]; + 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) { - register int fd, nr, nw; - char buf[1024]; - - 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); + } } /************************************************************************** @@ -231,62 +291,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 }, - { (char *)0, 0 } +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; + 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); } /* @@ -297,110 +393,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 } @@ -412,38 +517,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); } /************************************************************************** @@ -459,94 +564,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; - char *ttypath; + struct ttyent *t; +#else + FILE *fp; #endif + 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) { + 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 ((ttypath = ttyname(STDERR_FILENO)) != 0) { - if ((p = strrchr(ttypath, '/')) != 0) - ++p; - else - p = ttypath; - if ((t = getttynam(p))) { - ttype = t->ty_type; - goto map; - } + if ((t = getttynam(p))) { + ttype = t->ty_type; + goto map; } -#endif /* BSD */ - - /* 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 && *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; - } +#else + if ((fp = fopen("/etc/ttytype", "r")) != 0 + || (fp = fopen("/etc/ttys", "r")) != 0) { + char buffer[BUFSIZ]; + char *s, *t, *d; + + while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) { + for (s = buffer, t = d = 0; *s; s++) { + if (isspace(UChar(*s))) + *s = '\0'; + else if (t == 0) + t = s; + else if (d == 0 && s != buffer && s[-1] == '\0') + d = s; } + if (t != 0 && d != 0 && !strcmp(d, p)) { + ttype = strdup(t); + fclose(fp); + goto map; + } + } + fclose(fp); } - - /* - * ttype now contains a pointer to the type of the terminal. - * If the first character is '?', ask the user. +#endif /* HAVE_GETTTYNAM */ + } + + /* If still undefined, use "unknown". */ + ttype = "unknown"; + + map:ttype = mapped(ttype); + + /* + * If not a path, remove TERMCAP from the environment so we get a + * real entry from /etc/termcap. This prevents us from being fooled + * by out of date stuff in the environment. + */ + found:if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) { + /* 'unsetenv("TERMCAP")' is not portable. + * The 'environ' array is better. */ - if (ttype[0] == '?') - if (ttype[1] != '\0') - ttype = askuser(ttype + 1); - else - ttype = askuser(0); - - /* Find the terminfo entry. If it doesn't exist, ask the user. */ - while ((rval = setupterm(ttype, STDOUT_FILENO, &errret)) != OK) { - if (errret == 0) { - (void)fprintf(stderr, "tset: unknown terminal type %s\n", - ttype); - ttype = 0; + int n; + for (n = 0; environ[n] != 0; n++) { + if (!strncmp("TERMCAP=", environ[n], 8)) { + while ((environ[n] = environ[n + 1]) != 0) { + n++; } - else { - (void)fprintf(stderr, "tset: can't initialize terminal\ - type %s (error %d)\n", ttype, errret); - ttype = 0; - } - ttype = askuser(ttype); + break; + } + } + } + + /* + * ttype now contains a pointer to the type of the terminal. + * If the first character is '?', ask the user. + */ + if (ttype[0] == '?') { + if (ttype[1] != '\0') + ttype = askuser(ttype + 1); + else + ttype = askuser(0); + } + /* Find the terminfo entry. If it doesn't exist, ask the user. */ + while (setupterm((NCURSES_CONST char *) ttype, 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); } /************************************************************************** @@ -556,38 +684,65 @@ 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 #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') -#if defined(CLNEXT) -#undef CLNEXT +#endif +#ifndef CLNEXT #define CLNEXT CTRL('v') #endif -#if defined(CRPRNT) -#undef CRPRNT +#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) ((int)val <= 0 ? dft : val) +#define CHK(val, dft) (DISABLED(val) ? dft : val) -static bool set_tabs (void); +static bool set_tabs(void); /* * Reset the terminal mode bits to a sensible state. Very useful after @@ -597,172 +752,169 @@ 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); } /* - * Determine the erase, interrupt, and kill characters from the termcap - * entry and command line and update their values in 'mode'. + * Returns a "good" value for the erase character. This is loosely based on + * the BSD4.4 logic. */ -static void -set_control_chars(void) +#ifdef TERMIOS +static int +default_erase(void) { -#ifdef __OBSOLETE__ - /* - * 4.4BSD logic for setting erasechar, left here in case there is some - * necessary subtlety missed in the production code below that really - * needs to be added someday (in particular, I don't understand what - * the second if-statement involving the os flag is doing, and it makes - * my head hurt when I try and follow out all the combinations). - */ - char *bp, *p, bs_char, buf[1024]; - - bp = buf; - p = tgetstr("kb", &bp); - if (p == 0 || p[1] != '\0') - p = tgetstr("bc", &bp); - if (p != 0 && p[1] == '\0') - bs_char = p[0]; - else if (tgetflag("bs")) - bs_char = CTRL('h'); - else - bs_char = 0; + int result; - if (terasechar==0 && !tgetflag("os") && mode.c_cc[VERASE] != CERASE) { - if (tgetflag("bs") || bs_char != 0) - terasechar = -1; - } - if (terasechar < 0) - terasechar = (bs_char != 0) ? bs_char : CTRL('h'); -#else - /* the real erasechar logic used now */ - char bs_char = 0; - - if (key_backspace != (char *)0) - bs_char = key_backspace[0]; + if (over_strike + && key_backspace != 0 + && strlen(key_backspace) == 1) + result = key_backspace[0]; + else + result = CERASE; - if (terasechar <= 0) - terasechar = (bs_char != 0) ? bs_char : CTRL('h'); -#endif /* __OBSOLETE__ */ + 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 ? terasechar : CERASE; + 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 ? 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 ? tkillchar : CKILL; + if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) + mode.c_cc[VKILL] = (tkillchar >= 0) ? tkillchar : CKILL; #endif } @@ -776,62 +928,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 } @@ -839,45 +991,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)sleep(1); /* 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. */ + } } /* @@ -887,30 +1039,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); } /************************************************************************** @@ -922,34 +1074,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 old, new; - char *p; - - new = mode.c_cc[which]; - old = oldmode.c_cc[which]; - - if (old == new && old == def) - return; - - (void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to"); - - if ((p = key_backspace) != 0 - && new == (u_int)p[0] - && p[1] == '\0') - (void)fprintf(stderr, "backspace.\n"); - else if (new == 0177) - (void)fprintf(stderr, "delete.\n"); - else if (new < 040) { - new ^= 0100; - (void)fprintf(stderr, "control-%c (^%c).\n", new, new); - } else - (void)fprintf(stderr, "%c.\n", new); -#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. @@ -958,204 +1116,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) +{ + return (char) ((optarg[0] == '^' && optarg[1] != '\0') + ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1])) + : optarg[0]); } int main(int argc, char **argv) { -#ifdef TIOCGWINSZ - 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(); - oldmode = mode; - ospeed = mode.sg_ospeed; + 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 ((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 = optarg[0] == '^' && optarg[1] != '\0' ? - optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : - optarg[0]; - break; - case 'I': /* no initialization strings */ - noinit = 1; - break; - case 'i': /* interrupt character */ - intrchar = optarg[0] == '^' && optarg[1] != '\0' ? - optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : - optarg[0]; - break; - case 'k': /* kill character */ - tkillchar = optarg[0] == '^' && optarg[1] != '\0' ? - optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : - optarg[0]; - 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; - -#ifdef TIOCGWINSZ - /* 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 */