1/*- 2 * Copyright (c) 1980, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31 32__FBSDID("$FreeBSD$"); 33 34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1980, 1991, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif 39 40#ifndef lint 41static const char sccsid[] = "@(#)tset.c 8.1 (Berkeley) 6/9/93"; 42#endif 43 44#include <sys/types.h> 45#include <sys/ioctl.h> 46 47#include <ctype.h> 48#include <err.h> 49#include <stdio.h> 50#include <stdlib.h> 51#include <string.h> 52#include <termcap.h> 53#include <termios.h> 54#include <unistd.h> 55 56#include "extern.h" 57 58void obsolete(char *[]); 59void report(const char *, int, u_int); 60void usage(void); 61 62struct termios mode, oldmode; 63 64int erasech; /* new erase character */ 65int intrchar; /* new interrupt character */ 66int isreset; /* invoked as reset */ 67int killch; /* new kill character */ 68int Lines, Columns; /* window size */ 69speed_t Ospeed; 70 71int 72main(int argc, char *argv[]) 73{ 74#ifdef TIOCGWINSZ 75 struct winsize win; 76#endif 77 int ch, noinit, noset, quiet, Sflag, sflag, showterm, usingupper; 78 char *p, *tcapbuf; 79 const char *ttype; 80 81 if (tcgetattr(STDERR_FILENO, &mode) < 0) 82 err(1, "standard error"); 83 84 oldmode = mode; 85 Ospeed = cfgetospeed(&mode); 86 87 if ((p = strrchr(*argv, '/'))) 88 ++p; 89 else 90 p = *argv; 91 usingupper = isupper(*p); 92 if (!strcasecmp(p, "reset")) { 93 isreset = 1; 94 reset_mode(); 95 } 96 97 obsolete(argv); 98 noinit = noset = quiet = Sflag = sflag = showterm = 0; 99 while ((ch = getopt(argc, argv, "-a:d:e:Ii:k:m:np:QSrs")) != -1) { 100 switch (ch) { 101 case '-': /* display term only */ 102 noset = 1; 103 break; 104 case 'a': /* OBSOLETE: map identifier to type */ 105 add_mapping("arpanet", optarg); 106 break; 107 case 'd': /* OBSOLETE: map identifier to type */ 108 add_mapping("dialup", optarg); 109 break; 110 case 'e': /* erase character */ 111 erasech = optarg[0] == '^' && optarg[1] != '\0' ? 112 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : 113 optarg[0]; 114 break; 115 case 'I': /* no initialization strings */ 116 noinit = 1; 117 break; 118 case 'i': /* interrupt character */ 119 intrchar = optarg[0] == '^' && optarg[1] != '\0' ? 120 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : 121 optarg[0]; 122 break; 123 case 'k': /* kill character */ 124 killch = optarg[0] == '^' && optarg[1] != '\0' ? 125 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : 126 optarg[0]; 127 break; 128 case 'm': /* map identifier to type */ 129 add_mapping(NULL, optarg); 130 break; 131 case 'n': /* OBSOLETE: set new tty driver */ 132 break; 133 case 'p': /* OBSOLETE: map identifier to type */ 134 add_mapping("plugboard", optarg); 135 break; 136 case 'Q': /* don't output control key settings */ 137 quiet = 1; 138 break; 139 case 'S': /* output TERM/TERMCAP strings */ 140 Sflag = 1; 141 break; 142 case 'r': /* display term on stderr */ 143 showterm = 1; 144 break; 145 case 's': /* output TERM/TERMCAP strings */ 146 sflag = 1; 147 break; 148 case '?': 149 default: 150 usage(); 151 } 152 } 153 argc -= optind; 154 argv += optind; 155 156 if (argc > 1) 157 usage(); 158 159 ttype = get_termcap_entry(*argv, &tcapbuf); 160 161 if (!noset) { 162 Columns = tgetnum("co"); 163 Lines = tgetnum("li"); 164 165#ifdef TIOCGWINSZ 166 /* Set window size */ 167 (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win); 168 if (win.ws_row == 0 && win.ws_col == 0 && 169 Lines > 0 && Columns > 0) { 170 win.ws_row = Lines; 171 win.ws_col = Columns; 172 (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win); 173 } 174#endif 175 set_control_chars(); 176 set_conversions(usingupper); 177 178 if (!noinit) 179 set_init(); 180 181 /* Set the modes if they've changed. */ 182 if (memcmp(&mode, &oldmode, sizeof(mode))) 183 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); 184 } 185 186 if (noset) 187 (void)printf("%s\n", ttype); 188 else { 189 if (showterm) 190 (void)fprintf(stderr, "Terminal type is %s.\n", ttype); 191 /* 192 * If erase, kill and interrupt characters could have been 193 * modified and not -Q, display the changes. 194 */ 195 if (!quiet) { 196 report("Erase", VERASE, CERASE); 197 report("Kill", VKILL, CKILL); 198 report("Interrupt", VINTR, CINTR); 199 } 200 } 201 202 if (Sflag) { 203 (void)printf("%s ", ttype); 204 if (strlen(tcapbuf) > 0) 205 wrtermcap(tcapbuf); 206 } 207 208 if (sflag) { 209 /* 210 * Figure out what shell we're using. A hack, we look for an 211 * environmental variable SHELL ending in "csh". 212 */ 213 if ((p = getenv("SHELL")) && 214 !strcmp(p + strlen(p) - 3, "csh")) { 215 printf("set noglob;\nsetenv TERM %s;\n", ttype); 216 if (strlen(tcapbuf) > 0) { 217 printf("setenv TERMCAP '"); 218 wrtermcap(tcapbuf); 219 printf("';\n"); 220 } 221 printf("unset noglob;\n"); 222 } else { 223 printf("TERM=%s;\n", ttype); 224 if (strlen(tcapbuf) > 0) { 225 printf("TERMCAP='"); 226 wrtermcap(tcapbuf); 227 printf("';\nexport TERMCAP;\n"); 228 } 229 printf("export TERM;\n"); 230 } 231 } 232 233 exit(0); 234} 235 236/* 237 * Tell the user if a control key has been changed from the default value. 238 */ 239void 240report(const char *name, int which, u_int def) 241{ 242 u_int old, new; 243 244 new = mode.c_cc[which]; 245 old = oldmode.c_cc[which]; 246 247 if (old == new && old == def) 248 return; 249 250 (void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to"); 251 252 if (new == 010) 253 (void)fprintf(stderr, "backspace.\n"); 254 else if (new == 0177) 255 (void)fprintf(stderr, "delete.\n"); 256 else if (new < 040) { 257 new ^= 0100; 258 (void)fprintf(stderr, "control-%c (^%c).\n", new, new); 259 } else 260 (void)fprintf(stderr, "%c.\n", new); 261} 262 263/* 264 * Convert the obsolete argument form into something that getopt can handle. 265 * This means that -e, -i and -k get default arguments supplied for them. 266 */ 267void 268obsolete(char *argv[]) 269{ 270 for (; *argv; ++argv) { 271 if (argv[0][0] != '-' || (argv[1] && argv[1][0] != '-') || 272 (argv[0][1] != 'e' && argv[0][1] != 'i' && argv[0][1] != 'k') || 273 argv[0][2] != '\0') 274 continue; 275 switch(argv[0][1]) { 276 case 'e': 277 argv[0] = strdup("-e^H"); 278 break; 279 case 'i': 280 argv[0] = strdup("-i^C"); 281 break; 282 case 'k': 283 argv[0] = strdup("-k^U"); 284 break; 285 } 286 } 287} 288 289void 290usage(void) 291{ 292 (void)fprintf(stderr, "%s\n%s\n", 293"usage: tset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]", 294" reset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]"); 295 exit(1); 296} 297 298