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