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 |
277ca15f | 15 | static char sccsid[] = "@(#)tset.c 5.22 (Berkeley) %G%"; |
3e928ffa | 16 | #endif /* not lint */ |
6a19f69a | 17 | |
973c9dcf | 18 | #include <sys/types.h> |
c2ee5c3e | 19 | #include <sys/ioctl.h> |
973c9dcf | 20 | #include <termios.h> |
81ee81b5 | 21 | #include <errno.h> |
973c9dcf MT |
22 | #include <unistd.h> |
23 | #include <stdlib.h> | |
81ee81b5 | 24 | #include <stdio.h> |
973c9dcf MT |
25 | #include <ctype.h> |
26 | #include <string.h> | |
81ee81b5 | 27 | #include "extern.h" |
973c9dcf | 28 | |
81ee81b5 KB |
29 | void obsolete __P((char *[])); |
30 | void report __P((char *, int, u_int)); | |
31 | void usage __P((void)); | |
973c9dcf | 32 | |
81ee81b5 | 33 | struct termios mode, oldmode; |
973c9dcf | 34 | |
81ee81b5 KB |
35 | int erasechar; /* new erase character */ |
36 | int intrchar; /* new interrupt character */ | |
37 | int isreset; /* invoked as reset */ | |
38 | int killchar; /* new kill character */ | |
81ee81b5 | 39 | int lines, columns; /* window size */ |
973c9dcf | 40 | |
81ee81b5 | 41 | int |
177ed6dd | 42 | main(argc, argv) |
81ee81b5 KB |
43 | int argc; |
44 | char *argv[]; | |
177ed6dd | 45 | { |
973c9dcf | 46 | #ifdef TIOCGWINSZ |
81ee81b5 | 47 | struct winsize win; |
973c9dcf | 48 | #endif |
f666f4df | 49 | int ch, noinit, noset, quiet, Sflag, sflag, showterm, usingupper; |
81ee81b5 | 50 | char savech, *p, *t, *tcapbuf, *ttype; |
973c9dcf | 51 | |
81ee81b5 KB |
52 | if (tcgetattr(STDERR_FILENO, &mode) < 0) |
53 | err("standard error: %s", strerror(errno)); | |
973c9dcf | 54 | |
973c9dcf | 55 | oldmode = mode; |
973c9dcf MT |
56 | ospeed = cfgetospeed(&mode); |
57 | ||
81ee81b5 KB |
58 | if (p = strrchr(*argv, '/')) |
59 | ++p; | |
6a19f69a | 60 | else |
81ee81b5 KB |
61 | p = *argv; |
62 | usingupper = isupper(*p); | |
63 | if (!strcasecmp(p, "reset")) { | |
64 | isreset = 1; | |
973c9dcf | 65 | reset_mode(); |
6a19f69a | 66 | } |
6a19f69a | 67 | |
81ee81b5 | 68 | obsolete(argv); |
f666f4df KB |
69 | noinit = noset = quiet = Sflag = sflag = showterm = 0; |
70 | while ((ch = getopt(argc, argv, "-a:d:e:Ii:k:m:np:QSrs")) != EOF) { | |
81ee81b5 | 71 | switch (ch) { |
f666f4df | 72 | case '-': /* display term only */ |
81ee81b5 KB |
73 | noset = 1; |
74 | break; | |
c8d0758d KB |
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; | |
81ee81b5 KB |
81 | case 'e': /* erase character */ |
82 | erasechar = optarg[0] == '^' && optarg[1] != '\0' ? | |
83 | optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : | |
84 | optarg[0]; | |
85 | break; | |
f666f4df | 86 | case 'I': /* no initialization strings */ |
81ee81b5 KB |
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 */ | |
c8d0758d KB |
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); | |
81ee81b5 | 106 | break; |
f666f4df | 107 | case 'Q': /* don't output control key settings */ |
81ee81b5 KB |
108 | quiet = 1; |
109 | break; | |
f666f4df KB |
110 | case 'S': /* output TERM/TERMCAP strings */ |
111 | Sflag = 1; | |
112 | break; | |
c8d0758d KB |
113 | case 'r': /* display term on stderr */ |
114 | showterm = 1; | |
115 | break; | |
f666f4df KB |
116 | case 's': /* output TERM/TERMCAP strings */ |
117 | sflag = 1; | |
81ee81b5 KB |
118 | break; |
119 | case '?': | |
120 | default: | |
121 | usage(); | |
122 | } | |
177ed6dd | 123 | } |
81ee81b5 KB |
124 | argc -= optind; |
125 | argv += optind; | |
177ed6dd | 126 | |
81ee81b5 | 127 | if (argc > 1) |
973c9dcf | 128 | usage(); |
177ed6dd | 129 | |
81ee81b5 | 130 | ttype = get_termcap_entry(*argv, &tcapbuf); |
177ed6dd | 131 | |
81ee81b5 | 132 | if (!noset) { |
48e4fbf9 JB |
133 | columns = tgetnum("co"); |
134 | lines = tgetnum("li"); | |
135 | ||
973c9dcf | 136 | #ifdef TIOCGWINSZ |
48e4fbf9 | 137 | /* Set window size */ |
81ee81b5 | 138 | (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win); |
0b1d4860 JB |
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; | |
81ee81b5 | 143 | (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win); |
48e4fbf9 | 144 | } |
973c9dcf | 145 | #endif |
81ee81b5 KB |
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); | |
177ed6dd BJ |
155 | } |
156 | ||
277ca15f EA |
157 | /* Get the terminal name from the entry. */ |
158 | p = tcapbuf; | |
159 | if (p != NULL && *p != ':') { | |
160 | t = p; | |
81ee81b5 KB |
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; | |
177ed6dd BJ |
167 | } |
168 | } | |
169 | ||
c8d0758d | 170 | if (noset) |
81ee81b5 | 171 | (void)printf("%s\n", ttype); |
c8d0758d KB |
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 | } | |
973c9dcf MT |
184 | } |
185 | ||
f666f4df KB |
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 | } | |
c8d0758d | 208 | |
81ee81b5 | 209 | exit(0); |
177ed6dd BJ |
210 | } |
211 | ||
6a19f69a | 212 | /* |
81ee81b5 | 213 | * Tell the user if a control key has been changed from the default value. |
6a19f69a | 214 | */ |
010bfa9a | 215 | void |
81ee81b5 KB |
216 | report(name, which, def) |
217 | char *name; | |
218 | int which; | |
219 | u_int def; | |
6a19f69a | 220 | { |
81ee81b5 KB |
221 | u_int old, new; |
222 | char *bp, buf[1024]; | |
6a19f69a | 223 | |
81ee81b5 KB |
224 | new = mode.c_cc[which]; |
225 | old = oldmode.c_cc[which]; | |
973c9dcf | 226 | |
81ee81b5 | 227 | if (old == new && old == def) |
6a19f69a | 228 | return; |
177ed6dd | 229 | |
81ee81b5 KB |
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); | |
177ed6dd | 242 | } |
177ed6dd | 243 | |
81ee81b5 KB |
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 | */ | |
973c9dcf | 248 | void |
81ee81b5 KB |
249 | obsolete(argv) |
250 | char *argv[]; | |
177ed6dd | 251 | { |
81ee81b5 KB |
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') | |
6a19f69a | 256 | continue; |
81ee81b5 KB |
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"; | |
6a19f69a | 266 | break; |
177ed6dd | 267 | } |
177ed6dd | 268 | } |
177ed6dd | 269 | } |
c8d0758d | 270 | |
973c9dcf MT |
271 | void |
272 | usage() | |
177ed6dd | 273 | { |
81ee81b5 | 274 | (void)fprintf(stderr, |
f666f4df | 275 | "usage: tset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n"); |
177ed6dd BJ |
276 | exit(1); |
277 | } |