tset.c revision 24360
167754Smsmith/*-
267754Smsmith * Copyright (c) 1980, 1991, 1993
377424Smsmith *	The Regents of the University of California.  All rights reserved.
467754Smsmith *
567754Smsmith * Redistribution and use in source and binary forms, with or without
667754Smsmith * modification, are permitted provided that the following conditions
7217365Sjkim * are met:
8217365Sjkim * 1. Redistributions of source code must retain the above copyright
970243Smsmith *    notice, this list of conditions and the following disclaimer.
1067754Smsmith * 2. Redistributions in binary form must reproduce the above copyright
11217365Sjkim *    notice, this list of conditions and the following disclaimer in the
12217365Sjkim *    documentation and/or other materials provided with the distribution.
13217365Sjkim * 3. All advertising materials mentioning features or use of this software
14217365Sjkim *    must display the following acknowledgement:
15217365Sjkim *	This product includes software developed by the University of
16217365Sjkim *	California, Berkeley and its contributors.
17217365Sjkim * 4. Neither the name of the University nor the names of its contributors
18217365Sjkim *    may be used to endorse or promote products derived from this software
19217365Sjkim *    without specific prior written permission.
20217365Sjkim *
21217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22217365Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23217365Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24217365Sjkim * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2567754Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2967754Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30217365Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31217365Sjkim * SUCH DAMAGE.
32217365Sjkim */
33217365Sjkim
34217365Sjkim#ifndef lint
35217365Sjkimstatic char copyright[] =
36217365Sjkim"@(#) Copyright (c) 1980, 1991, 1993\n\
37217365Sjkim	The Regents of the University of California.  All rights reserved.\n";
38217365Sjkim#endif /* not lint */
39217365Sjkim
40217365Sjkim#ifndef lint
41217365Sjkimstatic char sccsid[] = "@(#)tset.c	8.1 (Berkeley) 6/9/93";
42217365Sjkim#endif /* not lint */
4367754Smsmith
4467754Smsmith#include <sys/types.h>
4567754Smsmith#include <sys/ioctl.h>
4667754Smsmith#include <termios.h>
47193341Sjkim#include <errno.h>
48193341Sjkim#include <unistd.h>
49193341Sjkim#include <stdlib.h>
50193341Sjkim#include <stdio.h>
5167754Smsmith#include <ctype.h>
5277424Smsmith#include <string.h>
5391116Smsmith#include "extern.h"
5467754Smsmith
55151937Sjkimvoid	obsolete __P((char *[]));
5667754Smsmithvoid	report __P((char *, int, u_int));
57151937Sjkimvoid	usage __P((void));
58151937Sjkim
59151937Sjkimstruct termios mode, oldmode;
60151937Sjkim
61151937Sjkimint	erasechar;		/* new erase character */
62151937Sjkimint	intrchar;		/* new interrupt character */
63151937Sjkimint	isreset;		/* invoked as reset */
64151937Sjkimint	killchar;		/* new kill character */
65151937Sjkimint	lines, columns;		/* window size */
66151937Sjkimspeed_t	Ospeed;
67151937Sjkim
68151937Sjkimint
69151937Sjkimmain(argc, argv)
70151937Sjkim	int argc;
71151937Sjkim	char *argv[];
72151937Sjkim{
73167802Sjkim#ifdef TIOCGWINSZ
74167802Sjkim	struct winsize win;
75167802Sjkim#endif
76167802Sjkim	int ch, noinit, noset, quiet, Sflag, sflag, showterm, usingupper;
77167802Sjkim	char savech, *p, *t, *tcapbuf, *ttype;
78167802Sjkim
79167802Sjkim	if (tcgetattr(STDERR_FILENO, &mode) < 0)
80167802Sjkim		err("standard error: %s", strerror(errno));
81167802Sjkim
82167802Sjkim	oldmode = mode;
83167802Sjkim	Ospeed = cfgetospeed(&mode);
84167802Sjkim
85167802Sjkim	if (p = strrchr(*argv, '/'))
86167802Sjkim		++p;
8767754Smsmith	else
8867754Smsmith		p = *argv;
89167802Sjkim	usingupper = isupper(*p);
90167802Sjkim	if (!strcasecmp(p, "reset")) {
91167802Sjkim		isreset = 1;
92167802Sjkim		reset_mode();
93167802Sjkim	}
94167802Sjkim
95167802Sjkim	obsolete(argv);
96167802Sjkim	noinit = noset = quiet = Sflag = sflag = showterm = 0;
97167802Sjkim	while ((ch = getopt(argc, argv, "-a:d:e:Ii:k:m:np:QSrs")) != -1) {
98167802Sjkim		switch (ch) {
99167802Sjkim		case '-':		/* display term only */
100167802Sjkim			noset = 1;
101167802Sjkim			break;
102167802Sjkim		case 'a':		/* OBSOLETE: map identifier to type */
103167802Sjkim			add_mapping("arpanet", optarg);
104167802Sjkim			break;
105167802Sjkim		case 'd':		/* OBSOLETE: map identifier to type */
106167802Sjkim			add_mapping("dialup", optarg);
107167802Sjkim			break;
108167802Sjkim		case 'e':		/* erase character */
109167802Sjkim			erasechar = optarg[0] == '^' && optarg[1] != '\0' ?
110167802Sjkim			    optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
111167802Sjkim			    optarg[0];
112167802Sjkim			break;
113167802Sjkim		case 'I':		/* no initialization strings */
114167802Sjkim			noinit = 1;
115167802Sjkim			break;
116167802Sjkim		case 'i':		/* interrupt character */
117167802Sjkim			intrchar = optarg[0] == '^' && optarg[1] != '\0' ?
118167802Sjkim			    optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
119167802Sjkim			    optarg[0];
120167802Sjkim			break;
121167802Sjkim		case 'k':		/* kill character */
122200553Sjkim			killchar = optarg[0] == '^' && optarg[1] != '\0' ?
123167802Sjkim			    optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
124167802Sjkim			    optarg[0];
125167802Sjkim			break;
126167802Sjkim		case 'm':		/* map identifier to type */
127167802Sjkim			add_mapping(NULL, optarg);
128167802Sjkim			break;
129167802Sjkim		case 'n':		/* OBSOLETE: set new tty driver */
130167802Sjkim			break;
131167802Sjkim		case 'p':		/* OBSOLETE: map identifier to type */
132167802Sjkim			add_mapping("plugboard", optarg);
133167802Sjkim			break;
134167802Sjkim		case 'Q':		/* don't output control key settings */
135167802Sjkim			quiet = 1;
136167802Sjkim			break;
137167802Sjkim		case 'S':		/* output TERM/TERMCAP strings */
138167802Sjkim			Sflag = 1;
139167802Sjkim			break;
140167802Sjkim		case 'r':		/* display term on stderr */
141167802Sjkim			showterm = 1;
142167802Sjkim			break;
143167802Sjkim		case 's':		/* output TERM/TERMCAP strings */
144167802Sjkim			sflag = 1;
145167802Sjkim			break;
146167802Sjkim		case '?':
147167802Sjkim		default:
148167802Sjkim			usage();
149167802Sjkim		}
150167802Sjkim	}
151167802Sjkim	argc -= optind;
152167802Sjkim	argv += optind;
15367754Smsmith
15467754Smsmith	if (argc > 1)
155167802Sjkim		usage();
156167802Sjkim
15767754Smsmith	ttype = get_termcap_entry(*argv, &tcapbuf);
15867754Smsmith
15977424Smsmith	if (!noset) {
16067754Smsmith		columns = tgetnum("co");
16167754Smsmith		lines = tgetnum("li");
162167802Sjkim
163167802Sjkim#ifdef TIOCGWINSZ
16467754Smsmith		/* Set window size */
16567754Smsmith		(void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
16667754Smsmith		if (win.ws_row == 0 && win.ws_col == 0 &&
16767754Smsmith		    lines > 0 && columns > 0) {
16867754Smsmith			win.ws_row = lines;
16967754Smsmith			win.ws_col = columns;
17067754Smsmith			(void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
17167754Smsmith		}
17267754Smsmith#endif
17367754Smsmith		set_control_chars();
17467754Smsmith		set_conversions(usingupper);
17567754Smsmith
17667754Smsmith		if (!noinit)
17767754Smsmith			set_init();
17867754Smsmith
17967754Smsmith		/* Set the modes if they've changed. */
180167802Sjkim		if (memcmp(&mode, &oldmode, sizeof(mode)))
18167754Smsmith			tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
18267754Smsmith	}
183167802Sjkim
18467754Smsmith	if (noset)
18577424Smsmith		(void)printf("%s\n", ttype);
186167802Sjkim	else {
18767754Smsmith		if (showterm)
188167802Sjkim			(void)fprintf(stderr, "Terminal type is %s.\n", ttype);
18991116Smsmith		/*
19091116Smsmith		 * If erase, kill and interrupt characters could have been
19191116Smsmith		 * modified and not -Q, display the changes.
19291116Smsmith		 */
19391116Smsmith		if (!quiet) {
194167802Sjkim			report("Erase", VERASE, CERASE);
19567754Smsmith			report("Kill", VKILL, CKILL);
19667754Smsmith			report("Interrupt", VINTR, CINTR);
19767754Smsmith		}
198167802Sjkim	}
19967754Smsmith
200167802Sjkim	if (Sflag) {
20167754Smsmith		(void)printf("%s ", ttype);
20267754Smsmith		wrtermcap(tcapbuf);
20367754Smsmith	}
20467754Smsmith
205167802Sjkim	if (sflag) {
20667754Smsmith		/*
207167802Sjkim		 * Figure out what shell we're using.  A hack, we look for an
20867754Smsmith		 * environmental variable SHELL ending in "csh".
20967754Smsmith		 */
21077424Smsmith		if ((p = getenv("SHELL")) &&
21167754Smsmith		    !strcmp(p + strlen(p) - 3, "csh")) {
21267754Smsmith			p = "set noglob;\nsetenv TERM %s;\nsetenv TERMCAP '";
213167802Sjkim			t = "';\nunset noglob;\n";
214167802Sjkim		} else {
21567754Smsmith			p = "TERM=%s;\nTERMCAP='";
21667754Smsmith			t = "';\nexport TERMCAP TERM;\n";
21767754Smsmith		}
21867754Smsmith		(void)printf(p, ttype);
21967754Smsmith		wrtermcap(tcapbuf);
22067754Smsmith		(void)printf(t);
22167754Smsmith	}
22267754Smsmith
22367754Smsmith	exit(0);
22467754Smsmith}
22567754Smsmith
22667754Smsmith/*
22767754Smsmith * Tell the user if a control key has been changed from the default value.
22867754Smsmith */
22967754Smsmithvoid
23067754Smsmithreport(name, which, def)
231167802Sjkim	char *name;
23267754Smsmith	int which;
23367754Smsmith	u_int def;
234167802Sjkim{
23567754Smsmith	u_int old, new;
23683174Smsmith
237167802Sjkim	new = mode.c_cc[which];
23867754Smsmith	old = oldmode.c_cc[which];
239167802Sjkim
24091116Smsmith	if (old == new && old == def)
24191116Smsmith		return;
24291116Smsmith
24391116Smsmith	(void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to");
24491116Smsmith
245167802Sjkim	if (new == 010)
24667754Smsmith		(void)fprintf(stderr, "backspace.\n");
24767754Smsmith	else if (new == 0177)
24867754Smsmith		(void)fprintf(stderr, "delete.\n");
249167802Sjkim	else if (new < 040) {
25067754Smsmith		new ^= 0100;
251167802Sjkim		(void)fprintf(stderr, "control-%c (^%c).\n", new, new);
25267754Smsmith	} else
25367754Smsmith		(void)fprintf(stderr, "%c.\n", new);
25467754Smsmith}
25567754Smsmith
256167802Sjkim/*
25767754Smsmith * Convert the obsolete argument form into something that getopt can handle.
258167802Sjkim * This means that -e, -i and -k get default arguments supplied for them.
25967754Smsmith */
26067754Smsmithvoid
26177424Smsmithobsolete(argv)
26267754Smsmith	char *argv[];
26367754Smsmith{
264167802Sjkim	for (; *argv; ++argv) {
265167802Sjkim		if (argv[0][0] != '-' || argv[1] && argv[1][0] != '-' ||
26667754Smsmith		    argv[0][1] != 'e' && argv[0][1] != 'i' &&
26767754Smsmith		    argv[0][1] != 'k' || argv[0][2] != '\0')
26867754Smsmith			continue;
26967754Smsmith		switch(argv[0][1]) {
27067754Smsmith		case 'e':
27167754Smsmith			argv[0] = "-e^H";
27267754Smsmith			break;
27367754Smsmith		case 'i':
27467754Smsmith			argv[0] = "-i^C";
27567754Smsmith			break;
27667754Smsmith		case 'k':
27767754Smsmith			argv[0] = "-k^U";
27867754Smsmith			break;
279167802Sjkim		}
28067754Smsmith	}
28167754Smsmith}
282167802Sjkim
28367754Smsmithvoid
28477424Smsmithusage()
285167802Sjkim{
28667754Smsmith	(void)fprintf(stderr,
287167802Sjkim"usage: tset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n");
28891116Smsmith	exit(1);
28991116Smsmith}
29091116Smsmith