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