1 /****************************************************************************
2 * Copyright (c) 1998 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 ****************************************************************************/
36 * tset.c - terminal initialization utility
38 * This code was mostly swiped from 4.4BSD tset, with some obsolescent
39 * cruft removed and substantial portions rewritten. A Regents of the
40 * University of California copyright applies to some portions of the
41 * code, and is reproduced below:
44 * Copyright (c) 1980, 1991, 1993
45 * The Regents of the University of California. All rights reserved.
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed by the University of
58 * California, Berkeley and its contributors.
59 * 4. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
76 #define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */
77 #include <progs.priv.h>
84 #if HAVE_GETTTYNAM && HAVE_TTYENT_H
88 char *ttyname(int fd);
91 /* this is just to stifle a missing-prototype warning */
93 # include <sys/ioctl.h>
97 /* they neglected to define struct winsize in termios.h -- it's only
99 #include <sys/stream.h>
100 #include <sys/ptem.h>
103 #include <curses.h> /* for bool typedef */
104 #include <dump_entry.h>
106 MODULE_ID("$Id: tset.c,v 0.31 1998/02/11 12:14:02 tom Exp $")
108 extern char **environ;
111 #define CTRL(x) ((x) & 0x1f)
113 const char *_nc_progname = "tset";
115 static TTY mode, oldmode;
117 static int terasechar = -1; /* new erase character */
118 static int intrchar = -1; /* new interrupt character */
119 static int isreset; /* invoked as reset */
120 static int tkillchar = -1; /* new kill character */
121 static int tlines, tcolumns; /* window size */
123 #define LOWERCASE(c) ((isalpha(c) && isupper(c)) ? tolower(c) : (c))
126 CaselessCmp(const char *a, const char *b) /* strcasecmp isn't portable */
129 int cmp = LOWERCASE(*a) - LOWERCASE(*b);
134 return LOWERCASE(*a) - LOWERCASE(*b);
138 static char *strdup (char *s)
142 p = malloc(strlen(s)+1);
147 #endif /* not HAVE_STRDUP */
150 err(const char *fmt, ...)
154 (void)fprintf(stderr, "tset: ");
155 (void)vfprintf(stderr, fmt, ap);
157 (void)fprintf(stderr, "\n");
163 failed(const char *msg)
166 perror(strcat(strcpy(temp, "tset: "), msg));
174 register int fd, nr, nw;
177 if ((fd = open(file, O_RDONLY, 0)) < 0)
180 while ((nr = read(fd, buf, sizeof(buf))) > 0)
181 if ((nw = write(STDERR_FILENO, buf, (size_t)nr)) == -1)
182 failed("write to stderr");
191 return putc(c, stderr);
194 /* Prompt the user for a terminal type. */
196 askuser(const char *dflt)
198 static char answer[256];
201 /* We can get recalled; if so, don't continue uselessly. */
202 if (feof(stdin) || ferror(stdin)) {
203 (void)fprintf(stderr, "\n");
208 (void)fprintf(stderr, "Terminal type? [%s] ", dflt);
210 (void)fprintf(stderr, "Terminal type? ");
211 (void)fflush(stderr);
213 if (fgets(answer, sizeof(answer), stdin) == 0) {
215 (void)fprintf(stderr, "\n");
221 if ((p = strchr(answer, '\n')) != 0)
230 /**************************************************************************
232 * Mapping logic begins here
234 **************************************************************************/
236 /* Baud rate conditionals for mapping. */
245 struct map *next; /* Linked list of maps. */
246 const char *porttype; /* Port type, or "" for any. */
247 const char *type; /* Terminal type to select. */
248 int conditional; /* Baud rate conditionals bitmask. */
249 int speed; /* Baud rate to compare against. */
252 static MAP *cur, *maplist;
254 typedef struct speeds {
259 static const SPEEDS speeds[] = {
297 { "115200", B115200 },
300 { "230400", B230400 },
303 { "460800", B460800 },
309 tbaudrate(char *rate)
314 /* The baudrate number can be preceded by a 'B', which is ignored. */
318 for (sp = speeds; sp->string; ++sp) {
319 if (!CaselessCmp(rate, sp->string)) {
325 err("unknown baud rate %s", rate);
331 * [port-type][test baudrate]:terminal-type
332 * The baud rate tests are: >, <, @, =, !
335 add_mapping(const char *port, char *arg)
343 mapp = malloc((u_int)sizeof(MAP));
344 if (copy == 0 || mapp == 0)
348 cur = maplist = mapp;
354 mapp->porttype = arg;
355 mapp->conditional = 0;
357 arg = strpbrk(arg, "><@=!:");
359 if (arg == 0) { /* [?]term */
360 mapp->type = mapp->porttype;
365 if (arg == mapp->porttype) /* [><@=! baud]:term */
366 termp = mapp->porttype = 0;
370 for (;; ++arg) /* Optional conditionals. */
373 if (mapp->conditional & GT)
375 mapp->conditional |= LT;
378 if (mapp->conditional & LT)
380 mapp->conditional |= GT;
383 case '=': /* Not documented. */
384 mapp->conditional |= EQ;
387 mapp->conditional |= NOT;
393 next: if (*arg == ':') {
394 if (mapp->conditional)
397 } else { /* Optional baudrate. */
398 arg = strchr(p = arg, ':');
402 mapp->speed = tbaudrate(p);
405 if (arg == (char *)0) /* Non-optional type. */
410 /* Terminate porttype, if specified. */
414 /* If a NOT conditional, reverse the test. */
415 if (mapp->conditional & NOT)
416 mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
418 /* If user specified a port with an option flag, set it. */
421 badmopt: err("illegal -m option format: %s", copy);
422 mapp->porttype = port;
426 (void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
427 (void)printf("type: %s\n", mapp->type);
428 (void)printf("conditional: ");
430 if (mapp->conditional & GT) {
434 if (mapp->conditional & EQ) {
435 (void)printf("%sEQ", p);
438 if (mapp->conditional & LT)
439 (void)printf("%sLT", p);
440 (void)printf("\nspeed: %d\n", mapp->speed);
445 * Return the type of terminal to use for a port of type 'type', as specified
446 * by the first applicable mapping in 'map'. If no mappings apply, return
450 mapped(const char *type)
455 for (mapp = maplist; mapp; mapp = mapp->next)
456 if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
457 switch (mapp->conditional) {
458 case 0: /* No test specified. */
462 match = (ospeed == mapp->speed);
465 match = (ospeed >= mapp->speed);
468 match = (ospeed > mapp->speed);
471 match = (ospeed <= mapp->speed);
474 match = (ospeed < mapp->speed);
482 /* No match found; return given type. */
486 /**************************************************************************
490 **************************************************************************/
493 * Figure out what kind of terminal we're dealing with, and then read in
497 get_termcap_entry(char *userarg)
514 /* Try the environment. */
515 if ((ttype = getenv("TERM")) != 0)
518 if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
519 if ((p = strrchr(ttypath, '/')) != 0)
525 * We have the 4.3BSD library call getttynam(3); that means
526 * there's an /etc/ttys to look up device-to-type mappings in.
527 * Try ttyname(3); check for dialup or other mapping.
529 if ((t = getttynam(p))) {
534 if ((fp = fopen("/etc/ttytype", "r")) != 0
535 || (fp = fopen("/etc/ttys", "r")) != 0) {
539 while (fgets(buffer, sizeof(buffer)-1, fp) != 0) {
540 for (s = buffer, t = d = 0; *s; s++) {
545 else if (d == 0 && s != buffer && s[-1] == '\0')
548 if (t != 0 && d != 0 && !strcmp(d,p)) {
556 #endif /* HAVE_GETTTYNAM */
559 /* If still undefined, use "unknown". */
562 map: ttype = mapped(ttype);
565 * If not a path, remove TERMCAP from the environment so we get a
566 * real entry from /etc/termcap. This prevents us from being fooled
567 * by out of date stuff in the environment.
569 found: if ((p = getenv("TERMCAP")) != 0 && *p != '/') {
570 /* 'unsetenv("TERMCAP")' is not portable.
571 * The 'environ' array is better.
574 for (n = 0; environ[n] != 0; n++) {
575 if (!strncmp("TERMCAP=", environ[n], 8)) {
576 while ((environ[n] = environ[n+1]) != 0) {
585 * ttype now contains a pointer to the type of the terminal.
586 * If the first character is '?', ask the user.
589 if (ttype[1] != '\0')
590 ttype = askuser(ttype + 1);
594 /* Find the terminfo entry. If it doesn't exist, ask the user. */
595 while ((rval = setupterm(ttype, STDOUT_FILENO, &errret)) != OK) {
597 (void)fprintf(stderr, "tset: unknown terminal type %s\n",
602 (void)fprintf(stderr, "tset: can't initialize terminal\
603 type %s (error %d)\n", ttype, errret);
606 ttype = askuser(ttype);
609 tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */
614 /**************************************************************************
618 **************************************************************************/
620 /* some BSD systems have these built in, some systems are missing
621 * one or more definitions. The safest solution is to override.
634 /* control-character defaults */
635 #define CEOF CTRL('D')
636 #define CERASE CTRL('H')
637 #define CINTR 127 /* ^? */
638 #define CKILL CTRL('U')
639 #define CLNEXT CTRL('v')
640 #define CRPRNT CTRL('r')
641 #define CQUIT CTRL('\\')
642 #define CSTART CTRL('Q')
643 #define CSTOP CTRL('S')
644 #define CSUSP CTRL('Z')
646 #define CHK(val, dft) ((int)val <= 0 ? dft : val)
648 static bool set_tabs (void);
651 * Reset the terminal mode bits to a sensible state. Very useful after
652 * a child program dies in raw mode.
658 tcgetattr(STDERR_FILENO, &mode);
660 stty(STDERR_FILENO,&mode);
664 #if defined(VDISCARD) && defined(CDISCARD)
665 mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
667 mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
668 mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
669 #if defined(VFLUSH) && defined(CFLUSH)
670 mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
672 mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
673 mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
674 #if defined(VLNEXT) && defined(CLNEXT)
675 mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
677 mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
678 #if defined(VREPRINT) && defined(CRPRNT)
679 mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
681 #if defined(VSTART) && defined(CSTART)
682 mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
684 #if defined(VSTOP) && defined(CSTOP)
685 mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
687 #if defined(VSUSP) && defined(CSUSP)
688 mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
690 #if defined(VWERASE) && defined(CWERASE)
691 mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
694 mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
703 mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
729 | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY
733 mode.c_oflag |= (OPOST
739 mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
740 mode.c_cflag |= (CS8 | CREAD);
741 mode.c_lflag &= ~(ECHONL | NOFLSH
753 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
764 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
766 stty(STDERR_FILENO, &mode);
771 * Returns a "good" value for the erase character. This is loosely based on
780 && key_backspace != 0
781 && strlen(key_backspace) == 1)
782 result = key_backspace[0];
790 * Update the values of the erase, interrupt, and kill characters in 'mode'.
792 * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
793 * characters if they're unset, or if we specify them as options. This differs
794 * from BSD 4.4 tset, which always sets erase.
797 set_control_chars(void)
800 if (mode.c_cc[VERASE] == 0 || terasechar >= 0)
801 mode.c_cc[VERASE] = terasechar >= 0 ? terasechar : default_erase();
803 if (mode.c_cc[VINTR] == 0 || intrchar >= 0)
804 mode.c_cc[VINTR] = intrchar >= 0 ? intrchar : CINTR;
806 if (mode.c_cc[VKILL] == 0 || tkillchar >= 0)
807 mode.c_cc[VKILL] = tkillchar >= 0 ? tkillchar : CKILL;
812 * Set up various conversions in 'mode', including parity, tabs, returns,
813 * echo, and case, according to the termcap entry. If the program we're
814 * running was named with a leading upper-case character, map external
815 * uppercase to internal lowercase.
818 set_conversions(void)
822 * Conversion logic for some *really* ancient terminal glitches,
823 * not supported in terminfo. Left here for succeeding generations
826 if (tgetflag("UC")) {
828 mode.c_iflag |= IUCLC;
829 mode.c_oflag |= OLCUC;
831 } else if (tgetflag("LC")) {
833 mode.c_iflag &= ~IUCLC;
834 mode.c_oflag &= ~OLCUC;
837 mode.c_iflag &= ~(PARMRK | INPCK);
838 mode.c_lflag |= ICANON;
839 if (tgetflag("EP")) {
840 mode.c_cflag |= PARENB;
841 mode.c_cflag &= ~PARODD;
843 if (tgetflag("OP")) {
844 mode.c_cflag |= PARENB;
845 mode.c_cflag |= PARODD;
847 #endif /* __OBSOLETE__ */
851 mode.c_oflag |= ONLCR;
853 mode.c_iflag |= ICRNL;
854 mode.c_lflag |= ECHO;
856 mode.c_oflag |= OXTABS;
859 /* test used to be tgetflag("NL") */
860 if (newline != (char *)0 && newline[0] == '\n' && !newline[1]) {
861 /* Newline, not linefeed. */
863 mode.c_oflag &= ~ONLCR;
865 mode.c_iflag &= ~ICRNL;
868 if (tgetflag("HD")) /* Half duplex. */
869 mode.c_lflag &= ~ECHO;
870 #endif /* __OBSOLETE__ */
872 /* test used to be tgetflag("pt") */
873 if (has_hardware_tabs) /* Print tabs. */
874 mode.c_oflag &= ~OXTABS;
876 mode.c_lflag |= (ECHOE | ECHOK);
880 /* Output startup string. */
888 if (pad_char != (char *)0) /* Get/set pad character. */
890 #endif /* OBSOLETE */
893 if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
894 oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
895 tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode);
901 if ((p = reset_1string) != 0) {
905 if ((p = reset_2string) != 0) {
909 /* What about rf, rs3, as per terminfo man page? */
910 /* also might be nice to send rmacs, rmul, rmm */
911 if ((p = reset_file) != 0
912 || (p = init_file) != 0) {
919 (void)putc('\r', stderr);
920 (void)fflush(stderr);
921 (void)napms(1000); /* Settle the terminal. */
926 * Set the hardware tabs on the terminal, using the ct (clear all tabs),
927 * st (set one tab) and ch (horizontal cursor addressing) capabilities.
928 * This is done before if and is, so they can patch in case we blow this.
929 * Return TRUE if we set any tab stops, FALSE if not.
934 if (set_tab && clear_all_tabs) {
937 (void)putc('\r', stderr); /* Force to left margin. */
938 tputs(clear_all_tabs, 0, outc);
940 for (c = 8; c < tcolumns; c += 8) {
941 /* Get to the right column. In BSD tset, this
942 * used to try a bunch of half-clever things
943 * with cup and hpa, for an average saving of
944 * somewhat less than two character times per
945 * tab stop, less that .01 sec at 2400cps. We
946 * lost all this cruft because it seemed to be
947 * introducing some odd bugs.
948 * ----------12345678----------- */
949 (void)fputs(" ", stderr);
950 tputs(set_tab, 0, outc);
958 /**************************************************************************
962 **************************************************************************/
965 * Tell the user if a control key has been changed from the default value.
968 report(const char *name, int which, u_int def)
974 newer = mode.c_cc[which];
975 older = oldmode.c_cc[which];
977 if (older == newer && older == def)
980 (void)fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to");
983 * Check 'delete' before 'backspace', since the key_backspace value
987 (void)fprintf(stderr, "delete.\n");
988 else if ((p = key_backspace) != 0
989 && newer == (u_int)p[0]
991 (void)fprintf(stderr, "backspace.\n");
992 else if (newer < 040) {
994 (void)fprintf(stderr, "control-%c (^%c).\n", newer, newer);
996 (void)fprintf(stderr, "%c.\n", newer);
1001 * Convert the obsolete argument forms into something that getopt can handle.
1002 * This means that -e, -i and -k get default arguments supplied for them.
1005 obsolete(char **argv)
1007 for (; *argv; ++argv) {
1008 char *parm = argv[0];
1010 if (parm[0] == '-' && parm[1] == '\0')
1012 argv[0] = strdup("-q");
1016 if ((parm[0] != '-')
1017 || (argv[1] && argv[1][0] != '-')
1018 || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
1019 || (parm[2] != '\0'))
1021 switch(argv[0][1]) {
1023 argv[0] = strdup("-e^H");
1026 argv[0] = strdup("-i^C");
1029 argv[0] = strdup("-k^U");
1036 usage(const char* pname)
1038 (void)fprintf(stderr,
1039 "usage: %s [-IQrs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n", pname);
1043 static char arg_to_char(void)
1045 return (optarg[0] == '^' && optarg[1] != '\0')
1046 ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
1051 main(int argc, char **argv)
1053 #if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
1056 int ch, noinit, noset, quiet, Sflag, sflag, showterm;
1061 if (tcgetattr(STDERR_FILENO, &mode) < 0)
1062 failed("standard error");
1065 ospeed = cfgetospeed(&mode);
1067 if (gtty(STDERR_FILENO, &mode) < 0)
1068 failed("standard error");
1071 ospeed = mode.sg_ospeed;
1074 if ((p = strrchr(*argv, '/')) != 0)
1078 if (!CaselessCmp(p, "reset")) {
1084 noinit = noset = quiet = Sflag = sflag = showterm = 0;
1085 while ((ch = getopt(argc, argv, "a:d:e:Ii:k:m:np:qQSrs")) != EOF) {
1087 case 'q': /* display term only */
1090 case 'a': /* OBSOLETE: map identifier to type */
1091 add_mapping("arpanet", optarg);
1093 case 'd': /* OBSOLETE: map identifier to type */
1094 add_mapping("dialup", optarg);
1096 case 'e': /* erase character */
1097 terasechar = arg_to_char();
1099 case 'I': /* no initialization strings */
1102 case 'i': /* interrupt character */
1103 intrchar = arg_to_char();
1105 case 'k': /* kill character */
1106 tkillchar = arg_to_char();
1108 case 'm': /* map identifier to type */
1109 add_mapping(0, optarg);
1111 case 'n': /* OBSOLETE: set new tty driver */
1113 case 'p': /* OBSOLETE: map identifier to type */
1114 add_mapping("plugboard", optarg);
1116 case 'Q': /* don't output control key settings */
1119 case 'S': /* OBSOLETE: output TERM & TERMCAP */
1122 case 'r': /* display term on stderr */
1125 case 's': /* output TERM set command */
1139 ttype = get_termcap_entry(*argv);
1145 #if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
1146 /* Set window size */
1147 (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
1148 if (win.ws_row == 0 && win.ws_col == 0 &&
1149 tlines > 0 && tcolumns > 0) {
1150 win.ws_row = tlines;
1151 win.ws_col = tcolumns;
1152 (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
1155 set_control_chars();
1161 /* Set the modes if they've changed. */
1162 if (memcmp(&mode, &oldmode, sizeof(mode)))
1164 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
1166 stty(STDERR_FILENO, &mode);
1170 /* Get the terminal name from the entry. */
1171 ttype = _nc_first_name(cur_term->type.term_names);
1174 (void)printf("%s\n", ttype);
1177 (void)fprintf(stderr, "Terminal type is %s.\n", ttype);
1179 * If erase, kill and interrupt characters could have been
1180 * modified and not -Q, display the changes.
1183 report("Erase", VERASE, CERASE);
1184 report("Kill", VKILL, CINTR);
1185 report("Interrupt", VINTR, CKILL);
1190 err("The -S option is not supported under terminfo.");
1194 * Figure out what shell we're using. A hack, we look for an
1195 * environmental variable SHELL ending in "csh".
1197 if ((p = getenv("SHELL")) != 0
1198 && !strcmp(p + strlen(p) - 3, "csh"))
1199 p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
1202 (void) printf(p, ttype);
1205 return EXIT_SUCCESS;
1208 /* tset.c ends here */