1 /*-
2 * Copyright (c) 1980, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1980, 1991, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)tset.c 8.1 (Berkeley) 06/09/93";
16 #endif /* not lint */
17
18 #include <sys/types.h>
19 #include <sys/ioctl.h>
20 #include <termios.h>
21 #include <errno.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include "extern.h"
28
29 void obsolete __P((char *[]));
30 void report __P((char *, int, u_int));
31 void usage __P((void));
32
33 struct termios mode, oldmode;
34
35 int erasechar; /* new erase character */
36 int intrchar; /* new interrupt character */
37 int isreset; /* invoked as reset */
38 int killchar; /* new kill character */
39 int lines, columns; /* window size */
40
41 int
main(argc,argv)42 main(argc, argv)
43 int argc;
44 char *argv[];
45 {
46 #ifdef TIOCGWINSZ
47 struct winsize win;
48 #endif
49 int ch, noinit, noset, quiet, Sflag, sflag, showterm, usingupper;
50 char savech, *p, *t, *tcapbuf, *ttype;
51
52 if (tcgetattr(STDERR_FILENO, &mode) < 0)
53 err("standard error: %s", strerror(errno));
54
55 oldmode = mode;
56 ospeed = cfgetospeed(&mode);
57
58 if (p = strrchr(*argv, '/'))
59 ++p;
60 else
61 p = *argv;
62 usingupper = isupper(*p);
63 if (!strcasecmp(p, "reset")) {
64 isreset = 1;
65 reset_mode();
66 }
67
68 obsolete(argv);
69 noinit = noset = quiet = Sflag = sflag = showterm = 0;
70 while ((ch = getopt(argc, argv, "-a:d:e:Ii:k:m:np:QSrs")) != EOF) {
71 switch (ch) {
72 case '-': /* display term only */
73 noset = 1;
74 break;
75 case 'a': /* OBSOLETE: map identifier to type */
76 add_mapping("arpanet", optarg);
77 break;
78 case 'd': /* OBSOLETE: map identifier to type */
79 add_mapping("dialup", optarg);
80 break;
81 case 'e': /* erase character */
82 erasechar = optarg[0] == '^' && optarg[1] != '\0' ?
83 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
84 optarg[0];
85 break;
86 case 'I': /* no initialization strings */
87 noinit = 1;
88 break;
89 case 'i': /* interrupt character */
90 intrchar = optarg[0] == '^' && optarg[1] != '\0' ?
91 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
92 optarg[0];
93 break;
94 case 'k': /* kill character */
95 killchar = optarg[0] == '^' && optarg[1] != '\0' ?
96 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
97 optarg[0];
98 break;
99 case 'm': /* map identifier to type */
100 add_mapping(NULL, optarg);
101 break;
102 case 'n': /* OBSOLETE: set new tty driver */
103 break;
104 case 'p': /* OBSOLETE: map identifier to type */
105 add_mapping("plugboard", optarg);
106 break;
107 case 'Q': /* don't output control key settings */
108 quiet = 1;
109 break;
110 case 'S': /* output TERM/TERMCAP strings */
111 Sflag = 1;
112 break;
113 case 'r': /* display term on stderr */
114 showterm = 1;
115 break;
116 case 's': /* output TERM/TERMCAP strings */
117 sflag = 1;
118 break;
119 case '?':
120 default:
121 usage();
122 }
123 }
124 argc -= optind;
125 argv += optind;
126
127 if (argc > 1)
128 usage();
129
130 ttype = get_termcap_entry(*argv, &tcapbuf);
131
132 if (!noset) {
133 columns = tgetnum("co");
134 lines = tgetnum("li");
135
136 #ifdef TIOCGWINSZ
137 /* Set window size */
138 (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
139 if (win.ws_row == 0 && win.ws_col == 0 &&
140 lines > 0 && columns > 0) {
141 win.ws_row = lines;
142 win.ws_col = columns;
143 (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
144 }
145 #endif
146 set_control_chars();
147 set_conversions(usingupper);
148
149 if (!noinit)
150 set_init();
151
152 /* Set the modes if they've changed. */
153 if (memcmp(&mode, &oldmode, sizeof(mode)))
154 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
155 }
156
157 /* Get the terminal name from the entry. */
158 p = tcapbuf;
159 if (p != NULL && *p != ':') {
160 t = p;
161 if (p = strpbrk(p, "|:")) {
162 savech = *p;
163 *p = '\0';
164 if ((ttype = strdup(t)) == NULL)
165 err("%s", strerror(errno));
166 *p = savech;
167 }
168 }
169
170 if (noset)
171 (void)printf("%s\n", ttype);
172 else {
173 if (showterm)
174 (void)fprintf(stderr, "Terminal type is %s.\n", ttype);
175 /*
176 * If erase, kill and interrupt characters could have been
177 * modified and not -Q, display the changes.
178 */
179 if (!quiet) {
180 report("Erase", VERASE, CERASE);
181 report("Kill", VKILL, CKILL);
182 report("Interrupt", VINTR, CINTR);
183 }
184 }
185
186 if (Sflag) {
187 (void)printf("%s ", ttype);
188 wrtermcap(tcapbuf);
189 }
190
191 if (sflag) {
192 /*
193 * Figure out what shell we're using. A hack, we look for an
194 * environmental variable SHELL ending in "csh".
195 */
196 if ((p = getenv("SHELL")) &&
197 !strcmp(p + strlen(p) - 3, "csh")) {
198 p = "set noglob;\nsetenv TERM %s;\nsetenv TERMCAP '";
199 t = "';\nunset noglob;\n";
200 } else {
201 p = "TERM=%s;\nTERMCAP='";
202 t = "';\nexport TERMCAP TERM;\n";
203 }
204 (void)printf(p, ttype);
205 wrtermcap(tcapbuf);
206 (void)printf(t);
207 }
208
209 exit(0);
210 }
211
212 /*
213 * Tell the user if a control key has been changed from the default value.
214 */
215 void
report(name,which,def)216 report(name, which, def)
217 char *name;
218 int which;
219 u_int def;
220 {
221 u_int old, new;
222 char *bp, buf[1024];
223
224 new = mode.c_cc[which];
225 old = oldmode.c_cc[which];
226
227 if (old == new && old == def)
228 return;
229
230 (void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to");
231
232 bp = buf;
233 if (tgetstr("kb", &bp) && new == buf[0] && buf[1] == '\0')
234 (void)fprintf(stderr, "backspace.\n");
235 else if (new == 0177)
236 (void)fprintf(stderr, "delete.\n");
237 else if (new < 040) {
238 new ^= 0100;
239 (void)fprintf(stderr, "control-%c (^%c).\n", new, new);
240 } else
241 (void)fprintf(stderr, "%c.\n", new);
242 }
243
244 /*
245 * Convert the obsolete argument form into something that getopt can handle.
246 * This means that -e, -i and -k get default arguments supplied for them.
247 */
248 void
obsolete(argv)249 obsolete(argv)
250 char *argv[];
251 {
252 for (; *argv; ++argv) {
253 if (argv[0][0] != '-' || argv[1] && argv[1][0] != '-' ||
254 argv[0][1] != 'e' && argv[0][1] != 'i' &&
255 argv[0][1] != 'k' || argv[0][2] != '\0')
256 continue;
257 switch(argv[0][1]) {
258 case 'e':
259 argv[0] = "-e^H";
260 break;
261 case 'i':
262 argv[0] = "-i^C";
263 break;
264 case 'k':
265 argv[0] = "-k^U";
266 break;
267 }
268 }
269 }
270
271 void
usage()272 usage()
273 {
274 (void)fprintf(stderr,
275 "usage: tset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n");
276 exit(1);
277 }
278