break up into multiple modules
[unix-history] / usr / src / usr.bin / tset / tset.c
CommitLineData
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
9char 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
81ee81b5 15static char sccsid[] = "@(#)tset.c 5.18 (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
28void obsolete __P((char *[]));
29void report __P((char *, int, u_int));
30void usage __P((void));
973c9dcf 31
81ee81b5 32struct termios mode, oldmode;
973c9dcf 33
81ee81b5
KB
34int dosetenv; /* output TERMCAP strings */
35int erasechar; /* new erase character */
36int intrchar; /* new interrupt character */
37int isreset; /* invoked as reset */
38int killchar; /* new kill character */
39int noinit; /* don't output initialization string */
40int noset; /* only report term type */
41int quiet; /* don't display ctrl key settings */
6a19f69a 42
81ee81b5 43int lines, columns; /* window size */
973c9dcf 44
81ee81b5 45int
177ed6dd 46main(argc, argv)
81ee81b5
KB
47 int argc;
48 char *argv[];
177ed6dd 49{
973c9dcf 50#ifdef TIOCGWINSZ
81ee81b5 51 struct winsize win;
973c9dcf 52#endif
81ee81b5
KB
53 int ch, csh, usingupper;
54 char savech, *p, *t, *tcapbuf, *ttype;
973c9dcf 55
81ee81b5
KB
56 if (tcgetattr(STDERR_FILENO, &mode) < 0)
57 err("standard error: %s", strerror(errno));
973c9dcf 58
973c9dcf 59 oldmode = mode;
973c9dcf
MT
60 ospeed = cfgetospeed(&mode);
61
81ee81b5
KB
62 if (p = strrchr(*argv, '/'))
63 ++p;
6a19f69a 64 else
81ee81b5
KB
65 p = *argv;
66 usingupper = isupper(*p);
67 if (!strcasecmp(p, "reset")) {
68 isreset = 1;
973c9dcf 69 reset_mode();
6a19f69a 70 }
6a19f69a 71
81ee81b5
KB
72 obsolete(argv);
73 while ((ch = getopt(argc, argv, "-e:Ii:k:m:nQs")) != EOF) {
74 switch (ch) {
75 case '-':
76 noset = 1;
77 break;
78 case 'e': /* erase character */
79 erasechar = optarg[0] == '^' && optarg[1] != '\0' ?
80 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
81 optarg[0];
82 break;
83 case 'I': /* no initialization */
84 noinit = 1;
85 break;
86 case 'i': /* interrupt character */
87 intrchar = optarg[0] == '^' && optarg[1] != '\0' ?
88 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
89 optarg[0];
90 break;
91 case 'k': /* kill character */
92 killchar = optarg[0] == '^' && optarg[1] != '\0' ?
93 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
94 optarg[0];
95 break;
96 case 'm': /* map identifier to type */
97 add_mapping(optarg);
98 break;
99 case 'n': /* Undocumented (obsolete). */
100 break; /* set newtty driver */
101 case 'Q': /* be quiet */
102 quiet = 1;
103 break;
104 case 's': /* print commands to set environment */
105 dosetenv = 1;
106 break;
107 case '?':
108 default:
109 usage();
110 }
177ed6dd 111 }
81ee81b5
KB
112 argc -= optind;
113 argv += optind;
177ed6dd 114
81ee81b5 115 if (argc > 1)
973c9dcf 116 usage();
177ed6dd 117
81ee81b5 118 ttype = get_termcap_entry(*argv, &tcapbuf);
177ed6dd 119
81ee81b5 120 if (!noset) {
48e4fbf9
JB
121 columns = tgetnum("co");
122 lines = tgetnum("li");
123
973c9dcf 124#ifdef TIOCGWINSZ
48e4fbf9 125 /* Set window size */
81ee81b5 126 (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
0b1d4860
JB
127 if (win.ws_row == 0 && win.ws_col == 0 &&
128 lines > 0 && columns > 0) {
129 win.ws_row = lines;
130 win.ws_col = columns;
81ee81b5 131 (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
48e4fbf9 132 }
973c9dcf 133#endif
81ee81b5
KB
134 set_control_chars();
135 set_conversions(usingupper);
136
137 if (!noinit)
138 set_init();
139
140 /* Set the modes if they've changed. */
141 if (memcmp(&mode, &oldmode, sizeof(mode)))
142 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
143
144 /*
145 * If erase, kill and interrupt characters have potentially
146 * been modified and not -Q, display the changes.
147 */
148 if (!quiet) {
149 report("Erase", VERASE, CERASE);
150 report("Kill", VKILL, CKILL);
151 report("Interrupt", VINTR, CINTR);
177ed6dd
BJ
152 }
153 }
154
81ee81b5
KB
155 if (!dosetenv && !noset)
156 exit(0);
157
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
81ee81b5
KB
176 if (noset) {
177 (void)printf("%s\n", ttype);
178 exit(0);
973c9dcf
MT
179 }
180
81ee81b5
KB
181 /*
182 * Figure out what shell we're using. A hack, we look for a $SHELL
183 * ending in "csh".
184 */
185 csh = (p = getenv("SHELL")) && !strcmp(p + strlen(p) - 3, "csh");
186 if (csh)
187 (void)printf("set noglob;\nsetenv TERM %s;\nsetenv TERMCAP '",
188 ttype);
973c9dcf 189 else
81ee81b5
KB
190 (void)printf("TERM=%s;\nTERMCAP='", ttype);
191 wrtermcap(tcapbuf);
192 if (csh)
193 (void)printf("';\nunset noglob;\n");
973c9dcf 194 else
81ee81b5
KB
195 (void)printf("';\nexport TERMCAP TERM;\n");
196 exit(0);
177ed6dd
BJ
197}
198
6a19f69a 199/*
81ee81b5 200 * Tell the user if a control key has been changed from the default value.
6a19f69a 201 */
010bfa9a 202void
81ee81b5
KB
203report(name, which, def)
204 char *name;
205 int which;
206 u_int def;
6a19f69a 207{
81ee81b5
KB
208 u_int old, new;
209 char *bp, buf[1024];
6a19f69a 210
81ee81b5
KB
211 new = mode.c_cc[which];
212 old = oldmode.c_cc[which];
973c9dcf 213
81ee81b5 214 if (old == new && old == def)
6a19f69a 215 return;
177ed6dd 216
81ee81b5
KB
217 (void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to");
218
219 bp = buf;
220 if (tgetstr("kb", &bp) && new == buf[0] && buf[1] == '\0')
221 (void)fprintf(stderr, "backspace.\n");
222 else if (new == 0177)
223 (void)fprintf(stderr, "delete.\n");
224 else if (new < 040) {
225 new ^= 0100;
226 (void)fprintf(stderr, "control-%c (^%c).\n", new, new);
227 } else
228 (void)fprintf(stderr, "%c.\n", new);
177ed6dd 229}
177ed6dd 230
81ee81b5
KB
231/*
232 * Convert the obsolete argument form into something that getopt can handle.
233 * This means that -e, -i and -k get default arguments supplied for them.
234 */
973c9dcf 235void
81ee81b5
KB
236obsolete(argv)
237 char *argv[];
177ed6dd 238{
81ee81b5
KB
239 for (; *argv; ++argv) {
240 if (argv[0][0] != '-' || argv[1] && argv[1][0] != '-' ||
241 argv[0][1] != 'e' && argv[0][1] != 'i' &&
242 argv[0][1] != 'k' || argv[0][2] != '\0')
6a19f69a 243 continue;
81ee81b5
KB
244 switch(argv[0][1]) {
245 case 'e':
246 argv[0] = "-e^H";
247 break;
248 case 'i':
249 argv[0] = "-i^C";
250 break;
251 case 'k':
252 argv[0] = "-k^U";
6a19f69a 253 break;
177ed6dd 254 }
177ed6dd 255 }
177ed6dd 256}
81ee81b5 257
973c9dcf
MT
258void
259usage()
177ed6dd 260{
81ee81b5
KB
261 (void)fprintf(stderr,
262"usage: tset [-IQs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n");
177ed6dd
BJ
263 exit(1);
264}