xref: /original-bsd/usr.bin/tset/tset.c (revision 3705696b)
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
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
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
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
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