2 /***************************************************************************
4 ****************************************************************************
5 * ncurses is copyright (C) 1992-1995 *
7 * zmbenhal@netcom.com *
9 * esr@snark.thyrsus.com *
11 * Permission is hereby granted to reproduce and distribute ncurses *
12 * by any means and for any fee, whether alone or as part of a *
13 * larger distribution, in source or in binary form, PROVIDED *
14 * this notice is included with any such distribution, and is not *
15 * removed from any of its header files. Mention of ncurses in any *
16 * applications linked with it is highly appreciated. *
18 * ncurses comes AS IS with no warranty, implied or expressed. *
20 ***************************************************************************/
24 * tset.c - terminal initialization utility
26 * This code was mostly swiped from 4.4BSD tset, with some obsolescent
27 * cruft removed and substantial portions rewritten. A Regents of the
28 * University of California copyright applies to some portions of the
29 * code, and is reproduced below:
32 * Copyright (c) 1980, 1991, 1993
33 * The Regents of the University of California. All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 #define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */
65 #include <progs.priv.h>
73 #if HAVE_GETTTYNAM && HAVE_TTYENT_H
77 char *ttyname(int fd);
80 /* this is just to stifle a missing-prototype warning */
82 # include <sys/ioctl.h>
85 #if SYSTEM_LOOKS_LIKE_SCO
86 /* they neglected to define struct winsize in termios.h -- it's only
88 #include <sys/stream.h>
92 #include <curses.h> /* for bool typedef */
93 #include <dump_entry.h>
95 MODULE_ID("$Id: tset.c,v 0.23 1997/05/10 17:44:47 tom Exp $")
97 extern char **environ;
100 #define CTRL(x) ((x) & 0x1f)
102 const char *_nc_progname = "tset";
104 static TTY mode, oldmode;
106 static int terasechar; /* new erase character */
107 static int intrchar; /* new interrupt character */
108 static int isreset; /* invoked as reset */
109 static int tkillchar; /* new kill character */
110 static int tlines, tcolumns; /* window size */
112 #define LOWERCASE(c) ((isalpha(c) && isupper(c)) ? tolower(c) : (c))
115 CaselessCmp(const char *a, const char *b) /* strcasecmp isn't portable */
118 int cmp = LOWERCASE(*a) - LOWERCASE(*b);
123 return LOWERCASE(*a) - LOWERCASE(*b);
127 static char *strdup (char *s)
131 p = malloc(strlen(s)+1);
136 #endif /* not HAVE_STRDUP */
139 err(const char *fmt, ...)
143 (void)fprintf(stderr, "tset: ");
144 (void)vfprintf(stderr, fmt, ap);
146 (void)fprintf(stderr, "\n");
152 failed(const char *msg)
155 perror(strcat(strcpy(temp, "tset: "), msg));
163 register int fd, nr, nw;
166 if ((fd = open(file, O_RDONLY, 0)) < 0)
169 while ((nr = read(fd, buf, sizeof(buf))) > 0)
170 if ((nw = write(STDERR_FILENO, buf, (size_t)nr)) == -1)
171 failed("write to stderr");
180 return putc(c, stderr);
183 /* Prompt the user for a terminal type. */
185 askuser(const char *dflt)
187 static char answer[256];
190 /* We can get recalled; if so, don't continue uselessly. */
191 if (feof(stdin) || ferror(stdin)) {
192 (void)fprintf(stderr, "\n");
197 (void)fprintf(stderr, "Terminal type? [%s] ", dflt);
199 (void)fprintf(stderr, "Terminal type? ");
200 (void)fflush(stderr);
202 if (fgets(answer, sizeof(answer), stdin) == 0) {
204 (void)fprintf(stderr, "\n");
210 if ((p = strchr(answer, '\n')) != 0)
219 /**************************************************************************
221 * Mapping logic begins here
223 **************************************************************************/
225 /* Baud rate conditionals for mapping. */
234 struct map *next; /* Linked list of maps. */
235 const char *porttype; /* Port type, or "" for any. */
236 const char *type; /* Terminal type to select. */
237 int conditional; /* Baud rate conditionals bitmask. */
238 int speed; /* Baud rate to compare against. */
241 static MAP *cur, *maplist;
243 typedef struct speeds {
248 static const SPEEDS speeds[] = {
272 tbaudrate(char *rate)
277 /* The baudrate number can be preceded by a 'B', which is ignored. */
281 for (sp = speeds; sp->string; ++sp) {
282 if (!CaselessCmp(rate, sp->string)) {
288 err("unknown baud rate %s", rate);
294 * [port-type][test baudrate]:terminal-type
295 * The baud rate tests are: >, <, @, =, !
298 add_mapping(const char *port, char *arg)
306 mapp = malloc((u_int)sizeof(MAP));
307 if (copy == 0 || mapp == 0)
311 cur = maplist = mapp;
317 mapp->porttype = arg;
318 mapp->conditional = 0;
320 arg = strpbrk(arg, "><@=!:");
322 if (arg == 0) { /* [?]term */
323 mapp->type = mapp->porttype;
328 if (arg == mapp->porttype) /* [><@=! baud]:term */
329 termp = mapp->porttype = 0;
333 for (;; ++arg) /* Optional conditionals. */
336 if (mapp->conditional & GT)
338 mapp->conditional |= LT;
341 if (mapp->conditional & LT)
343 mapp->conditional |= GT;
346 case '=': /* Not documented. */
347 mapp->conditional |= EQ;
350 mapp->conditional |= NOT;
356 next: if (*arg == ':') {
357 if (mapp->conditional)
360 } else { /* Optional baudrate. */
361 arg = strchr(p = arg, ':');
365 mapp->speed = tbaudrate(p);
368 if (arg == (char *)0) /* Non-optional type. */
373 /* Terminate porttype, if specified. */
377 /* If a NOT conditional, reverse the test. */
378 if (mapp->conditional & NOT)
379 mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
381 /* If user specified a port with an option flag, set it. */
384 badmopt: err("illegal -m option format: %s", copy);
385 mapp->porttype = port;
389 (void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
390 (void)printf("type: %s\n", mapp->type);
391 (void)printf("conditional: ");
393 if (mapp->conditional & GT) {
397 if (mapp->conditional & EQ) {
398 (void)printf("%sEQ", p);
401 if (mapp->conditional & LT)
402 (void)printf("%sLT", p);
403 (void)printf("\nspeed: %d\n", mapp->speed);
408 * Return the type of terminal to use for a port of type 'type', as specified
409 * by the first applicable mapping in 'map'. If no mappings apply, return
413 mapped(const char *type)
418 for (mapp = maplist; mapp; mapp = mapp->next)
419 if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
420 switch (mapp->conditional) {
421 case 0: /* No test specified. */
425 match = (ospeed == mapp->speed);
428 match = (ospeed >= mapp->speed);
431 match = (ospeed > mapp->speed);
434 match = (ospeed <= mapp->speed);
437 match = (ospeed < mapp->speed);
445 /* No match found; return given type. */
449 /**************************************************************************
453 **************************************************************************/
456 * Figure out what kind of terminal we're dealing with, and then read in
460 get_termcap_entry(char *userarg)
475 /* Try the environment. */
476 if ((ttype = getenv("TERM")) != 0)
481 * We have the 4.3BSD library call getttynam(3); that means
482 * there's an /etc/ttys to look up device-to-type mappings in.
483 * Try ttyname(3); check for dialup or other mapping.
485 if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
486 if ((p = strrchr(ttypath, '/')) != 0)
490 if ((t = getttynam(p))) {
497 /* If still undefined, use "unknown". */
500 map: ttype = mapped(ttype);
503 * If not a path, remove TERMCAP from the environment so we get a
504 * real entry from /etc/termcap. This prevents us from being fooled
505 * by out of date stuff in the environment.
507 found: if ((p = getenv("TERMCAP")) != 0 && *p != '/') {
508 /* 'unsetenv("TERMCAP")' is not portable.
509 * The 'environ' array is better.
512 for (n = 0; environ[n] != 0; n++) {
513 if (!strncmp("TERMCAP=", environ[n], 8)) {
514 while ((environ[n] = environ[n+1]) != 0) {
523 * ttype now contains a pointer to the type of the terminal.
524 * If the first character is '?', ask the user.
527 if (ttype[1] != '\0')
528 ttype = askuser(ttype + 1);
532 /* Find the terminfo entry. If it doesn't exist, ask the user. */
533 while ((rval = setupterm(ttype, STDOUT_FILENO, &errret)) != OK) {
535 (void)fprintf(stderr, "tset: unknown terminal type %s\n",
540 (void)fprintf(stderr, "tset: can't initialize terminal\
541 type %s (error %d)\n", ttype, errret);
544 ttype = askuser(ttype);
547 tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */
552 /**************************************************************************
556 **************************************************************************/
558 /* some BSD systems have these built in, some systems are missing
559 * one or more definitions. The safest solution is to override.
570 /* control-character defaults */
571 #define CEOF CTRL('D')
572 #define CERASE CTRL('H')
573 #define CINTR 127 /* ^? */
574 #define CKILL CTRL('U')
577 #define CLNEXT CTRL('v')
581 #define CRPRNT CTRL('r')
583 #define CQUIT CTRL('\\')
584 #define CSTART CTRL('Q')
585 #define CSTOP CTRL('S')
586 #define CSUSP CTRL('Z')
588 #define CHK(val, dft) ((int)val <= 0 ? dft : val)
590 static bool set_tabs (void);
593 * Reset the terminal mode bits to a sensible state. Very useful after
594 * a child program dies in raw mode.
600 tcgetattr(STDERR_FILENO, &mode);
602 stty(STDERR_FILENO,&mode);
606 #if defined(VDISCARD) && defined(CDISCARD)
607 mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
609 mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
610 mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
611 #if defined(VFLUSH) && defined(CFLUSH)
612 mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
614 mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
615 mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
616 #if defined(VLNEXT) && defined(CLNEXT)
617 mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
619 mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
620 #if defined(VREPRINT) && defined(CRPRNT)
621 mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
623 #if defined(VSTART) && defined(CSTART)
624 mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
626 #if defined(VSTOP) && defined(CSTOP)
627 mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
629 #if defined(VSUSP) && defined(CSUSP)
630 mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
632 #if defined(VWERASE) && defined(CWERASE)
633 mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
636 mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
645 mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
671 | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY
675 mode.c_oflag |= (OPOST
681 mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
682 mode.c_cflag |= (CS8 | CREAD);
683 mode.c_lflag &= ~(ECHONL | NOFLSH
695 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
706 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
708 stty(STDERR_FILENO, &mode);
713 * Determine the erase, interrupt, and kill characters from the termcap
714 * entry and command line and update their values in 'mode'.
717 set_control_chars(void)
721 * 4.4BSD logic for setting erasechar, left here in case there is some
722 * necessary subtlety missed in the production code below that really
723 * needs to be added someday (in particular, I don't understand what
724 * the second if-statement involving the os flag is doing, and it makes
725 * my head hurt when I try and follow out all the combinations).
727 char *bp, *p, bs_char, buf[1024];
730 p = tgetstr("kb", &bp);
731 if (p == 0 || p[1] != '\0')
732 p = tgetstr("bc", &bp);
733 if (p != 0 && p[1] == '\0')
735 else if (tgetflag("bs"))
740 if (terasechar==0 && !tgetflag("os") && mode.c_cc[VERASE] != CERASE) {
741 if (tgetflag("bs") || bs_char != 0)
745 terasechar = (bs_char != 0) ? bs_char : CTRL('h');
747 /* the real erasechar logic used now */
750 if (key_backspace != (char *)0)
751 bs_char = key_backspace[0];
754 terasechar = (bs_char != 0) ? bs_char : CTRL('h');
755 #endif /* __OBSOLETE__ */
758 if (mode.c_cc[VERASE] == 0 || terasechar != 0)
759 mode.c_cc[VERASE] = terasechar ? terasechar : CERASE;
761 if (mode.c_cc[VINTR] == 0 || intrchar != 0)
762 mode.c_cc[VINTR] = intrchar ? intrchar : CINTR;
764 if (mode.c_cc[VKILL] == 0 || tkillchar != 0)
765 mode.c_cc[VKILL] = tkillchar ? tkillchar : CKILL;
770 * Set up various conversions in 'mode', including parity, tabs, returns,
771 * echo, and case, according to the termcap entry. If the program we're
772 * running was named with a leading upper-case character, map external
773 * uppercase to internal lowercase.
776 set_conversions(void)
780 * Conversion logic for some *really* ancient terminal glitches,
781 * not supported in terminfo. Left here for succeeding generations
784 if (tgetflag("UC")) {
786 mode.c_iflag |= IUCLC;
787 mode.c_oflag |= OLCUC;
789 } else if (tgetflag("LC")) {
791 mode.c_iflag &= ~IUCLC;
792 mode.c_oflag &= ~OLCUC;
795 mode.c_iflag &= ~(PARMRK | INPCK);
796 mode.c_lflag |= ICANON;
797 if (tgetflag("EP")) {
798 mode.c_cflag |= PARENB;
799 mode.c_cflag &= ~PARODD;
801 if (tgetflag("OP")) {
802 mode.c_cflag |= PARENB;
803 mode.c_cflag |= PARODD;
805 #endif /* __OBSOLETE__ */
809 mode.c_oflag |= ONLCR;
811 mode.c_iflag |= ICRNL;
812 mode.c_lflag |= ECHO;
814 mode.c_oflag |= OXTABS;
817 /* test used to be tgetflag("NL") */
818 if (newline != (char *)0 && newline[0] == '\n' && !newline[1]) {
819 /* Newline, not linefeed. */
821 mode.c_oflag &= ~ONLCR;
823 mode.c_iflag &= ~ICRNL;
826 if (tgetflag("HD")) /* Half duplex. */
827 mode.c_lflag &= ~ECHO;
828 #endif /* __OBSOLETE__ */
830 /* test used to be tgetflag("pt") */
831 if (has_hardware_tabs) /* Print tabs. */
832 mode.c_oflag &= ~OXTABS;
834 mode.c_lflag |= (ECHOE | ECHOK);
838 /* Output startup string. */
846 if (pad_char != (char *)0) /* Get/set pad character. */
848 #endif /* OBSOLETE */
851 if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
852 oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
853 tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode);
859 if ((p = reset_1string) != 0) {
863 if ((p = reset_2string) != 0) {
867 /* What about rf, rs3, as per terminfo man page? */
868 /* also might be nice to send rmacs, rmul, rmm */
869 if ((p = reset_file) != 0
870 || (p = init_file) != 0) {
877 (void)putc('\r', stderr);
878 (void)fflush(stderr);
879 (void)sleep(1); /* Settle the terminal. */
884 * Set the hardware tabs on the terminal, using the ct (clear all tabs),
885 * st (set one tab) and ch (horizontal cursor addressing) capabilities.
886 * This is done before if and is, so they can patch in case we blow this.
887 * Return TRUE if we set any tab stops, FALSE if not.
892 if (set_tab && clear_all_tabs) {
895 (void)putc('\r', stderr); /* Force to left margin. */
896 tputs(clear_all_tabs, 0, outc);
898 for (c = 8; c < tcolumns; c += 8) {
899 /* Get to the right column. In BSD tset, this
900 * used to try a bunch of half-clever things
901 * with cup and hpa, for an average saving of
902 * somewhat less than two character times per
903 * tab stop, less that .01 sec at 2400cps. We
904 * lost all this cruft because it seemed to be
905 * introducing some odd bugs.
906 * ----------12345678----------- */
907 (void)fputs(" ", stderr);
908 tputs(set_tab, 0, outc);
916 /**************************************************************************
920 **************************************************************************/
923 * Tell the user if a control key has been changed from the default value.
926 report(const char *name, int which, u_int def)
932 new = mode.c_cc[which];
933 old = oldmode.c_cc[which];
935 if (old == new && old == def)
938 (void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to");
940 if ((p = key_backspace) != 0
941 && new == (u_int)p[0]
943 (void)fprintf(stderr, "backspace.\n");
944 else if (new == 0177)
945 (void)fprintf(stderr, "delete.\n");
946 else if (new < 040) {
948 (void)fprintf(stderr, "control-%c (^%c).\n", new, new);
950 (void)fprintf(stderr, "%c.\n", new);
955 * Convert the obsolete argument forms into something that getopt can handle.
956 * This means that -e, -i and -k get default arguments supplied for them.
959 obsolete(char **argv)
961 for (; *argv; ++argv) {
962 char *parm = argv[0];
964 if (parm[0] == '-' && parm[1] == '\0')
966 argv[0] = strdup("-q");
971 || (argv[1] && argv[1][0] != '-')
972 || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
973 || (parm[2] != '\0'))
977 argv[0] = strdup("-e^H");
980 argv[0] = strdup("-i^C");
983 argv[0] = strdup("-k^U");
990 usage(const char* pname)
992 (void)fprintf(stderr,
993 "usage: %s [-IQrs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n", pname);
998 main(int argc, char **argv)
1003 int ch, noinit, noset, quiet, Sflag, sflag, showterm;
1008 if (tcgetattr(STDERR_FILENO, &mode) < 0)
1009 failed("standard error");
1012 ospeed = cfgetospeed(&mode);
1014 if (gtty(STDERR_FILENO, &mode) < 0)
1015 failed("standard error");
1018 ospeed = mode.sg_ospeed;
1021 if ((p = strrchr(*argv, '/')) != 0)
1025 if (!CaselessCmp(p, "reset")) {
1031 noinit = noset = quiet = Sflag = sflag = showterm = 0;
1032 while ((ch = getopt(argc, argv, "a:d:e:Ii:k:m:np:qQSrs")) != EOF) {
1034 case 'q': /* display term only */
1037 case 'a': /* OBSOLETE: map identifier to type */
1038 add_mapping("arpanet", optarg);
1040 case 'd': /* OBSOLETE: map identifier to type */
1041 add_mapping("dialup", optarg);
1043 case 'e': /* erase character */
1044 terasechar = optarg[0] == '^' && optarg[1] != '\0' ?
1045 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
1048 case 'I': /* no initialization strings */
1051 case 'i': /* interrupt character */
1052 intrchar = optarg[0] == '^' && optarg[1] != '\0' ?
1053 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
1056 case 'k': /* kill character */
1057 tkillchar = optarg[0] == '^' && optarg[1] != '\0' ?
1058 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
1061 case 'm': /* map identifier to type */
1062 add_mapping(0, optarg);
1064 case 'n': /* OBSOLETE: set new tty driver */
1066 case 'p': /* OBSOLETE: map identifier to type */
1067 add_mapping("plugboard", optarg);
1069 case 'Q': /* don't output control key settings */
1072 case 'S': /* OBSOLETE: output TERM & TERMCAP */
1075 case 'r': /* display term on stderr */
1078 case 's': /* output TERM set command */
1092 ttype = get_termcap_entry(*argv);
1099 /* Set window size */
1100 (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
1101 if (win.ws_row == 0 && win.ws_col == 0 &&
1102 tlines > 0 && tcolumns > 0) {
1103 win.ws_row = tlines;
1104 win.ws_col = tcolumns;
1105 (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
1108 set_control_chars();
1114 /* Set the modes if they've changed. */
1115 if (memcmp(&mode, &oldmode, sizeof(mode)))
1117 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
1119 stty(STDERR_FILENO, &mode);
1123 /* Get the terminal name from the entry. */
1124 ttype = _nc_first_name(cur_term->type.term_names);
1127 (void)printf("%s\n", ttype);
1130 (void)fprintf(stderr, "Terminal type is %s.\n", ttype);
1132 * If erase, kill and interrupt characters could have been
1133 * modified and not -Q, display the changes.
1136 report("Erase", VERASE, CERASE);
1137 report("Kill", VKILL, CINTR);
1138 report("Interrupt", VINTR, CKILL);
1143 err("The -S option is not supported under terminfo.");
1147 * Figure out what shell we're using. A hack, we look for an
1148 * environmental variable SHELL ending in "csh".
1150 if ((p = getenv("SHELL")) != 0
1151 && !strcmp(p + strlen(p) - 3, "csh"))
1152 p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
1155 (void) printf(p, ttype);
1158 return EXIT_SUCCESS;
1161 /* tset.c ends here */