1 /****************************************************************************
2 * Copyright (c) 1998-2013,2015 Free Software Foundation, Inc. *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
27 ****************************************************************************/
29 /****************************************************************************
30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
31 * and: Eric S. Raymond <esr@snark.thyrsus.com> *
32 * and: Thomas E. Dickey 1996-on *
33 ****************************************************************************/
37 * The initial adaptation from 4.4BSD Lite sources in September 1995 used 686
38 * lines from that version, and made changes/additions for 150 lines. There
39 * was no reformatting, so with/without ignoring whitespace, the amount of
42 * Comparing with current (2009) source, excluding this comment:
43 * a) 209 lines match identically to the 4.4BSD Lite sources, with 771 lines
45 * a) Ignoring whitespace, the current version still uses 516 lines from the
46 * 4.4BSD Lite sources, with 402 lines changed/added.
48 * Raymond's original comment on this follows...
52 * tset.c - terminal initialization utility
54 * This code was mostly swiped from 4.4BSD tset, with some obsolescent
55 * cruft removed and substantial portions rewritten. A Regents of the
56 * University of California copyright applies to some portions of the
57 * code, and is reproduced below:
60 * Copyright (c) 1980, 1991, 1993
61 * The Regents of the University of California. All rights reserved.
63 * Redistribution and use in source and binary forms, with or without
64 * modification, are permitted provided that the following conditions
66 * 1. Redistributions of source code must retain the above copyright
67 * notice, this list of conditions and the following disclaimer.
68 * 2. Redistributions in binary form must reproduce the above copyright
69 * notice, this list of conditions and the following disclaimer in the
70 * documentation and/or other materials provided with the distribution.
71 * 3. Neither the name of the University nor the names of its contributors
72 * may be used to endorse or promote products derived from this software
73 * without specific prior written permission.
75 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
76 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
77 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
78 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
79 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
80 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
81 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
82 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
83 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
84 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
89 #define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */
90 #include <progs.priv.h>
97 #if HAVE_GETTTYNAM && HAVE_TTYENT_H
101 char *ttyname(int fd);
105 # if !defined(sun) || !TERMIOS
106 # if HAVE_SYS_IOCTL_H
107 # include <sys/ioctl.h>
113 /* they neglected to define struct winsize in termios.h -- it's only
115 #include <sys/stream.h>
116 #include <sys/ptem.h>
119 #include <dump_entry.h>
120 #include <transform.h>
122 MODULE_ID("$Id: tset.c,v 1.97 2015/11/08 01:45:47 tom Exp $")
125 * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS,
126 * Solaris, IRIX) define TIOCGWINSZ and struct winsize.
129 # define IOCTL_GET_WINSIZE TIOCGSIZE
130 # define IOCTL_SET_WINSIZE TIOCSSIZE
131 # define STRUCT_WINSIZE struct ttysize
132 # define WINSIZE_ROWS(n) n.ts_lines
133 # define WINSIZE_COLS(n) n.ts_cols
136 # define IOCTL_GET_WINSIZE TIOCGWINSZ
137 # define IOCTL_SET_WINSIZE TIOCSWINSZ
138 # define STRUCT_WINSIZE struct winsize
139 # define WINSIZE_ROWS(n) n.ws_row
140 # define WINSIZE_COLS(n) n.ws_col
145 extern char **environ;
149 #define CTRL(x) ((x) & 0x1f)
151 static void failed(const char *) GCC_NORETURN;
152 static void exit_error(void) GCC_NORETURN;
153 static void err(const char *,...) GCC_NORETURN;
155 const char *_nc_progname = "tset";
157 static TTY mode, oldmode, original;
159 static bool opt_c; /* set control-chars */
160 static bool opt_w; /* set window-size */
162 static bool can_restore = FALSE;
163 static bool isreset = FALSE; /* invoked as reset */
164 static int terasechar = -1; /* new erase character */
165 static int intrchar = -1; /* new interrupt character */
166 static int tkillchar = -1; /* new kill character */
169 static int tlines, tcolumns; /* window size */
172 #define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
175 CaselessCmp(const char *a, const char *b)
176 { /* strcasecmp isn't portable */
178 int cmp = LOWERCASE(*a) - LOWERCASE(*b);
183 return LOWERCASE(*a) - LOWERCASE(*b);
190 SET_TTY(STDERR_FILENO, &original);
191 (void) fprintf(stderr, "\n");
193 ExitProgram(EXIT_FAILURE);
198 err(const char *fmt,...)
202 (void) fprintf(stderr, "%s: ", _nc_progname);
203 (void) vfprintf(stderr, fmt, ap);
210 failed(const char *msg)
213 size_t len = strlen(_nc_progname) + 2;
215 if ((int) len < (int) sizeof(temp) - 12) {
216 _nc_STRCPY(temp, _nc_progname, sizeof(temp));
217 _nc_STRCAT(temp, ": ", sizeof(temp));
219 _nc_STRCPY(temp, "tset: ", sizeof(temp));
221 perror(strncat(temp, msg, sizeof(temp) - strlen(temp) - 2));
233 if ((fp = fopen(file, "r")) == 0)
236 while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0)
237 if (fwrite(buf, sizeof(char), nr, stderr) != nr)
238 failed("write to stderr");
245 return putc(c, stderr);
248 /* Prompt the user for a terminal type. */
250 askuser(const char *dflt)
252 static char answer[256];
255 /* We can get recalled; if so, don't continue uselessly. */
257 if (feof(stdin) || ferror(stdin)) {
258 (void) fprintf(stderr, "\n");
264 (void) fprintf(stderr, "Terminal type? [%s] ", dflt);
266 (void) fprintf(stderr, "Terminal type? ");
267 (void) fflush(stderr);
269 if (fgets(answer, sizeof(answer), stdin) == 0) {
277 if ((p = strchr(answer, '\n')) != 0)
286 /**************************************************************************
288 * Mapping logic begins here
290 **************************************************************************/
292 /* Baud rate conditionals for mapping. */
301 struct map *next; /* Linked list of maps. */
302 const char *porttype; /* Port type, or "" for any. */
303 const char *type; /* Terminal type to select. */
304 int conditional; /* Baud rate conditionals bitmask. */
305 int speed; /* Baud rate to compare against. */
308 static MAP *cur, *maplist;
310 #define DATA(name,value) { { name }, value }
312 typedef struct speeds {
313 const char string[7];
317 static const SPEEDS speeds[] =
334 /* sgttyb may define up to this point */
336 DATA("19200", B19200),
339 DATA("38400", B38400),
342 DATA("19200", B19200),
345 DATA("38400", B38400),
348 DATA("19200", B19200),
355 DATA("38400", B38400),
362 DATA("57600", B57600),
365 DATA("115200", B115200),
368 DATA("230400", B230400),
371 DATA("460800", B460800),
377 tbaudrate(char *rate)
379 const SPEEDS *sp = 0;
382 /* The baudrate number can be preceded by a 'B', which is ignored. */
386 for (n = 0; n < SIZEOF(speeds); ++n) {
387 if (!CaselessCmp(rate, speeds[n].string)) {
393 err("unknown baud rate %s", rate);
399 * [port-type][test baudrate]:terminal-type
400 * The baud rate tests are: >, <, @, =, !
403 add_mapping(const char *port, char *arg)
411 mapp = typeMalloc(MAP, 1);
412 if (copy == 0 || mapp == 0)
420 cur = maplist = mapp;
426 mapp->porttype = arg;
427 mapp->conditional = 0;
429 arg = strpbrk(arg, "><@=!:");
431 if (arg == 0) { /* [?]term */
432 mapp->type = mapp->porttype;
437 if (arg == mapp->porttype) /* [><@=! baud]:term */
438 termp = mapp->porttype = 0;
442 for (;; ++arg) { /* Optional conditionals. */
445 if (mapp->conditional & GT)
447 mapp->conditional |= LT;
450 if (mapp->conditional & LT)
452 mapp->conditional |= GT;
455 case '=': /* Not documented. */
456 mapp->conditional |= EQ;
459 mapp->conditional |= NOT;
468 if (mapp->conditional)
471 } else { /* Optional baudrate. */
472 arg = strchr(p = arg, ':');
476 mapp->speed = tbaudrate(p);
481 /* Terminate porttype, if specified. */
485 /* If a NOT conditional, reverse the test. */
486 if (mapp->conditional & NOT)
487 mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
489 /* If user specified a port with an option flag, set it. */
492 if (mapp->porttype) {
494 err("illegal -m option format: %s", copy);
496 mapp->porttype = port;
500 (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
501 (void) printf("type: %s\n", mapp->type);
502 (void) printf("conditional: ");
504 if (mapp->conditional & GT) {
508 if (mapp->conditional & EQ) {
509 (void) printf("%sEQ", p);
512 if (mapp->conditional & LT)
513 (void) printf("%sLT", p);
514 (void) printf("\nspeed: %d\n", mapp->speed);
519 * Return the type of terminal to use for a port of type 'type', as specified
520 * by the first applicable mapping in 'map'. If no mappings apply, return
524 mapped(const char *type)
529 for (mapp = maplist; mapp; mapp = mapp->next)
530 if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
531 switch (mapp->conditional) {
532 case 0: /* No test specified. */
536 match = ((int) ospeed == mapp->speed);
539 match = ((int) ospeed >= mapp->speed);
542 match = ((int) ospeed > mapp->speed);
545 match = ((int) ospeed <= mapp->speed);
548 match = ((int) ospeed < mapp->speed);
556 /* No match found; return given type. */
560 /**************************************************************************
564 **************************************************************************/
567 * Figure out what kind of terminal we're dealing with, and then read in
571 get_termcap_entry(char *userarg)
588 /* Try the environment. */
589 if ((ttype = getenv("TERM")) != 0)
592 if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
593 p = _nc_basename(ttypath);
596 * We have the 4.3BSD library call getttynam(3); that means
597 * there's an /etc/ttys to look up device-to-type mappings in.
598 * Try ttyname(3); check for dialup or other mapping.
600 if ((t = getttynam(p))) {
605 if ((fp = fopen("/etc/ttytype", "r")) != 0
606 || (fp = fopen("/etc/ttys", "r")) != 0) {
610 while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) {
611 for (s = buffer, t = d = 0; *s; s++) {
612 if (isspace(UChar(*s)))
616 else if (d == 0 && s != buffer && s[-1] == '\0')
619 if (t != 0 && d != 0 && !strcmp(d, p)) {
627 #endif /* HAVE_GETTTYNAM */
630 /* If still undefined, use "unknown". */
633 map:ttype = mapped(ttype);
636 * If not a path, remove TERMCAP from the environment so we get a
637 * real entry from /etc/termcap. This prevents us from being fooled
638 * by out of date stuff in the environment.
641 if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) {
642 /* 'unsetenv("TERMCAP")' is not portable.
643 * The 'environ' array is better.
646 for (n = 0; environ[n] != 0; n++) {
647 if (!strncmp("TERMCAP=", environ[n], (size_t) 8)) {
648 while ((environ[n] = environ[n + 1]) != 0) {
657 * ttype now contains a pointer to the type of the terminal.
658 * If the first character is '?', ask the user.
660 if (ttype[0] == '?') {
661 if (ttype[1] != '\0')
662 ttype = askuser(ttype + 1);
666 /* Find the terminfo entry. If it doesn't exist, ask the user. */
667 while (setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO, &errret)
670 (void) fprintf(stderr, "%s: unknown terminal type %s\n",
671 _nc_progname, ttype);
674 (void) fprintf(stderr,
675 "%s: can't initialize terminal type %s (error %d)\n",
676 _nc_progname, ttype, errret);
679 ttype = askuser(ttype);
682 tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */
687 /**************************************************************************
691 **************************************************************************/
693 /* some BSD systems have these built in, some systems are missing
694 * one or more definitions. The safest solution is to override unless the
695 * commonly-altered ones are defined.
697 #if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT))
710 /* control-character defaults */
712 #define CEOF CTRL('D')
715 #define CERASE CTRL('H')
718 #define CINTR 127 /* ^? */
721 #define CKILL CTRL('U')
724 #define CLNEXT CTRL('v')
727 #define CRPRNT CTRL('r')
730 #define CQUIT CTRL('\\')
733 #define CSTART CTRL('Q')
736 #define CSTOP CTRL('S')
739 #define CSUSP CTRL('Z')
742 #if defined(_POSIX_VDISABLE)
743 #define DISABLED(val) (((_POSIX_VDISABLE != -1) \
744 && ((val) == _POSIX_VDISABLE)) \
747 #define DISABLED(val) ((int)(val) <= 0)
750 #define CHK(val, dft) (unsigned char) (DISABLED(val) ? dft : val)
752 static bool set_tabs(void);
755 * Reset the terminal mode bits to a sensible state. Very useful after
756 * a child program dies in raw mode.
762 tcgetattr(STDERR_FILENO, &mode);
764 stty(STDERR_FILENO, &mode);
768 #if defined(VDISCARD) && defined(CDISCARD)
769 mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
771 mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
772 mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
773 #if defined(VFLUSH) && defined(CFLUSH)
774 mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
776 mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
777 mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
778 #if defined(VLNEXT) && defined(CLNEXT)
779 mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
781 mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
782 #if defined(VREPRINT) && defined(CRPRNT)
783 mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
785 #if defined(VSTART) && defined(CSTART)
786 mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
788 #if defined(VSTOP) && defined(CSTOP)
789 mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
791 #if defined(VSUSP) && defined(CSUSP)
792 mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
794 #if defined(VWERASE) && defined(CWERASE)
795 mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
798 mode.c_iflag &= ~((unsigned) (IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
807 mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
813 mode.c_oflag &= ~((unsigned) (0
852 mode.c_oflag |= (OPOST
858 mode.c_cflag &= ~((unsigned) (CSIZE | CSTOPB | PARENB | PARODD | CLOCAL));
859 mode.c_cflag |= (CS8 | CREAD);
860 mode.c_lflag &= ~((unsigned) (ECHONL | NOFLSH
872 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
882 SET_TTY(STDERR_FILENO, &mode);
886 * Returns a "good" value for the erase character. This is loosely based on
896 && key_backspace != 0
897 && strlen(key_backspace) == 1)
898 result = key_backspace[0];
907 * Update the values of the erase, interrupt, and kill characters in 'mode'.
909 * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
910 * characters if they're unset, or if we specify them as options. This differs
911 * from BSD 4.4 tset, which always sets erase.
914 set_control_chars(void)
917 if (DISABLED(mode.c_cc[VERASE]) || terasechar >= 0) {
918 mode.c_cc[VERASE] = UChar((terasechar >= 0)
923 if (DISABLED(mode.c_cc[VINTR]) || intrchar >= 0) {
924 mode.c_cc[VINTR] = UChar((intrchar >= 0)
929 if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) {
930 mode.c_cc[VKILL] = UChar((tkillchar >= 0)
938 * Set up various conversions in 'mode', including parity, tabs, returns,
939 * echo, and case, according to the termcap entry. If the program we're
940 * running was named with a leading upper-case character, map external
941 * uppercase to internal lowercase.
944 set_conversions(void)
948 * Conversion logic for some *really* ancient terminal glitches,
949 * not supported in terminfo. Left here for succeeding generations
952 if (tgetflag("UC")) {
954 mode.c_iflag |= IUCLC;
955 mode.c_oflag |= OLCUC;
957 } else if (tgetflag("LC")) {
959 mode.c_iflag &= ~IUCLC;
960 mode.c_oflag &= ~OLCUC;
963 mode.c_iflag &= ~(PARMRK | INPCK);
964 mode.c_lflag |= ICANON;
965 if (tgetflag("EP")) {
966 mode.c_cflag |= PARENB;
967 mode.c_cflag &= ~PARODD;
969 if (tgetflag("OP")) {
970 mode.c_cflag |= PARENB;
971 mode.c_cflag |= PARODD;
973 #endif /* __OBSOLETE__ */
977 mode.c_oflag |= ONLCR;
979 mode.c_iflag |= ICRNL;
980 mode.c_lflag |= ECHO;
982 mode.c_oflag |= OXTABS;
985 /* test used to be tgetflag("NL") */
986 if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) {
987 /* Newline, not linefeed. */
989 mode.c_oflag &= ~((unsigned) ONLCR);
991 mode.c_iflag &= ~((unsigned) ICRNL);
994 if (tgetflag("HD")) /* Half duplex. */
995 mode.c_lflag &= ~ECHO;
996 #endif /* __OBSOLETE__ */
998 /* test used to be tgetflag("pt") */
999 if (has_hardware_tabs) /* Print tabs. */
1000 mode.c_oflag &= ~OXTABS;
1002 mode.c_lflag |= (ECHOE | ECHOK);
1006 /* Output startup string. */
1014 if (pad_char != (char *) 0) /* Get/set pad character. */
1016 #endif /* OBSOLETE */
1019 if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
1020 oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
1021 SET_TTY(STDERR_FILENO, &oldmode);
1024 settle = set_tabs();
1027 if ((p = reset_1string) != 0) {
1031 if ((p = reset_2string) != 0) {
1035 /* What about rf, rs3, as per terminfo man page? */
1036 /* also might be nice to send rmacs, rmul, rmm */
1037 if ((p = reset_file) != 0
1038 || (p = init_file) != 0) {
1045 (void) putc('\r', stderr);
1046 (void) fflush(stderr);
1047 (void) napms(1000); /* Settle the terminal. */
1052 * Set the hardware tabs on the terminal, using the ct (clear all tabs),
1053 * st (set one tab) and ch (horizontal cursor addressing) capabilities.
1054 * This is done before if and is, so they can patch in case we blow this.
1055 * Return TRUE if we set any tab stops, FALSE if not.
1060 if (set_tab && clear_all_tabs) {
1070 (void) putc('\r', stderr); /* Force to left margin. */
1071 tputs(clear_all_tabs, 0, outc);
1073 for (c = 8; c < lim; c += 8) {
1074 /* Get to the right column. In BSD tset, this
1075 * used to try a bunch of half-clever things
1076 * with cup and hpa, for an average saving of
1077 * somewhat less than two character times per
1078 * tab stop, less than .01 sec at 2400cps. We
1079 * lost all this cruft because it seemed to be
1080 * introducing some odd bugs.
1081 * -----------12345678----------- */
1082 (void) fputs(" ", stderr);
1083 tputs(set_tab, 0, outc);
1091 /**************************************************************************
1095 **************************************************************************/
1098 * Tell the user if a control key has been changed from the default value.
1102 report(const char *name, int which, unsigned def)
1104 unsigned older, newer;
1107 newer = mode.c_cc[which];
1108 older = oldmode.c_cc[which];
1110 if (older == newer && older == def)
1113 (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to");
1115 if (DISABLED(newer))
1116 (void) fprintf(stderr, "undef.\n");
1118 * Check 'delete' before 'backspace', since the key_backspace value
1121 else if (newer == 0177)
1122 (void) fprintf(stderr, "delete.\n");
1123 else if ((p = key_backspace) != 0
1124 && newer == (unsigned char) p[0]
1126 (void) fprintf(stderr, "backspace.\n");
1127 else if (newer < 040) {
1129 (void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer));
1131 (void) fprintf(stderr, "%c.\n", UChar(newer));
1136 * Convert the obsolete argument forms into something that getopt can handle.
1137 * This means that -e, -i and -k get default arguments supplied for them.
1140 obsolete(char **argv)
1142 for (; *argv; ++argv) {
1143 char *parm = argv[0];
1145 if (parm[0] == '-' && parm[1] == '\0') {
1146 argv[0] = strdup("-q");
1150 if ((parm[0] != '-')
1151 || (argv[1] && argv[1][0] != '-')
1152 || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
1153 || (parm[2] != '\0'))
1155 switch (argv[0][1]) {
1157 argv[0] = strdup("-e^H");
1160 argv[0] = strdup("-i^C");
1163 argv[0] = strdup("-k^U");
1172 #define DATA(s) s "\n"
1173 static const char msg[] =
1177 DATA(" -c set control characters")
1178 DATA(" -e ch erase character")
1179 DATA(" -I no initialization strings")
1180 DATA(" -i ch interrupt character")
1181 DATA(" -k ch kill character")
1182 DATA(" -m mapping map identifier to type")
1183 DATA(" -Q do not output control key settings")
1184 DATA(" -r display term on stderr")
1185 DATA(" -s output TERM set command")
1186 DATA(" -V print curses-version")
1187 DATA(" -w set window-size")
1190 (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
1199 return (char) ((optarg[0] == '^' && optarg[1] != '\0')
1200 ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
1205 main(int argc, char **argv)
1207 int ch, noinit, noset, quiet, Sflag, sflag, showterm;
1212 noinit = noset = quiet = Sflag = sflag = showterm = 0;
1213 while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:np:qQSrsVw")) != -1) {
1215 case 'c': /* set control-chars */
1218 case 'a': /* OBSOLETE: map identifier to type */
1219 add_mapping("arpanet", optarg);
1221 case 'd': /* OBSOLETE: map identifier to type */
1222 add_mapping("dialup", optarg);
1224 case 'e': /* erase character */
1225 terasechar = arg_to_char();
1227 case 'I': /* no initialization strings */
1230 case 'i': /* interrupt character */
1231 intrchar = arg_to_char();
1233 case 'k': /* kill character */
1234 tkillchar = arg_to_char();
1236 case 'm': /* map identifier to type */
1237 add_mapping(0, optarg);
1239 case 'n': /* OBSOLETE: set new tty driver */
1241 case 'p': /* OBSOLETE: map identifier to type */
1242 add_mapping("plugboard", optarg);
1244 case 'Q': /* don't output control key settings */
1247 case 'q': /* display term only */
1250 case 'r': /* display term on stderr */
1253 case 'S': /* OBSOLETE: output TERM & TERMCAP */
1256 case 's': /* output TERM set command */
1259 case 'V': /* print curses-version */
1260 puts(curses_version());
1261 ExitProgram(EXIT_SUCCESS);
1262 case 'w': /* set window-size */
1271 _nc_progname = _nc_rootname(*argv);
1278 if (!opt_c && !opt_w)
1279 opt_c = opt_w = TRUE;
1281 if (GET_TTY(STDERR_FILENO, &mode) < 0)
1282 failed("standard error");
1284 original = oldmode = mode;
1286 ospeed = (NCURSES_OSPEED) cfgetospeed(&mode);
1288 ospeed = (NCURSES_OSPEED) mode.sg_ospeed;
1291 if (same_program(_nc_progname, PROG_RESET)) {
1296 ttype = get_termcap_entry(*argv);
1305 /* Set window size if not set already */
1306 (void) ioctl(STDERR_FILENO, IOCTL_GET_WINSIZE, &win);
1307 if (WINSIZE_ROWS(win) == 0 &&
1308 WINSIZE_COLS(win) == 0 &&
1309 tlines > 0 && tcolumns > 0) {
1310 WINSIZE_ROWS(win) = (unsigned short) tlines;
1311 WINSIZE_COLS(win) = (unsigned short) tcolumns;
1312 (void) ioctl(STDERR_FILENO, IOCTL_SET_WINSIZE, &win);
1317 set_control_chars();
1323 /* Set the modes if they've changed. */
1324 if (memcmp(&mode, &oldmode, sizeof(mode))) {
1325 SET_TTY(STDERR_FILENO, &mode);
1331 (void) printf("%s\n", ttype);
1334 (void) fprintf(stderr, "Terminal type is %s.\n", ttype);
1336 * If erase, kill and interrupt characters could have been
1337 * modified and not -Q, display the changes.
1341 report("Erase", VERASE, CERASE);
1342 report("Kill", VKILL, CKILL);
1343 report("Interrupt", VINTR, CINTR);
1349 err("The -S option is not supported under terminfo.");
1356 * Figure out what shell we're using. A hack, we look for an
1357 * environmental variable SHELL ending in "csh".
1359 if ((var = getenv("SHELL")) != 0
1360 && ((len = (int) strlen(leaf = _nc_basename(var))) >= 3)
1361 && !strcmp(leaf + len - 3, "csh"))
1362 p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
1365 (void) printf(p, ttype);
1368 ExitProgram(EXIT_SUCCESS);