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.95 2015/04/04 15:09:24 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;
383 /* The baudrate number can be preceded by a 'B', which is ignored. */
387 for (n = 0; n < SIZEOF(speeds); ++n) {
388 if (!CaselessCmp(rate, speeds[n].string)) {
395 err("unknown baud rate %s", rate);
401 * [port-type][test baudrate]:terminal-type
402 * The baud rate tests are: >, <, @, =, !
405 add_mapping(const char *port, char *arg)
413 mapp = typeMalloc(MAP, 1);
414 if (copy == 0 || mapp == 0)
422 cur = maplist = mapp;
428 mapp->porttype = arg;
429 mapp->conditional = 0;
431 arg = strpbrk(arg, "><@=!:");
433 if (arg == 0) { /* [?]term */
434 mapp->type = mapp->porttype;
439 if (arg == mapp->porttype) /* [><@=! baud]:term */
440 termp = mapp->porttype = 0;
444 for (;; ++arg) { /* Optional conditionals. */
447 if (mapp->conditional & GT)
449 mapp->conditional |= LT;
452 if (mapp->conditional & LT)
454 mapp->conditional |= GT;
457 case '=': /* Not documented. */
458 mapp->conditional |= EQ;
461 mapp->conditional |= NOT;
470 if (mapp->conditional)
473 } else { /* Optional baudrate. */
474 arg = strchr(p = arg, ':');
478 mapp->speed = tbaudrate(p);
483 /* Terminate porttype, if specified. */
487 /* If a NOT conditional, reverse the test. */
488 if (mapp->conditional & NOT)
489 mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
491 /* If user specified a port with an option flag, set it. */
494 if (mapp->porttype) {
496 err("illegal -m option format: %s", copy);
498 mapp->porttype = port;
502 (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
503 (void) printf("type: %s\n", mapp->type);
504 (void) printf("conditional: ");
506 if (mapp->conditional & GT) {
510 if (mapp->conditional & EQ) {
511 (void) printf("%sEQ", p);
514 if (mapp->conditional & LT)
515 (void) printf("%sLT", p);
516 (void) printf("\nspeed: %d\n", mapp->speed);
521 * Return the type of terminal to use for a port of type 'type', as specified
522 * by the first applicable mapping in 'map'. If no mappings apply, return
526 mapped(const char *type)
531 for (mapp = maplist; mapp; mapp = mapp->next)
532 if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
533 switch (mapp->conditional) {
534 case 0: /* No test specified. */
538 match = ((int) ospeed == mapp->speed);
541 match = ((int) ospeed >= mapp->speed);
544 match = ((int) ospeed > mapp->speed);
547 match = ((int) ospeed <= mapp->speed);
550 match = ((int) ospeed < mapp->speed);
558 /* No match found; return given type. */
562 /**************************************************************************
566 **************************************************************************/
569 * Figure out what kind of terminal we're dealing with, and then read in
573 get_termcap_entry(char *userarg)
590 /* Try the environment. */
591 if ((ttype = getenv("TERM")) != 0)
594 if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
595 p = _nc_basename(ttypath);
598 * We have the 4.3BSD library call getttynam(3); that means
599 * there's an /etc/ttys to look up device-to-type mappings in.
600 * Try ttyname(3); check for dialup or other mapping.
602 if ((t = getttynam(p))) {
607 if ((fp = fopen("/etc/ttytype", "r")) != 0
608 || (fp = fopen("/etc/ttys", "r")) != 0) {
612 while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) {
613 for (s = buffer, t = d = 0; *s; s++) {
614 if (isspace(UChar(*s)))
618 else if (d == 0 && s != buffer && s[-1] == '\0')
621 if (t != 0 && d != 0 && !strcmp(d, p)) {
629 #endif /* HAVE_GETTTYNAM */
632 /* If still undefined, use "unknown". */
635 map:ttype = mapped(ttype);
638 * If not a path, remove TERMCAP from the environment so we get a
639 * real entry from /etc/termcap. This prevents us from being fooled
640 * by out of date stuff in the environment.
643 if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) {
644 /* 'unsetenv("TERMCAP")' is not portable.
645 * The 'environ' array is better.
648 for (n = 0; environ[n] != 0; n++) {
649 if (!strncmp("TERMCAP=", environ[n], (size_t) 8)) {
650 while ((environ[n] = environ[n + 1]) != 0) {
659 * ttype now contains a pointer to the type of the terminal.
660 * If the first character is '?', ask the user.
662 if (ttype[0] == '?') {
663 if (ttype[1] != '\0')
664 ttype = askuser(ttype + 1);
668 /* Find the terminfo entry. If it doesn't exist, ask the user. */
669 while (setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO, &errret)
672 (void) fprintf(stderr, "%s: unknown terminal type %s\n",
673 _nc_progname, ttype);
676 (void) fprintf(stderr,
677 "%s: can't initialize terminal type %s (error %d)\n",
678 _nc_progname, ttype, errret);
681 ttype = askuser(ttype);
684 tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */
689 /**************************************************************************
693 **************************************************************************/
695 /* some BSD systems have these built in, some systems are missing
696 * one or more definitions. The safest solution is to override unless the
697 * commonly-altered ones are defined.
699 #if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT))
712 /* control-character defaults */
714 #define CEOF CTRL('D')
717 #define CERASE CTRL('H')
720 #define CINTR 127 /* ^? */
723 #define CKILL CTRL('U')
726 #define CLNEXT CTRL('v')
729 #define CRPRNT CTRL('r')
732 #define CQUIT CTRL('\\')
735 #define CSTART CTRL('Q')
738 #define CSTOP CTRL('S')
741 #define CSUSP CTRL('Z')
744 #if defined(_POSIX_VDISABLE)
745 #define DISABLED(val) (((_POSIX_VDISABLE != -1) \
746 && ((val) == _POSIX_VDISABLE)) \
749 #define DISABLED(val) ((int)(val) <= 0)
752 #define CHK(val, dft) (unsigned char) (DISABLED(val) ? dft : val)
754 static bool set_tabs(void);
757 * Reset the terminal mode bits to a sensible state. Very useful after
758 * a child program dies in raw mode.
764 tcgetattr(STDERR_FILENO, &mode);
766 stty(STDERR_FILENO, &mode);
770 #if defined(VDISCARD) && defined(CDISCARD)
771 mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
773 mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
774 mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
775 #if defined(VFLUSH) && defined(CFLUSH)
776 mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
778 mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
779 mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
780 #if defined(VLNEXT) && defined(CLNEXT)
781 mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
783 mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
784 #if defined(VREPRINT) && defined(CRPRNT)
785 mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
787 #if defined(VSTART) && defined(CSTART)
788 mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
790 #if defined(VSTOP) && defined(CSTOP)
791 mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
793 #if defined(VSUSP) && defined(CSUSP)
794 mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
796 #if defined(VWERASE) && defined(CWERASE)
797 mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
800 mode.c_iflag &= ~((unsigned) (IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
809 mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
815 mode.c_oflag &= ~((unsigned) (0
854 mode.c_oflag |= (OPOST
860 mode.c_cflag &= ~((unsigned) (CSIZE | CSTOPB | PARENB | PARODD | CLOCAL));
861 mode.c_cflag |= (CS8 | CREAD);
862 mode.c_lflag &= ~((unsigned) (ECHONL | NOFLSH
874 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
884 SET_TTY(STDERR_FILENO, &mode);
888 * Returns a "good" value for the erase character. This is loosely based on
898 && key_backspace != 0
899 && strlen(key_backspace) == 1)
900 result = key_backspace[0];
909 * Update the values of the erase, interrupt, and kill characters in 'mode'.
911 * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
912 * characters if they're unset, or if we specify them as options. This differs
913 * from BSD 4.4 tset, which always sets erase.
916 set_control_chars(void)
919 if (DISABLED(mode.c_cc[VERASE]) || terasechar >= 0) {
920 mode.c_cc[VERASE] = UChar((terasechar >= 0)
925 if (DISABLED(mode.c_cc[VINTR]) || intrchar >= 0) {
926 mode.c_cc[VINTR] = UChar((intrchar >= 0)
931 if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) {
932 mode.c_cc[VKILL] = UChar((tkillchar >= 0)
940 * Set up various conversions in 'mode', including parity, tabs, returns,
941 * echo, and case, according to the termcap entry. If the program we're
942 * running was named with a leading upper-case character, map external
943 * uppercase to internal lowercase.
946 set_conversions(void)
950 * Conversion logic for some *really* ancient terminal glitches,
951 * not supported in terminfo. Left here for succeeding generations
954 if (tgetflag("UC")) {
956 mode.c_iflag |= IUCLC;
957 mode.c_oflag |= OLCUC;
959 } else if (tgetflag("LC")) {
961 mode.c_iflag &= ~IUCLC;
962 mode.c_oflag &= ~OLCUC;
965 mode.c_iflag &= ~(PARMRK | INPCK);
966 mode.c_lflag |= ICANON;
967 if (tgetflag("EP")) {
968 mode.c_cflag |= PARENB;
969 mode.c_cflag &= ~PARODD;
971 if (tgetflag("OP")) {
972 mode.c_cflag |= PARENB;
973 mode.c_cflag |= PARODD;
975 #endif /* __OBSOLETE__ */
979 mode.c_oflag |= ONLCR;
981 mode.c_iflag |= ICRNL;
982 mode.c_lflag |= ECHO;
984 mode.c_oflag |= OXTABS;
987 /* test used to be tgetflag("NL") */
988 if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) {
989 /* Newline, not linefeed. */
991 mode.c_oflag &= ~((unsigned) ONLCR);
993 mode.c_iflag &= ~((unsigned) ICRNL);
996 if (tgetflag("HD")) /* Half duplex. */
997 mode.c_lflag &= ~ECHO;
998 #endif /* __OBSOLETE__ */
1000 /* test used to be tgetflag("pt") */
1001 if (has_hardware_tabs) /* Print tabs. */
1002 mode.c_oflag &= ~OXTABS;
1004 mode.c_lflag |= (ECHOE | ECHOK);
1008 /* Output startup string. */
1016 if (pad_char != (char *) 0) /* Get/set pad character. */
1018 #endif /* OBSOLETE */
1021 if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
1022 oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
1023 SET_TTY(STDERR_FILENO, &oldmode);
1026 settle = set_tabs();
1029 if ((p = reset_1string) != 0) {
1033 if ((p = reset_2string) != 0) {
1037 /* What about rf, rs3, as per terminfo man page? */
1038 /* also might be nice to send rmacs, rmul, rmm */
1039 if ((p = reset_file) != 0
1040 || (p = init_file) != 0) {
1047 (void) putc('\r', stderr);
1048 (void) fflush(stderr);
1049 (void) napms(1000); /* Settle the terminal. */
1054 * Set the hardware tabs on the terminal, using the ct (clear all tabs),
1055 * st (set one tab) and ch (horizontal cursor addressing) capabilities.
1056 * This is done before if and is, so they can patch in case we blow this.
1057 * Return TRUE if we set any tab stops, FALSE if not.
1062 if (set_tab && clear_all_tabs) {
1072 (void) putc('\r', stderr); /* Force to left margin. */
1073 tputs(clear_all_tabs, 0, outc);
1075 for (c = 8; c < lim; c += 8) {
1076 /* Get to the right column. In BSD tset, this
1077 * used to try a bunch of half-clever things
1078 * with cup and hpa, for an average saving of
1079 * somewhat less than two character times per
1080 * tab stop, less than .01 sec at 2400cps. We
1081 * lost all this cruft because it seemed to be
1082 * introducing some odd bugs.
1083 * -----------12345678----------- */
1084 (void) fputs(" ", stderr);
1085 tputs(set_tab, 0, outc);
1093 /**************************************************************************
1097 **************************************************************************/
1100 * Tell the user if a control key has been changed from the default value.
1104 report(const char *name, int which, unsigned def)
1106 unsigned older, newer;
1109 newer = mode.c_cc[which];
1110 older = oldmode.c_cc[which];
1112 if (older == newer && older == def)
1115 (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to");
1117 if (DISABLED(newer))
1118 (void) fprintf(stderr, "undef.\n");
1120 * Check 'delete' before 'backspace', since the key_backspace value
1123 else if (newer == 0177)
1124 (void) fprintf(stderr, "delete.\n");
1125 else if ((p = key_backspace) != 0
1126 && newer == (unsigned char) p[0]
1128 (void) fprintf(stderr, "backspace.\n");
1129 else if (newer < 040) {
1131 (void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer));
1133 (void) fprintf(stderr, "%c.\n", UChar(newer));
1138 * Convert the obsolete argument forms into something that getopt can handle.
1139 * This means that -e, -i and -k get default arguments supplied for them.
1142 obsolete(char **argv)
1144 for (; *argv; ++argv) {
1145 char *parm = argv[0];
1147 if (parm[0] == '-' && parm[1] == '\0') {
1148 argv[0] = strdup("-q");
1152 if ((parm[0] != '-')
1153 || (argv[1] && argv[1][0] != '-')
1154 || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
1155 || (parm[2] != '\0'))
1157 switch (argv[0][1]) {
1159 argv[0] = strdup("-e^H");
1162 argv[0] = strdup("-i^C");
1165 argv[0] = strdup("-k^U");
1174 #define DATA(s) s "\n"
1175 static const char msg[] =
1179 DATA(" -c set control characters")
1180 DATA(" -e ch erase character")
1181 DATA(" -I no initialization strings")
1182 DATA(" -i ch interrupt character")
1183 DATA(" -k ch kill character")
1184 DATA(" -m mapping map identifier to type")
1185 DATA(" -Q do not output control key settings")
1186 DATA(" -r display term on stderr")
1187 DATA(" -s output TERM set command")
1188 DATA(" -V print curses-version")
1189 DATA(" -w set window-size")
1192 (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
1201 return (char) ((optarg[0] == '^' && optarg[1] != '\0')
1202 ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
1207 main(int argc, char **argv)
1209 int ch, noinit, noset, quiet, Sflag, sflag, showterm;
1214 noinit = noset = quiet = Sflag = sflag = showterm = 0;
1215 while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:np:qQSrsVw")) != -1) {
1217 case 'c': /* set control-chars */
1220 case 'a': /* OBSOLETE: map identifier to type */
1221 add_mapping("arpanet", optarg);
1223 case 'd': /* OBSOLETE: map identifier to type */
1224 add_mapping("dialup", optarg);
1226 case 'e': /* erase character */
1227 terasechar = arg_to_char();
1229 case 'I': /* no initialization strings */
1232 case 'i': /* interrupt character */
1233 intrchar = arg_to_char();
1235 case 'k': /* kill character */
1236 tkillchar = arg_to_char();
1238 case 'm': /* map identifier to type */
1239 add_mapping(0, optarg);
1241 case 'n': /* OBSOLETE: set new tty driver */
1243 case 'p': /* OBSOLETE: map identifier to type */
1244 add_mapping("plugboard", optarg);
1246 case 'Q': /* don't output control key settings */
1249 case 'q': /* display term only */
1252 case 'r': /* display term on stderr */
1255 case 'S': /* OBSOLETE: output TERM & TERMCAP */
1258 case 's': /* output TERM set command */
1261 case 'V': /* print curses-version */
1262 puts(curses_version());
1263 ExitProgram(EXIT_SUCCESS);
1264 case 'w': /* set window-size */
1273 _nc_progname = _nc_rootname(*argv);
1280 if (!opt_c && !opt_w)
1281 opt_c = opt_w = TRUE;
1283 if (GET_TTY(STDERR_FILENO, &mode) < 0)
1284 failed("standard error");
1286 original = oldmode = mode;
1288 ospeed = (NCURSES_OSPEED) cfgetospeed(&mode);
1290 ospeed = (NCURSES_OSPEED) mode.sg_ospeed;
1293 if (same_program(_nc_progname, PROG_RESET)) {
1298 (void) get_termcap_entry(*argv);
1307 /* Set window size if not set already */
1308 (void) ioctl(STDERR_FILENO, IOCTL_GET_WINSIZE, &win);
1309 if (WINSIZE_ROWS(win) == 0 &&
1310 WINSIZE_COLS(win) == 0 &&
1311 tlines > 0 && tcolumns > 0) {
1312 WINSIZE_ROWS(win) = (unsigned short) tlines;
1313 WINSIZE_COLS(win) = (unsigned short) tcolumns;
1314 (void) ioctl(STDERR_FILENO, IOCTL_SET_WINSIZE, &win);
1319 set_control_chars();
1325 /* Set the modes if they've changed. */
1326 if (memcmp(&mode, &oldmode, sizeof(mode))) {
1327 SET_TTY(STDERR_FILENO, &mode);
1332 /* Get the terminal name from the entry. */
1333 ttype = _nc_first_name(cur_term->type.term_names);
1336 (void) printf("%s\n", ttype);
1339 (void) fprintf(stderr, "Terminal type is %s.\n", ttype);
1341 * If erase, kill and interrupt characters could have been
1342 * modified and not -Q, display the changes.
1346 report("Erase", VERASE, CERASE);
1347 report("Kill", VKILL, CKILL);
1348 report("Interrupt", VINTR, CINTR);
1354 err("The -S option is not supported under terminfo.");
1361 * Figure out what shell we're using. A hack, we look for an
1362 * environmental variable SHELL ending in "csh".
1364 if ((var = getenv("SHELL")) != 0
1365 && ((len = (int) strlen(leaf = _nc_basename(var))) >= 3)
1366 && !strcmp(leaf + len - 3, "csh"))
1367 p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
1370 (void) printf(p, ttype);
1373 ExitProgram(EXIT_SUCCESS);