1 /* $NetBSD: tset.c,v 1.20 2011/09/06 18:34:12 joerg Exp $ */
2
3 /*-
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993\
34 The Regents of the University of California. All rights reserved.");
35 __RCSID("$NetBSD: tset.c,v 1.20 2011/09/06 18:34:12 joerg Exp $");
36
37 #include <sys/types.h>
38 #include <sys/ioctl.h>
39 #include <ctype.h>
40 #include <err.h>
41 #include <errno.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <term.h>
46 #include <termios.h>
47 #include <unistd.h>
48 #include "extern.h"
49
50 static void obsolete(char *[]);
51 static void report(const char *, int, u_int);
52 __dead static void usage(void);
53
54 struct termios mode, oldmode;
55
56 int isreset; /* invoked as reset */
57 int nlines, ncolumns; /* window size */
58
59 int
main(int argc,char * argv[])60 main(int argc, char *argv[])
61 {
62 #ifdef TIOCGWINSZ
63 struct winsize win;
64 #endif
65 int ch, noinit, noset, quiet, sflag, showterm;
66 int erasechar = 0, intrchar = 0, killchar = 0;
67 int usingupper;
68 char *p;
69 const char *k1, *k2;
70 const char *ttype;
71
72 if (tcgetattr(STDERR_FILENO, &mode) < 0)
73 err(1, "standard error");
74
75 oldmode = mode;
76 ospeed = cfgetospeed(&mode);
77
78 if ((p = strrchr(*argv, '/')) != NULL)
79 ++p;
80 else
81 p = *argv;
82 usingupper = isupper((unsigned char)*p);
83 if (!strcasecmp(p, "reset")) {
84 isreset = 1;
85 reset_mode();
86 }
87
88 obsolete(argv);
89 noinit = noset = quiet = sflag = showterm = 0;
90 while ((ch = getopt(argc, argv, "-a:d:e:EIi:k:m:np:QSrs")) != -1) {
91 switch (ch) {
92 case '-': /* display term only */
93 noset = 1;
94 break;
95 case 'a': /* OBSOLETE: map identifier to type */
96 add_mapping("arpanet", optarg);
97 break;
98 case 'd': /* OBSOLETE: map identifier to type */
99 add_mapping("dialup", optarg);
100 break;
101 case 'e': /* erase character */
102 erasechar = optarg[0] == '^' && optarg[1] != '\0' ?
103 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
104 optarg[0];
105 break;
106 case 'E': /* -E does not make sense for terminfo
107 should this be noisy? */
108 break;
109 case 'I': /* no initialization strings */
110 noinit = 1;
111 break;
112 case 'i': /* interrupt character */
113 intrchar = optarg[0] == '^' && optarg[1] != '\0' ?
114 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
115 optarg[0];
116 break;
117 case 'k': /* kill character */
118 killchar = optarg[0] == '^' && optarg[1] != '\0' ?
119 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
120 optarg[0];
121 break;
122 case 'm': /* map identifier to type */
123 add_mapping(NULL, optarg);
124 break;
125 case 'n': /* OBSOLETE: set new tty driver */
126 break;
127 case 'p': /* OBSOLETE: map identifier to type */
128 add_mapping("plugboard", optarg);
129 break;
130 case 'Q': /* don't output control key settings */
131 quiet = 1;
132 break;
133 case 'S': /* -S does not make sense for terminfo
134 should this be noisy? */
135 break;
136 case 'r': /* display term on stderr */
137 showterm = 1;
138 break;
139 case 's': /* output TERM string */
140 sflag = 1;
141 break;
142 case '?':
143 default:
144 usage();
145 }
146 }
147 argc -= optind;
148 argv += optind;
149
150 if (argc > 1)
151 usage();
152
153 ttype = get_terminfo_entry(*argv);
154
155 if (!noset) {
156 ncolumns = columns;
157 nlines = lines;
158
159 #ifdef TIOCGWINSZ
160 /* Set window size */
161 (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
162 if (win.ws_row > 0 && win.ws_col > 0) {
163 nlines = win.ws_row;
164 ncolumns = win.ws_col;
165 } else if (win.ws_row == 0 && win.ws_col == 0 &&
166 nlines > 0 && columns > 0) {
167 win.ws_row = nlines;
168 win.ws_col = ncolumns;
169 (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
170 }
171 #endif
172 set_control_chars(erasechar, intrchar, killchar);
173 set_conversions(usingupper);
174
175 if (!noinit)
176 set_init();
177
178 /* Set the modes if they've changed. */
179 if (memcmp(&mode, &oldmode, sizeof(mode)))
180 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
181 }
182
183 if (noset)
184 (void)printf("%s\n", ttype);
185 else {
186 if (showterm)
187 (void)fprintf(stderr, "Terminal type is %s.\n", ttype);
188 /*
189 * If erase, kill and interrupt characters could have been
190 * modified and not -Q, display the changes.
191 */
192 if (!quiet) {
193 report("Erase", VERASE, CERASE);
194 report("Kill", VKILL, CKILL);
195 report("Interrupt", VINTR, CINTR);
196 }
197 }
198
199 if (sflag) {
200 /*
201 * Figure out what shell we're using. A hack, we look for an
202 * environmental variable SHELL ending in "csh".
203 */
204 if ((p = getenv("SHELL")) &&
205 !strcmp(p + strlen(p) - 3, "csh")) {
206 k1 = "set noglob;\nsetenv TERM ";
207 k2 = ";\nunset noglob;\n";
208 } else {
209 k1 = "TERM=";
210 k2 = ";\nexport TERM;\n";
211 }
212 (void)printf("%s%s%s", k1, ttype, k2);
213 }
214
215 exit(0);
216 }
217
218 /*
219 * Tell the user if a control key has been changed from the default value.
220 */
221 static void
report(const char * name,int which,u_int def)222 report(const char *name, int which, u_int def)
223 {
224 u_int old, new;
225
226 new = mode.c_cc[which];
227 old = oldmode.c_cc[which];
228
229 if (old == new && old == def)
230 return;
231
232 (void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to");
233
234 if (key_backspace != NULL &&
235 new == (unsigned int)key_backspace[0] &&
236 key_backspace[1] == '\0')
237 (void)fprintf(stderr, "backspace.\n");
238 else if (new == 0177)
239 (void)fprintf(stderr, "delete.\n");
240 else if (new < 040) {
241 new ^= 0100;
242 (void)fprintf(stderr, "control-%c (^%c).\n", new, new);
243 } else if (new == _POSIX_VDISABLE)
244 (void)fprintf(stderr, "<undef>.\n");
245 else
246 (void)fprintf(stderr, "%c.\n", new);
247 }
248
249 /*
250 * Convert the obsolete argument form into something that getopt can handle.
251 * This means that -e, -i and -k get default arguments supplied for them.
252 */
253 void
obsolete(char * argv[])254 obsolete(char *argv[])
255 {
256 static char earg[5] = { '-', 'e', '^', 'H', '\0' };
257 static char iarg[5] = { '-', 'i', '^', 'C', '\0' };
258 static char karg[5] = { '-', 'k', '^', 'U', '\0' };
259
260 for (; *argv; ++argv) {
261 if (argv[0][0] != '-' || (argv[1] && argv[1][0] != '-') ||
262 (argv[0][1] != 'e' && argv[0][1] != 'i' &&
263 argv[0][1] != 'k') || argv[0][2] != '\0')
264 continue;
265 switch(argv[0][1]) {
266 case 'e':
267 argv[0] = earg;
268 break;
269 case 'i':
270 argv[0] = iarg;
271 break;
272 case 'k':
273 argv[0] = karg;
274 break;
275 }
276 }
277 }
278
279 static void
usage(void)280 usage(void)
281 {
282 (void)fprintf(stderr,
283 "usage: %s [-EIQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n",
284 getprogname());
285 exit(1);
286 }
287