xref: /csrg-svn/usr.bin/tset/tset.c (revision 63082)
152057Sbostic /*-
2*63082Sbostic  * Copyright (c) 1980, 1991, 1993
3*63082Sbostic  *	The Regents of the University of California.  All rights reserved.
434201Sbostic  *
542770Sbostic  * %sccs.include.redist.c%
622406Sdist  */
722406Sdist 
814555Ssam #ifndef lint
9*63082Sbostic static char copyright[] =
10*63082Sbostic "@(#) Copyright (c) 1980, 1991, 1993\n\
11*63082Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1234201Sbostic #endif /* not lint */
135028Sroot 
1422406Sdist #ifndef lint
15*63082Sbostic static char sccsid[] = "@(#)tset.c	8.1 (Berkeley) 06/09/93";
1634201Sbostic #endif /* not lint */
1722406Sdist 
1852000Smarc #include <sys/types.h>
1954808Spendry #include <sys/ioctl.h>
2052000Smarc #include <termios.h>
2152057Sbostic #include <errno.h>
2252000Smarc #include <unistd.h>
2352000Smarc #include <stdlib.h>
2452057Sbostic #include <stdio.h>
2552000Smarc #include <ctype.h>
2652000Smarc #include <string.h>
2752057Sbostic #include "extern.h"
2824159Sbloom 
2952057Sbostic void	obsolete __P((char *[]));
3052057Sbostic void	report __P((char *, int, u_int));
3152057Sbostic void	usage __P((void));
3226973Sbloom 
3352057Sbostic struct termios mode, oldmode;
345026Sroot 
3552057Sbostic int	erasechar;		/* new erase character */
3652057Sbostic int	intrchar;		/* new interrupt character */
3752057Sbostic int	isreset;		/* invoked as reset */
3852057Sbostic int	killchar;		/* new kill character */
3952057Sbostic int	lines, columns;		/* window size */
405026Sroot 
4152057Sbostic int
main(argc,argv)425026Sroot main(argc, argv)
4352057Sbostic 	int argc;
4452057Sbostic 	char *argv[];
455026Sroot {
4652000Smarc #ifdef TIOCGWINSZ
4752057Sbostic 	struct winsize win;
4852000Smarc #endif
4952072Sbostic 	int ch, noinit, noset, quiet, Sflag, sflag, showterm, usingupper;
5052057Sbostic 	char savech, *p, *t, *tcapbuf, *ttype;
515026Sroot 
5252057Sbostic 	if (tcgetattr(STDERR_FILENO, &mode) < 0)
5352057Sbostic 		err("standard error: %s", strerror(errno));
545028Sroot 
5552000Smarc 	oldmode = mode;
5652000Smarc 	ospeed = cfgetospeed(&mode);
5752000Smarc 
5852057Sbostic 	if (p = strrchr(*argv, '/'))
5952057Sbostic 		++p;
605028Sroot 	else
6152057Sbostic 		p = *argv;
6252057Sbostic 	usingupper = isupper(*p);
6352057Sbostic 	if (!strcasecmp(p, "reset")) {
6452057Sbostic 		isreset = 1;
6552000Smarc 		reset_mode();
665026Sroot 	}
675028Sroot 
6852057Sbostic 	obsolete(argv);
6952072Sbostic 	noinit = noset = quiet = Sflag = sflag = showterm = 0;
7052072Sbostic 	while ((ch = getopt(argc, argv, "-a:d:e:Ii:k:m:np:QSrs")) != EOF) {
7152057Sbostic 		switch (ch) {
7252072Sbostic 		case '-':		/* display term only */
7352057Sbostic 			noset = 1;
7452057Sbostic 			break;
7552064Sbostic 		case 'a':		/* OBSOLETE: map identifier to type */
7652064Sbostic 			add_mapping("arpanet", optarg);
7752064Sbostic 			break;
7852064Sbostic 		case 'd':		/* OBSOLETE: map identifier to type */
7952064Sbostic 			add_mapping("dialup", optarg);
8052064Sbostic 			break;
8152057Sbostic 		case 'e':		/* erase character */
8252057Sbostic 			erasechar = optarg[0] == '^' && optarg[1] != '\0' ?
8352057Sbostic 			    optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
8452057Sbostic 			    optarg[0];
8552057Sbostic 			break;
8652072Sbostic 		case 'I':		/* no initialization strings */
8752057Sbostic 			noinit = 1;
8852057Sbostic 			break;
8952057Sbostic 		case 'i':		/* interrupt character */
9052057Sbostic 			intrchar = optarg[0] == '^' && optarg[1] != '\0' ?
9152057Sbostic 			    optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
9252057Sbostic 			    optarg[0];
9352057Sbostic 			break;
9452057Sbostic 		case 'k':		/* kill character */
9552057Sbostic 			killchar = optarg[0] == '^' && optarg[1] != '\0' ?
9652057Sbostic 			    optarg[1] == '?' ? '\177' : CTRL(optarg[1]) :
9752057Sbostic 			    optarg[0];
9852057Sbostic 			break;
9952057Sbostic 		case 'm':		/* map identifier to type */
10052064Sbostic 			add_mapping(NULL, optarg);
10152057Sbostic 			break;
10252064Sbostic 		case 'n':		/* OBSOLETE: set new tty driver */
10352064Sbostic 			break;
10452064Sbostic 		case 'p':		/* OBSOLETE: map identifier to type */
10552064Sbostic 			add_mapping("plugboard", optarg);
10652064Sbostic 			break;
10752072Sbostic 		case 'Q':		/* don't output control key settings */
10852057Sbostic 			quiet = 1;
10952057Sbostic 			break;
11052072Sbostic 		case 'S':		/* output TERM/TERMCAP strings */
11152072Sbostic 			Sflag = 1;
11252072Sbostic 			break;
11352064Sbostic 		case 'r':		/* display term on stderr */
11452064Sbostic 			showterm = 1;
11552064Sbostic 			break;
11652072Sbostic 		case 's':		/* output TERM/TERMCAP strings */
11752072Sbostic 			sflag = 1;
11852057Sbostic 			break;
11952057Sbostic 		case '?':
12052057Sbostic 		default:
12152057Sbostic 			usage();
12252057Sbostic 		}
1235026Sroot 	}
12452057Sbostic 	argc -= optind;
12552057Sbostic 	argv += optind;
1265026Sroot 
12752057Sbostic 	if (argc > 1)
12852000Smarc 		usage();
1295026Sroot 
13052057Sbostic 	ttype = get_termcap_entry(*argv, &tcapbuf);
1315026Sroot 
13252057Sbostic 	if (!noset) {
13318031Sbloom 		columns = tgetnum("co");
13418031Sbloom 		lines = tgetnum("li");
13518031Sbloom 
13652000Smarc #ifdef TIOCGWINSZ
13718031Sbloom 		/* Set window size */
13852057Sbostic 		(void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
13926973Sbloom 		if (win.ws_row == 0 && win.ws_col == 0 &&
14026973Sbloom 		    lines > 0 && columns > 0) {
14126973Sbloom 			win.ws_row = lines;
14226973Sbloom 			win.ws_col = columns;
14352057Sbostic 			(void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
14418031Sbloom 		}
14552000Smarc #endif
14652057Sbostic 		set_control_chars();
14752057Sbostic 		set_conversions(usingupper);
14852000Smarc 
14952057Sbostic 		if (!noinit)
15052057Sbostic 			set_init();
1515026Sroot 
15252057Sbostic 		/* Set the modes if they've changed. */
15352057Sbostic 		if (memcmp(&mode, &oldmode, sizeof(mode)))
15452057Sbostic 			tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
1555026Sroot 	}
1565026Sroot 
15757936Selan 	/* Get the terminal name from the entry. */
15857936Selan 	p = tcapbuf;
15957936Selan 	if (p != NULL && *p != ':') {
16057936Selan 		t = p;
16152057Sbostic 		if (p = strpbrk(p, "|:")) {
16252057Sbostic 			savech = *p;
16352057Sbostic 			*p = '\0';
16452057Sbostic 			if ((ttype = strdup(t)) == NULL)
16552057Sbostic 				err("%s", strerror(errno));
16652057Sbostic 			*p = savech;
1675026Sroot 		}
1685026Sroot 	}
1695026Sroot 
17052064Sbostic 	if (noset)
17152057Sbostic 		(void)printf("%s\n", ttype);
17252064Sbostic 	else {
17352064Sbostic 		if (showterm)
17452064Sbostic 			(void)fprintf(stderr, "Terminal type is %s.\n", ttype);
17552064Sbostic 		/*
17652064Sbostic 		 * If erase, kill and interrupt characters could have been
17752064Sbostic 		 * modified and not -Q, display the changes.
17852064Sbostic 		 */
17952064Sbostic 		if (!quiet) {
18052064Sbostic 			report("Erase", VERASE, CERASE);
18152064Sbostic 			report("Kill", VKILL, CKILL);
18252064Sbostic 			report("Interrupt", VINTR, CINTR);
18352064Sbostic 		}
18452000Smarc 	}
1855026Sroot 
18652072Sbostic 	if (Sflag) {
18752072Sbostic 		(void)printf("%s ", ttype);
18852072Sbostic 		wrtermcap(tcapbuf);
18952072Sbostic 	}
19052064Sbostic 
19152072Sbostic 	if (sflag) {
19252072Sbostic 		/*
19352072Sbostic 		 * Figure out what shell we're using.  A hack, we look for an
19452072Sbostic 		 * environmental variable SHELL ending in "csh".
19552072Sbostic 		 */
19652072Sbostic 		if ((p = getenv("SHELL")) &&
19752072Sbostic 		    !strcmp(p + strlen(p) - 3, "csh")) {
19852072Sbostic 			p = "set noglob;\nsetenv TERM %s;\nsetenv TERMCAP '";
19952072Sbostic 			t = "';\nunset noglob;\n";
20052072Sbostic 		} else {
20152072Sbostic 			p = "TERM=%s;\nTERMCAP='";
20252072Sbostic 			t = "';\nexport TERMCAP TERM;\n";
20352072Sbostic 		}
20452072Sbostic 		(void)printf(p, ttype);
20552072Sbostic 		wrtermcap(tcapbuf);
20652072Sbostic 		(void)printf(t);
20752072Sbostic 	}
20852072Sbostic 
20952057Sbostic 	exit(0);
21052000Smarc }
21152000Smarc 
2125028Sroot /*
21352057Sbostic  * Tell the user if a control key has been changed from the default value.
2145028Sroot  */
21546863Sbostic void
report(name,which,def)21652057Sbostic report(name, which, def)
21752057Sbostic 	char *name;
21852057Sbostic 	int which;
21952057Sbostic 	u_int def;
2205028Sroot {
22152057Sbostic 	u_int old, new;
22252057Sbostic 	char *bp, buf[1024];
2235028Sroot 
22452057Sbostic 	new = mode.c_cc[which];
22552057Sbostic 	old = oldmode.c_cc[which];
22652000Smarc 
22752057Sbostic 	if (old == new && old == def)
2285026Sroot 		return;
2295026Sroot 
23052057Sbostic 	(void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to");
2315026Sroot 
23252057Sbostic 	bp = buf;
23352057Sbostic 	if (tgetstr("kb", &bp) && new == buf[0] && buf[1] == '\0')
23452057Sbostic 		(void)fprintf(stderr, "backspace.\n");
23552057Sbostic 	else if (new == 0177)
23652057Sbostic 		(void)fprintf(stderr, "delete.\n");
23752057Sbostic 	else if (new < 040) {
23852057Sbostic 		new ^= 0100;
23952057Sbostic 		(void)fprintf(stderr, "control-%c (^%c).\n", new, new);
24052057Sbostic 	} else
24152057Sbostic 		(void)fprintf(stderr, "%c.\n", new);
2425026Sroot }
2435026Sroot 
24452057Sbostic /*
24552057Sbostic  * Convert the obsolete argument form into something that getopt can handle.
24652057Sbostic  * This means that -e, -i and -k get default arguments supplied for them.
24752057Sbostic  */
24852000Smarc void
obsolete(argv)24952057Sbostic obsolete(argv)
25052057Sbostic 	char *argv[];
2515026Sroot {
25252057Sbostic 	for (; *argv; ++argv) {
25352057Sbostic 		if (argv[0][0] != '-' || argv[1] && argv[1][0] != '-' ||
25452057Sbostic 		    argv[0][1] != 'e' && argv[0][1] != 'i' &&
25552057Sbostic 		    argv[0][1] != 'k' || argv[0][2] != '\0')
2565026Sroot 			continue;
25752057Sbostic 		switch(argv[0][1]) {
25852057Sbostic 		case 'e':
25952057Sbostic 			argv[0] = "-e^H";
2605028Sroot 			break;
26152057Sbostic 		case 'i':
26252057Sbostic 			argv[0] = "-i^C";
26352057Sbostic 			break;
26452057Sbostic 		case 'k':
26552057Sbostic 			argv[0] = "-k^U";
26652057Sbostic 			break;
2675028Sroot 		}
2685028Sroot 	}
2695026Sroot }
27052064Sbostic 
27152000Smarc void
usage()27252000Smarc usage()
2735026Sroot {
27452057Sbostic 	(void)fprintf(stderr,
27552072Sbostic "usage: tset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n");
2765026Sroot 	exit(1);
2775026Sroot }
278