1 /*- 2 * Copyright (c) 1980, 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1980, 1991 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)tset.c 5.21 (Berkeley) 07/08/92"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 #include <sys/ioctl.h> 20 #include <termios.h> 21 #include <errno.h> 22 #include <unistd.h> 23 #include <stdlib.h> 24 #include <stdio.h> 25 #include <ctype.h> 26 #include <string.h> 27 #include "extern.h" 28 29 void obsolete __P((char *[])); 30 void report __P((char *, int, u_int)); 31 void usage __P((void)); 32 33 struct termios mode, oldmode; 34 35 int erasechar; /* new erase character */ 36 int intrchar; /* new interrupt character */ 37 int isreset; /* invoked as reset */ 38 int killchar; /* new kill character */ 39 int lines, columns; /* window size */ 40 41 int 42 main(argc, argv) 43 int argc; 44 char *argv[]; 45 { 46 #ifdef TIOCGWINSZ 47 struct winsize win; 48 #endif 49 int ch, noinit, noset, quiet, Sflag, sflag, showterm, usingupper; 50 char savech, *p, *t, *tcapbuf, *ttype; 51 52 if (tcgetattr(STDERR_FILENO, &mode) < 0) 53 err("standard error: %s", strerror(errno)); 54 55 oldmode = mode; 56 ospeed = cfgetospeed(&mode); 57 58 if (p = strrchr(*argv, '/')) 59 ++p; 60 else 61 p = *argv; 62 usingupper = isupper(*p); 63 if (!strcasecmp(p, "reset")) { 64 isreset = 1; 65 reset_mode(); 66 } 67 68 obsolete(argv); 69 noinit = noset = quiet = Sflag = sflag = showterm = 0; 70 while ((ch = getopt(argc, argv, "-a:d:e:Ii:k:m:np:QSrs")) != EOF) { 71 switch (ch) { 72 case '-': /* display term only */ 73 noset = 1; 74 break; 75 case 'a': /* OBSOLETE: map identifier to type */ 76 add_mapping("arpanet", optarg); 77 break; 78 case 'd': /* OBSOLETE: map identifier to type */ 79 add_mapping("dialup", optarg); 80 break; 81 case 'e': /* erase character */ 82 erasechar = optarg[0] == '^' && optarg[1] != '\0' ? 83 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : 84 optarg[0]; 85 break; 86 case 'I': /* no initialization strings */ 87 noinit = 1; 88 break; 89 case 'i': /* interrupt character */ 90 intrchar = optarg[0] == '^' && optarg[1] != '\0' ? 91 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : 92 optarg[0]; 93 break; 94 case 'k': /* kill character */ 95 killchar = optarg[0] == '^' && optarg[1] != '\0' ? 96 optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : 97 optarg[0]; 98 break; 99 case 'm': /* map identifier to type */ 100 add_mapping(NULL, optarg); 101 break; 102 case 'n': /* OBSOLETE: set new tty driver */ 103 break; 104 case 'p': /* OBSOLETE: map identifier to type */ 105 add_mapping("plugboard", optarg); 106 break; 107 case 'Q': /* don't output control key settings */ 108 quiet = 1; 109 break; 110 case 'S': /* output TERM/TERMCAP strings */ 111 Sflag = 1; 112 break; 113 case 'r': /* display term on stderr */ 114 showterm = 1; 115 break; 116 case 's': /* output TERM/TERMCAP strings */ 117 sflag = 1; 118 break; 119 case '?': 120 default: 121 usage(); 122 } 123 } 124 argc -= optind; 125 argv += optind; 126 127 if (argc > 1) 128 usage(); 129 130 ttype = get_termcap_entry(*argv, &tcapbuf); 131 132 if (!noset) { 133 columns = tgetnum("co"); 134 lines = tgetnum("li"); 135 136 #ifdef TIOCGWINSZ 137 /* Set window size */ 138 (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win); 139 if (win.ws_row == 0 && win.ws_col == 0 && 140 lines > 0 && columns > 0) { 141 win.ws_row = lines; 142 win.ws_col = columns; 143 (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win); 144 } 145 #endif 146 set_control_chars(); 147 set_conversions(usingupper); 148 149 if (!noinit) 150 set_init(); 151 152 /* Set the modes if they've changed. */ 153 if (memcmp(&mode, &oldmode, sizeof(mode))) 154 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); 155 } 156 157 /* 158 * The termcap file generally has a two-character name first in each 159 * entry followed by more descriptive names. If we ended up with the 160 * first one, we switch to the second one for setting or reporting 161 * information. 162 */ 163 p = strpbrk(tcapbuf, "|:"); 164 if (p && *p != ':' && !strncmp(ttype, tcapbuf, p - tcapbuf)) { 165 t = ++p; 166 if (p = strpbrk(p, "|:")) { 167 savech = *p; 168 *p = '\0'; 169 if ((ttype = strdup(t)) == NULL) 170 err("%s", strerror(errno)); 171 *p = savech; 172 } 173 } 174 175 if (noset) 176 (void)printf("%s\n", ttype); 177 else { 178 if (showterm) 179 (void)fprintf(stderr, "Terminal type is %s.\n", ttype); 180 /* 181 * If erase, kill and interrupt characters could have been 182 * modified and not -Q, display the changes. 183 */ 184 if (!quiet) { 185 report("Erase", VERASE, CERASE); 186 report("Kill", VKILL, CKILL); 187 report("Interrupt", VINTR, CINTR); 188 } 189 } 190 191 if (Sflag) { 192 (void)printf("%s ", ttype); 193 wrtermcap(tcapbuf); 194 } 195 196 if (sflag) { 197 /* 198 * Figure out what shell we're using. A hack, we look for an 199 * environmental variable SHELL ending in "csh". 200 */ 201 if ((p = getenv("SHELL")) && 202 !strcmp(p + strlen(p) - 3, "csh")) { 203 p = "set noglob;\nsetenv TERM %s;\nsetenv TERMCAP '"; 204 t = "';\nunset noglob;\n"; 205 } else { 206 p = "TERM=%s;\nTERMCAP='"; 207 t = "';\nexport TERMCAP TERM;\n"; 208 } 209 (void)printf(p, ttype); 210 wrtermcap(tcapbuf); 211 (void)printf(t); 212 } 213 214 exit(0); 215 } 216 217 /* 218 * Tell the user if a control key has been changed from the default value. 219 */ 220 void 221 report(name, which, def) 222 char *name; 223 int which; 224 u_int def; 225 { 226 u_int old, new; 227 char *bp, buf[1024]; 228 229 new = mode.c_cc[which]; 230 old = oldmode.c_cc[which]; 231 232 if (old == new && old == def) 233 return; 234 235 (void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to"); 236 237 bp = buf; 238 if (tgetstr("kb", &bp) && new == buf[0] && buf[1] == '\0') 239 (void)fprintf(stderr, "backspace.\n"); 240 else if (new == 0177) 241 (void)fprintf(stderr, "delete.\n"); 242 else if (new < 040) { 243 new ^= 0100; 244 (void)fprintf(stderr, "control-%c (^%c).\n", new, new); 245 } else 246 (void)fprintf(stderr, "%c.\n", new); 247 } 248 249 /* 250 * Convert the obsolete argument form into something that getopt can handle. 251 * This means that -e, -i and -k get default arguments supplied for them. 252 */ 253 void 254 obsolete(argv) 255 char *argv[]; 256 { 257 for (; *argv; ++argv) { 258 if (argv[0][0] != '-' || argv[1] && argv[1][0] != '-' || 259 argv[0][1] != 'e' && argv[0][1] != 'i' && 260 argv[0][1] != 'k' || argv[0][2] != '\0') 261 continue; 262 switch(argv[0][1]) { 263 case 'e': 264 argv[0] = "-e^H"; 265 break; 266 case 'i': 267 argv[0] = "-i^C"; 268 break; 269 case 'k': 270 argv[0] = "-k^U"; 271 break; 272 } 273 } 274 } 275 276 void 277 usage() 278 { 279 (void)fprintf(stderr, 280 "usage: tset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n"); 281 exit(1); 282 } 283