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