11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1980, 1991, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 3087701Smarkm#include <sys/cdefs.h> 3187701Smarkm 3287701Smarkm__FBSDID("$FreeBSD$"); 3387701Smarkm 341590Srgrimes#ifndef lint 3528370Scharnierstatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1980, 1991, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 3887701Smarkm#endif 391590Srgrimes 401590Srgrimes#ifndef lint 4187701Smarkmstatic const char sccsid[] = "@(#)tset.c 8.1 (Berkeley) 6/9/93"; 4228370Scharnier#endif 431590Srgrimes 441590Srgrimes#include <sys/types.h> 451590Srgrimes#include <sys/ioctl.h> 4687701Smarkm 4728370Scharnier#include <ctype.h> 4828370Scharnier#include <err.h> 4928370Scharnier#include <stdio.h> 501590Srgrimes#include <stdlib.h> 511590Srgrimes#include <string.h> 52200419Sdelphij#include <termcap.h> 5387701Smarkm#include <termios.h> 5428370Scharnier#include <unistd.h> 5587701Smarkm 561590Srgrimes#include "extern.h" 571590Srgrimes 5892922Simpvoid obsolete(char *[]); 5992922Simpvoid report(const char *, int, u_int); 6092922Simpvoid usage(void); 611590Srgrimes 621590Srgrimesstruct termios mode, oldmode; 631590Srgrimes 6468617Sdgint erasech; /* new erase character */ 651590Srgrimesint intrchar; /* new interrupt character */ 661590Srgrimesint isreset; /* invoked as reset */ 6768617Sdgint killch; /* new kill character */ 6850638Speterint Lines, Columns; /* window size */ 692599Sachespeed_t Ospeed; 701590Srgrimes 711590Srgrimesint 72102944Sdwmalonemain(int argc, char *argv[]) 731590Srgrimes{ 741590Srgrimes#ifdef TIOCGWINSZ 751590Srgrimes struct winsize win; 761590Srgrimes#endif 771590Srgrimes int ch, noinit, noset, quiet, Sflag, sflag, showterm, usingupper; 7887701Smarkm char *p, *tcapbuf; 7987701Smarkm const char *ttype; 801590Srgrimes 811590Srgrimes if (tcgetattr(STDERR_FILENO, &mode) < 0) 8228370Scharnier err(1, "standard error"); 831590Srgrimes 841590Srgrimes oldmode = mode; 852599Sache Ospeed = cfgetospeed(&mode); 863397Sache 8728370Scharnier if ((p = strrchr(*argv, '/'))) 881590Srgrimes ++p; 891590Srgrimes else 901590Srgrimes p = *argv; 911590Srgrimes usingupper = isupper(*p); 921590Srgrimes if (!strcasecmp(p, "reset")) { 931590Srgrimes isreset = 1; 941590Srgrimes reset_mode(); 951590Srgrimes } 961590Srgrimes 971590Srgrimes obsolete(argv); 981590Srgrimes noinit = noset = quiet = Sflag = sflag = showterm = 0; 9924360Simp while ((ch = getopt(argc, argv, "-a:d:e:Ii:k:m:np:QSrs")) != -1) { 1001590Srgrimes switch (ch) { 1011590Srgrimes case '-': /* display term only */ 1021590Srgrimes noset = 1; 1031590Srgrimes break; 1041590Srgrimes case 'a': /* OBSOLETE: map identifier to type */ 1051590Srgrimes add_mapping("arpanet", optarg); 1061590Srgrimes break; 1071590Srgrimes case 'd': /* OBSOLETE: map identifier to type */ 1081590Srgrimes add_mapping("dialup", optarg); 1091590Srgrimes break; 1101590Srgrimes case 'e': /* erase character */ 11168617Sdg erasech = optarg[0] == '^' && optarg[1] != '\0' ? 1121590Srgrimes optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : 1131590Srgrimes optarg[0]; 1141590Srgrimes break; 1151590Srgrimes case 'I': /* no initialization strings */ 1161590Srgrimes noinit = 1; 1171590Srgrimes break; 1181590Srgrimes case 'i': /* interrupt character */ 1191590Srgrimes intrchar = optarg[0] == '^' && optarg[1] != '\0' ? 1201590Srgrimes optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : 1211590Srgrimes optarg[0]; 1221590Srgrimes break; 1231590Srgrimes case 'k': /* kill character */ 12468617Sdg killch = optarg[0] == '^' && optarg[1] != '\0' ? 1251590Srgrimes optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : 1261590Srgrimes optarg[0]; 1271590Srgrimes break; 1281590Srgrimes case 'm': /* map identifier to type */ 1291590Srgrimes add_mapping(NULL, optarg); 1301590Srgrimes break; 1311590Srgrimes case 'n': /* OBSOLETE: set new tty driver */ 1321590Srgrimes break; 1331590Srgrimes case 'p': /* OBSOLETE: map identifier to type */ 1341590Srgrimes add_mapping("plugboard", optarg); 1351590Srgrimes break; 1361590Srgrimes case 'Q': /* don't output control key settings */ 1371590Srgrimes quiet = 1; 1381590Srgrimes break; 1391590Srgrimes case 'S': /* output TERM/TERMCAP strings */ 1401590Srgrimes Sflag = 1; 1411590Srgrimes break; 1421590Srgrimes case 'r': /* display term on stderr */ 1431590Srgrimes showterm = 1; 1441590Srgrimes break; 1451590Srgrimes case 's': /* output TERM/TERMCAP strings */ 1461590Srgrimes sflag = 1; 1471590Srgrimes break; 1481590Srgrimes case '?': 1491590Srgrimes default: 1501590Srgrimes usage(); 1511590Srgrimes } 1521590Srgrimes } 1531590Srgrimes argc -= optind; 1541590Srgrimes argv += optind; 1551590Srgrimes 1561590Srgrimes if (argc > 1) 1571590Srgrimes usage(); 1581590Srgrimes 1591590Srgrimes ttype = get_termcap_entry(*argv, &tcapbuf); 1601590Srgrimes 1611590Srgrimes if (!noset) { 16250638Speter Columns = tgetnum("co"); 16350638Speter Lines = tgetnum("li"); 1641590Srgrimes 1651590Srgrimes#ifdef TIOCGWINSZ 1661590Srgrimes /* Set window size */ 1671590Srgrimes (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win); 1681590Srgrimes if (win.ws_row == 0 && win.ws_col == 0 && 16950638Speter Lines > 0 && Columns > 0) { 17050638Speter win.ws_row = Lines; 17150638Speter win.ws_col = Columns; 1721590Srgrimes (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win); 1731590Srgrimes } 1741590Srgrimes#endif 1751590Srgrimes set_control_chars(); 1761590Srgrimes set_conversions(usingupper); 1771590Srgrimes 1781590Srgrimes if (!noinit) 1791590Srgrimes set_init(); 1801590Srgrimes 1811590Srgrimes /* Set the modes if they've changed. */ 1821590Srgrimes if (memcmp(&mode, &oldmode, sizeof(mode))) 1831590Srgrimes tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); 1841590Srgrimes } 1851590Srgrimes 1861590Srgrimes if (noset) 1871590Srgrimes (void)printf("%s\n", ttype); 1881590Srgrimes else { 1891590Srgrimes if (showterm) 1901590Srgrimes (void)fprintf(stderr, "Terminal type is %s.\n", ttype); 1911590Srgrimes /* 1921590Srgrimes * If erase, kill and interrupt characters could have been 1931590Srgrimes * modified and not -Q, display the changes. 1941590Srgrimes */ 1951590Srgrimes if (!quiet) { 1961590Srgrimes report("Erase", VERASE, CERASE); 1971590Srgrimes report("Kill", VKILL, CKILL); 1981590Srgrimes report("Interrupt", VINTR, CINTR); 1991590Srgrimes } 2001590Srgrimes } 2011590Srgrimes 2021590Srgrimes if (Sflag) { 2031590Srgrimes (void)printf("%s ", ttype); 20450638Speter if (strlen(tcapbuf) > 0) 20550638Speter wrtermcap(tcapbuf); 2061590Srgrimes } 2071590Srgrimes 2081590Srgrimes if (sflag) { 2091590Srgrimes /* 2101590Srgrimes * Figure out what shell we're using. A hack, we look for an 2111590Srgrimes * environmental variable SHELL ending in "csh". 2121590Srgrimes */ 2131590Srgrimes if ((p = getenv("SHELL")) && 2141590Srgrimes !strcmp(p + strlen(p) - 3, "csh")) { 21550638Speter printf("set noglob;\nsetenv TERM %s;\n", ttype); 21650638Speter if (strlen(tcapbuf) > 0) { 21750638Speter printf("setenv TERMCAP '"); 21850638Speter wrtermcap(tcapbuf); 21950638Speter printf("';\n"); 22050638Speter } 22150638Speter printf("unset noglob;\n"); 2221590Srgrimes } else { 22350638Speter printf("TERM=%s;\n", ttype); 22450638Speter if (strlen(tcapbuf) > 0) { 22550638Speter printf("TERMCAP='"); 22650638Speter wrtermcap(tcapbuf); 22750638Speter printf("';\nexport TERMCAP;\n"); 22850638Speter } 22950638Speter printf("export TERM;\n"); 2301590Srgrimes } 2311590Srgrimes } 2321590Srgrimes 2331590Srgrimes exit(0); 2341590Srgrimes} 2351590Srgrimes 2361590Srgrimes/* 2371590Srgrimes * Tell the user if a control key has been changed from the default value. 2381590Srgrimes */ 2391590Srgrimesvoid 240102944Sdwmalonereport(const char *name, int which, u_int def) 2411590Srgrimes{ 2421590Srgrimes u_int old, new; 2431590Srgrimes 2441590Srgrimes new = mode.c_cc[which]; 2451590Srgrimes old = oldmode.c_cc[which]; 2461590Srgrimes 2471590Srgrimes if (old == new && old == def) 2481590Srgrimes return; 2491590Srgrimes 2501590Srgrimes (void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to"); 2511590Srgrimes 2528524Sache if (new == 010) 2531590Srgrimes (void)fprintf(stderr, "backspace.\n"); 2541590Srgrimes else if (new == 0177) 2551590Srgrimes (void)fprintf(stderr, "delete.\n"); 2561590Srgrimes else if (new < 040) { 2571590Srgrimes new ^= 0100; 2581590Srgrimes (void)fprintf(stderr, "control-%c (^%c).\n", new, new); 2591590Srgrimes } else 2601590Srgrimes (void)fprintf(stderr, "%c.\n", new); 2611590Srgrimes} 2621590Srgrimes 2631590Srgrimes/* 2641590Srgrimes * Convert the obsolete argument form into something that getopt can handle. 2651590Srgrimes * This means that -e, -i and -k get default arguments supplied for them. 2661590Srgrimes */ 2671590Srgrimesvoid 268102944Sdwmaloneobsolete(char *argv[]) 2691590Srgrimes{ 2701590Srgrimes for (; *argv; ++argv) { 27128370Scharnier if (argv[0][0] != '-' || (argv[1] && argv[1][0] != '-') || 27228370Scharnier (argv[0][1] != 'e' && argv[0][1] != 'i' && argv[0][1] != 'k') || 27328370Scharnier argv[0][2] != '\0') 2741590Srgrimes continue; 2751590Srgrimes switch(argv[0][1]) { 2761590Srgrimes case 'e': 27787701Smarkm argv[0] = strdup("-e^H"); 2781590Srgrimes break; 2791590Srgrimes case 'i': 28087701Smarkm argv[0] = strdup("-i^C"); 2811590Srgrimes break; 2821590Srgrimes case 'k': 28387701Smarkm argv[0] = strdup("-k^U"); 2841590Srgrimes break; 2851590Srgrimes } 2861590Srgrimes } 2871590Srgrimes} 2881590Srgrimes 2891590Srgrimesvoid 290102944Sdwmaloneusage(void) 2911590Srgrimes{ 29228370Scharnier (void)fprintf(stderr, "%s\n%s\n", 29328370Scharnier"usage: tset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]", 29428370Scharnier" reset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]"); 2951590Srgrimes exit(1); 2961590Srgrimes} 29728370Scharnier 298