X-Git-Url: https://ncurses.scripts.mit.edu/?a=blobdiff_plain;f=progs%2Ftset.c;h=8417effc039e2ef724731cef849f9669c61f6ce8;hb=aa70bf3c762c5b6407bf34812d63c20f7ac8ffdd;hp=3d6091224979776fd8d5c415d51464cad0718035;hpb=491a3f08b795f494ae17179338c31a11b18fd433;p=ncurses.git diff --git a/progs/tset.c b/progs/tset.c index 3d609122..8417effc 100644 --- a/progs/tset.c +++ b/progs/tset.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright (c) 1998-2015,2016 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 * @@ -32,6 +32,22 @@ * 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 * @@ -52,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. * @@ -89,9 +101,12 @@ 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 NEED_PTEM_H @@ -104,15 +119,42 @@ char *ttyname(int fd); #include #include -MODULE_ID("$Id: tset.c,v 1.70 2007/10/13 22:22:04 tom Exp $") +MODULE_ID("$Id: tset.c,v 1.100 2016/07/30 21:32:26 tom Exp $") + +/* + * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, + * Solaris, IRIX) define TIOCGWINSZ and struct winsize. + */ +#ifdef TIOCGSIZE +# define IOCTL_GET_WINSIZE TIOCGSIZE +# define IOCTL_SET_WINSIZE TIOCSSIZE +# define STRUCT_WINSIZE struct ttysize +# define WINSIZE_ROWS(n) n.ts_lines +# define WINSIZE_COLS(n) n.ts_cols +#else +# ifdef TIOCGWINSZ +# define IOCTL_GET_WINSIZE TIOCGWINSZ +# define IOCTL_SET_WINSIZE TIOCSWINSZ +# define STRUCT_WINSIZE struct winsize +# define WINSIZE_ROWS(n) n.ws_row +# define WINSIZE_COLS(n) n.ws_col +# endif +#endif +#ifndef environ extern char **environ; +#endif #undef CTRL #define CTRL(x) ((x) & 0x1f) +static void failed(const char *) GCC_NORETURN; +static void exit_error(void) GCC_NORETURN; +static void err(const char *,...) GCC_NORETURN; + const char *_nc_progname = "tset"; +static int my_fd; static TTY mode, oldmode, original; static bool opt_c; /* set control-chars */ @@ -123,7 +165,10 @@ 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 */ + +#if HAVE_SIZECHANGE static int tlines, tcolumns; /* window size */ +#endif #define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c)) @@ -143,7 +188,7 @@ static void exit_error(void) { if (can_restore) - SET_TTY(STDERR_FILENO, &original); + SET_TTY(my_fd, &original); (void) fprintf(stderr, "\n"); fflush(stderr); ExitProgram(EXIT_FAILURE); @@ -166,19 +211,30 @@ static void failed(const char *msg) { char temp[BUFSIZ]; - unsigned len = strlen(_nc_progname) + 2; + size_t len = strlen(_nc_progname) + 2; - if (len < sizeof(temp) - 12) { - strcpy(temp, _nc_progname); - strcat(temp, ": "); + if ((int) len < (int) sizeof(temp) - 12) { + _nc_STRCPY(temp, _nc_progname, sizeof(temp)); + _nc_STRCAT(temp, ": ", sizeof(temp)); } else { - strcpy(temp, "tset: "); + _nc_STRCPY(temp, "tset: ", sizeof(temp)); } perror(strncat(temp, msg, sizeof(temp) - strlen(temp) - 2)); exit_error(); /* NOTREACHED */ } +static bool +get_mode(int fd) +{ + bool success = TRUE; + my_fd = fd; + if (GET_TTY(my_fd, &mode) < 0) { + success = FALSE; + } + return success; +} + static void cat(char *file) { @@ -263,87 +319,89 @@ typedef struct map { static MAP *cur, *maplist; +#define DATA(name,value) { { name }, value } + typedef struct speeds { - const char *string; + const char string[7]; int speed; } SPEEDS; static const SPEEDS speeds[] = { - {"0", B0}, - {"50", B50}, - {"75", B75}, - {"110", B110}, - {"134", B134}, - {"134.5", B134}, - {"150", B150}, - {"200", B200}, - {"300", B300}, - {"600", B600}, - {"1200", B1200}, - {"1800", B1800}, - {"2400", B2400}, - {"4800", B4800}, - {"9600", B9600}, + 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 B115200 - {"115200", B115200}, + DATA("115200", B115200), #endif #ifdef B230400 - {"230400", B230400}, + DATA("230400", B230400), #endif #ifdef B460800 - {"460800", B460800}, + DATA("460800", B460800), #endif - {(char *) 0, 0} }; +#undef DATA static int tbaudrate(char *rate) { - const SPEEDS *sp; - int found = FALSE; + const SPEEDS *sp = 0; + size_t n; /* The baudrate number can be preceded by a 'B', which is ignored. */ if (*rate == 'B') ++rate; - for (sp = speeds; sp->string; ++sp) { - if (!CaselessCmp(rate, sp->string)) { - found = TRUE; + for (n = 0; n < SIZEOF(speeds); ++n) { + if (!CaselessCmp(rate, speeds[n].string)) { + sp = speeds + n; break; } } - if (!found) + if (sp == 0) err("unknown baud rate %s", rate); return (sp->speed); } @@ -362,9 +420,13 @@ add_mapping(const char *port, char *arg) char *base = 0; copy = strdup(arg); - mapp = (MAP *) 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; @@ -426,9 +488,6 @@ add_mapping(const char *port, char *arg) mapp->speed = tbaudrate(p); } - if (arg == (char *) 0) /* Non-optional type. */ - goto badmopt; - mapp->type = arg; /* Terminate porttype, if specified. */ @@ -440,11 +499,15 @@ add_mapping(const char *port, char *arg) 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); @@ -482,19 +545,19 @@ mapped(const char *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; @@ -538,7 +601,7 @@ get_termcap_entry(char *userarg) if ((ttype = getenv("TERM")) != 0) goto map; - if ((ttypath = ttyname(STDERR_FILENO)) != 0) { + if ((ttypath = ttyname(my_fd)) != 0) { p = _nc_basename(ttypath); #if HAVE_GETTTYNAM /* @@ -586,13 +649,14 @@ get_termcap_entry(char *userarg) * 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)) { + 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++; } @@ -695,7 +759,7 @@ get_termcap_entry(char *userarg) #define DISABLED(val) ((int)(val) <= 0) #endif -#define CHK(val, dft) (DISABLED(val) ? dft : val) +#define CHK(val, dft) (unsigned char) (DISABLED(val) ? dft : val) static bool set_tabs(void); @@ -707,9 +771,9 @@ static void reset_mode(void) { #ifdef TERMIOS - tcgetattr(STDERR_FILENO, &mode); + tcgetattr(my_fd, &mode); #else - stty(STDERR_FILENO, &mode); + stty(my_fd, &mode); #endif #ifdef TERMIOS @@ -743,14 +807,14 @@ reset_mode(void) mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); #endif - mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR + mode.c_iflag &= ~((unsigned) (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 #ifdef IMAXBEL @@ -758,44 +822,44 @@ reset_mode(void) #endif ); - mode.c_oflag &= ~(0 + mode.c_oflag &= ~((unsigned) (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 + | NLDLY #endif -#ifdef CRDLY - | CRDLY +#ifdef CRDLY + | CRDLY #endif -#ifdef TABDLY - | TABDLY +#ifdef TABDLY + | TABDLY #endif -#ifdef BSDLY - | BSDLY +#ifdef BSDLY + | BSDLY #endif -#ifdef VTDLY - | VTDLY +#ifdef VTDLY + | VTDLY #endif #ifdef FFDLY - | FFDLY + | FFDLY #endif - ); + )); mode.c_oflag |= (OPOST #ifdef ONLCR @@ -803,19 +867,19 @@ reset_mode(void) #endif ); - mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); + mode.c_cflag &= ~((unsigned) (CSIZE | CSTOPB | PARENB | PARODD | CLOCAL)); mode.c_cflag |= (CS8 | CREAD); - mode.c_lflag &= ~(ECHONL | NOFLSH + mode.c_lflag &= ~((unsigned) (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 #ifdef ECHOCTL @@ -827,7 +891,7 @@ reset_mode(void) ); #endif - SET_TTY(STDERR_FILENO, &mode); + SET_TTY(my_fd, &mode); } /* @@ -862,14 +926,23 @@ 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[VERASE]) || terasechar >= 0) { + mode.c_cc[VERASE] = UChar((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[VINTR]) || intrchar >= 0) { + mode.c_cc[VINTR] = UChar((intrchar >= 0) + ? intrchar + : CINTR); + } - if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) - mode.c_cc[VKILL] = tkillchar >= 0 ? tkillchar : CKILL; + if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) { + mode.c_cc[VKILL] = UChar((tkillchar >= 0) + ? tkillchar + : CKILL); + } #endif } @@ -925,9 +998,9 @@ set_conversions(void) if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) { /* Newline, not linefeed. */ #ifdef ONLCR - mode.c_oflag &= ~ONLCR; + mode.c_oflag &= ~((unsigned) ONLCR); #endif - mode.c_iflag &= ~ICRNL; + mode.c_iflag &= ~((unsigned) ICRNL); } #ifdef __OBSOLETE__ if (tgetflag("HD")) /* Half duplex. */ @@ -957,7 +1030,7 @@ set_init(void) #ifdef TAB3 if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); - SET_TTY(STDERR_FILENO, &oldmode); + SET_TTY(my_fd, &oldmode); } #endif settle = set_tabs(); @@ -998,11 +1071,18 @@ set_tabs(void) { if (set_tab && clear_all_tabs) { int c; + int lim = +#if HAVE_SIZECHANGE + tcolumns +#else + columns +#endif + ; (void) putc('\r', stderr); /* Force to left margin. */ tputs(clear_all_tabs, 0, outc); - for (c = 8; c < tcolumns; c += 8) { + for (c = 8; c < lim; 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 @@ -1101,26 +1181,26 @@ obsolete(char **argv) static void usage(void) { - static const char *tbl[] = +#define DATA(s) s "\n" + static const char msg[] = { - "" - ,"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" + DATA("") + DATA("Options:") + DATA(" -c set control characters") + DATA(" -e ch erase character") + DATA(" -I no initialization strings") + DATA(" -i ch interrupt character") + DATA(" -k ch kill character") + DATA(" -m mapping map identifier to type") + DATA(" -Q do not output control key settings") + DATA(" -r display term on stderr") + DATA(" -s output TERM set command") + DATA(" -V print curses-version") + DATA(" -w set window-size") }; - unsigned n; +#undef DATA (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]); + fputs(msg, stderr); exit_error(); /* NOTREACHED */ } @@ -1128,24 +1208,22 @@ usage(void) static char arg_to_char(void) { - return (optarg[0] == '^' && optarg[1] != '\0') - ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1])) - : optarg[0]; + return (char) ((optarg[0] == '^' && optarg[1] != '\0') + ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1])) + : optarg[0]); } int main(int argc, char **argv) { -#if defined(TIOCGWINSZ) && defined(TIOCSWINSZ) - struct winsize win; -#endif int ch, noinit, noset, quiet, Sflag, sflag, showterm; const char *p; const char *ttype; + my_fd = STDERR_FILENO; obsolete(argv); noinit = noset = quiet = Sflag = sflag = showterm = 0; - while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:np:qQSrsVw")) != -1) { + while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:p:qQSrsVw")) != -1) { switch (ch) { case 'c': /* set control-chars */ opt_c = TRUE; @@ -1171,8 +1249,6 @@ main(int argc, char **argv) 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; @@ -1213,17 +1289,24 @@ main(int argc, char **argv) if (!opt_c && !opt_w) opt_c = opt_w = TRUE; - if (GET_TTY(STDERR_FILENO, &mode) < 0) - failed("standard error"); + /* + * stderr is less likely to be redirected than stdout; try that first. + */ + if (!get_mode(STDERR_FILENO) && + !get_mode(STDOUT_FILENO) && + !get_mode(STDIN_FILENO) && + !get_mode(open("/dev/tty", O_RDWR))) { + failed("terminal attributes"); + } can_restore = TRUE; original = oldmode = mode; #ifdef TERMIOS - ospeed = cfgetospeed(&mode); + ospeed = (NCURSES_OSPEED) cfgetospeed(&mode); #else - ospeed = mode.sg_ospeed; + ospeed = (NCURSES_OSPEED) mode.sg_ospeed; #endif - if (!strcmp(_nc_progname, PROG_RESET)) { + if (same_program(_nc_progname, PROG_RESET)) { isreset = TRUE; reset_mode(); } @@ -1231,18 +1314,20 @@ main(int argc, char **argv) ttype = get_termcap_entry(*argv); if (!noset) { +#if HAVE_SIZECHANGE tcolumns = columns; tlines = lines; -#if defined(TIOCGWINSZ) && defined(TIOCSWINSZ) if (opt_w) { - /* Set window size */ - (void) ioctl(STDERR_FILENO, TIOCGWINSZ, &win); - if (win.ws_row == 0 && win.ws_col == 0 && + STRUCT_WINSIZE win; + /* Set window size if not set already */ + (void) ioctl(my_fd, IOCTL_GET_WINSIZE, &win); + if (WINSIZE_ROWS(win) == 0 && + WINSIZE_COLS(win) == 0 && tlines > 0 && tcolumns > 0) { - win.ws_row = tlines; - win.ws_col = tcolumns; - (void) ioctl(STDERR_FILENO, TIOCSWINSZ, &win); + WINSIZE_ROWS(win) = (unsigned short) tlines; + WINSIZE_COLS(win) = (unsigned short) tcolumns; + (void) ioctl(my_fd, IOCTL_SET_WINSIZE, &win); } } #endif @@ -1255,14 +1340,11 @@ main(int argc, char **argv) /* Set the modes if they've changed. */ if (memcmp(&mode, &oldmode, sizeof(mode))) { - SET_TTY(STDERR_FILENO, &mode); + SET_TTY(my_fd, &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 { @@ -1293,7 +1375,7 @@ main(int argc, char **argv) * environmental variable SHELL ending in "csh". */ if ((var = getenv("SHELL")) != 0 - && ((len = strlen(leaf = _nc_basename(var))) >= 3) + && ((len = (int) strlen(leaf = _nc_basename(var))) >= 3) && !strcmp(leaf + len - 3, "csh")) p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n"; else