1 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 2 /* All Rights Reserved */ 3 4 5 /* 6 * Copyright (c) 1980 Regents of the University of California. 7 * All rights reserved. The Berkeley software License Agreement 8 * specifies the terms and conditions for redistribution. 9 */ 10 11 /* 12 * Copyright (c) 1983 - 1999 by Sun Microsystems, Inc. 13 * All rights reserved. 14 */ 15 16 #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ 17 18 /* 19 ** TSET -- set terminal modes 20 ** 21 ** This program does sophisticated terminal initialization. 22 ** I recommend that you include it in your .profile or .login 23 ** file to initialize whatever terminal you are on. 24 ** 25 ** There are several features: 26 ** 27 ** A special file or sequence (as controlled by the termcap file) 28 ** is sent to the terminal. 29 ** 30 ** Mode bits are set on a per-terminal_type basis (much better 31 ** than UNIX itself). This allows special delays, automatic 32 ** tabs, etc. 33 ** 34 ** Erase and Kill characters can be set to whatever you want. 35 ** Default is to change erase to control-H on a terminal which 36 ** can overstrike, and leave it alone on anything else. Kill 37 ** is always left alone unless specifically requested. These 38 ** characters can be represented as "^X" meaning control-X; 39 ** X is any character. 40 ** 41 ** Terminals which are dialups or plugboard types can be aliased 42 ** to whatever type you may have in your home or office. Thus, 43 ** if you know that when you dial up you will always be on a 44 ** TI 733, you can specify that fact to tset. You can represent 45 ** a type as "?type". This will ask you what type you want it 46 ** to be -- if you reply with just a newline, it will default 47 ** to the type given. 48 ** 49 ** The current terminal type can be queried. 50 ** 51 ** Usage: 52 ** tset [-] [-EC] [-eC] [-kC] [-iC] [-s] [-h] [-u] [-r] 53 ** [-m [ident] [test baudrate] :type] 54 ** [-Q] [-I] [-S] [type] 55 ** 56 ** In systems with environments, use: 57 ** eval `tset -s ...` 58 ** Actually, this doesn't work in old csh's. 59 ** Instead, use: 60 ** tset -s ... > tset.tmp 61 ** source tset.tmp 62 ** rm tset.tmp 63 ** or: 64 ** set noglob 65 ** set term=(`tset -S ....`) 66 ** setenv TERM $term[1] 67 ** setenv TERMCAP "$term[2]" 68 ** unset term 69 ** unset noglob 70 ** 71 ** Positional Parameters: 72 ** type -- the terminal type to force. If this is 73 ** specified, initialization is for this 74 ** terminal type. 75 ** 76 ** Flags: 77 ** - -- report terminal type. Whatever type is 78 ** decided on is reported. If no other flags 79 ** are stated, the only affect is to write 80 ** the terminal type on the standard output. 81 ** -r -- report to user in addition to other flags. 82 ** -EC -- set the erase character to C on all terminals 83 ** except those which cannot backspace (e.g., 84 ** a TTY 33). C defaults to control-H. 85 ** -eC -- set the erase character to C on all terminals. 86 ** C defaults to control-H. If not specified, 87 ** the erase character is untouched; however, if 88 ** not specified and the erase character is NULL 89 ** (zero byte), the erase character is set to CERASE. 90 ** -kC -- set the kill character to C on all terminals. 91 ** Default for C is control-U. If not specified, 92 ** the kill character is untouched; however, if 93 ** not specified and the kill character is NULL 94 ** (zero byte), the kill character is set to CKILL. 95 ** -iC -- set the interrupt character to C on all terminals. 96 ** Default for C is control-C. If not specified, the 97 ** interrupt character is untouched; however, if 98 ** not specified and the interrupt character is NULL 99 ** (zero byte), the interrupt character is set to 100 ** control-C. 101 ** -qC -- reserved for setable quit character. 102 ** -m -- map the system identified type to some user 103 ** specified type. The mapping can be baud rate 104 ** dependent. This replaces the old -d, -p flags. 105 ** (-d type -> -m dialup:type) 106 ** (-p type -> -m plug:type) 107 ** Syntax: -m identifier [test baudrate] :type 108 ** where: ``identifier'' is terminal type found in 109 ** /etc/ttys for this port, (abscence of an identifier 110 ** matches any identifier); ``test'' may be any combination 111 ** of > = < ! @; ``baudrate'' is as with stty(1); 112 ** ``type'' is the actual terminal type to use if the 113 ** mapping condition is met. Multiple maps are scanned 114 ** in order and the first match prevails. 115 ** -n -- If the new tty driver from UCB is available, this flag 116 ** will activate the new options for erase and kill 117 ** processing. This will be different for printers 118 ** and crt's. For crts, if the baud rate is < 1200 then 119 ** erase and kill don't remove characters from the screen. 120 ** -h -- don't read htmp file. Normally the terminal type 121 ** is determined by reading the htmp file or the 122 ** environment (unless some mapping is specified). 123 ** This forces a read of the ttytype file -- useful 124 ** when htmp is somehow wrong. (V6 only) 125 ** -u -- don't update htmp. It seemed like this should 126 ** be put in. Note that htmp is never actually 127 ** written if there are no changes, so don't bother 128 ** bother using this for efficiency reasons alone. 129 ** -s -- output setenv commands for TERM. This can be 130 ** used with 131 ** `tset -s ...` 132 ** and is to be prefered to: 133 ** setenv TERM `tset - ...` 134 ** because -s sets the TERMCAP variable also. 135 ** -S -- Similar to -s but outputs 2 strings suitable for 136 ** use in csh .login files as follows: 137 ** set noglob 138 ** set term=(`tset -S .....`) 139 ** setenv TERM $term[1] 140 ** setenv TERMCAP "$term[2]" 141 ** unset term 142 ** unset noglob 143 ** -Q -- be quiet. don't output 'Erase set to' etc. 144 ** -I -- don't do terminal initialization (is & if 145 ** strings). 146 ** -v -- On virtual terminal systems, don't set up a 147 ** virtual terminal. Otherwise tset will tell 148 ** the operating system what kind of terminal you 149 ** are on (if it is a known terminal) and fix up 150 ** the output of -s to use virtual terminal sequences. 151 ** 152 ** Files: 153 ** /etc/ttys 154 ** contains a terminal id -> terminal type 155 ** mapping; used when any user mapping is specified, 156 ** or the environment doesn't have TERM set. 157 ** /etc/termcap 158 ** a terminal_type -> terminal_capabilities 159 ** mapping. 160 ** 161 ** Return Codes: 162 ** -1 -- couldn't open termcap. 163 ** 1 -- bad terminal type, or standard output not tty. 164 ** 0 -- ok. 165 ** 166 ** Defined Constants: 167 ** DIALUP -- the type code for a dialup port. 168 ** PLUGBOARD -- the type code for a plugboard port. 169 ** ARPANET -- the type code for an arpanet port. 170 ** BACKSPACE -- control-H, the default for -e. 171 ** CNTL('U') -- control-U, the default for -k. 172 ** OLDERASE -- the ancient default erase character. 173 ** FILEDES -- the file descriptor to do the operation 174 ** on, nominally 1 or 2. 175 ** STDOUT -- the standard output file descriptor. 176 ** UIDMASK -- the bit pattern to mask with the getuid() 177 ** call to get just the user id. 178 ** GTTYN -- defines file containing generalized ttynames 179 ** and compiles code to look there. 180 ** 181 ** Requires: 182 ** Routines to handle htmp, ttys, and termcap. 183 ** 184 ** Compilation Flags: 185 ** OLDFLAGS -- must be defined to compile code for any of 186 ** the -d, -p, or -a flags. 187 ** OLDDIALUP -- accept the -d flag. 188 ** OLDPLUGBOARD -- accept the -p flag. 189 ** OLDARPANET -- accept the -a flag. 190 ** V6 -- if clear, use environments, not htmp. 191 ** also use TIOCSETN rather than stty to avoid flushing 192 ** GTTYN -- if set, compiles code to look at /etc/ttys. 193 ** 194 ** Trace Flags: 195 ** none 196 ** 197 ** Diagnostics: 198 ** Bad flag 199 ** An incorrect option was specified. 200 ** Too few args 201 ** more command line arguments are required. 202 ** Unexpected arg 203 ** wrong type of argument was encountered. 204 ** Cannot open ... 205 ** The specified file could not be openned. 206 ** Type ... unknown 207 ** An unknown terminal type was specified. 208 ** Cannot update htmp 209 ** Cannot update htmp file when the standard 210 ** output is not a terminal. 211 ** Erase set to ... 212 ** Telling that the erase character has been 213 ** set to the specified character. 214 ** Kill set to ... 215 ** Ditto for kill 216 ** Erase is ... Kill is ... 217 ** Tells that the erase/kill characters were 218 ** wierd before, but they are being left as-is. 219 ** Not a terminal 220 ** Set if FILEDES is not a terminal. 221 ** 222 ** Compilation Instructions: 223 ** cc -n -O tset.c -ltermlib 224 ** mv a.out tset 225 ** chown bin tset 226 ** chmod 4755 tset 227 ** 228 ** where 'bin' should be whoever owns the 'htmp' file. 229 ** If 'htmp' is 666, then tset need not be setuid. 230 ** 231 ** For version 6 the compile command should be: 232 ** cc -n -O -I/usr/include/retrofit tset.c -ltermlib -lretro -lS 233 ** 234 ** 235 ** History: 236 ** 1/81 -- Added alias checking for mapping identifiers. 237 ** 7/80 -- '-S' added. '-m' mapping added. TERMCAP string 238 ** cleaned up. 239 ** 3/80 -- Changed to use tputs. Prc & flush added. 240 ** 10/79 -- '-s' option extended to handle TERMCAP 241 ** variable, set noglob, quote the entry, 242 ** and know about the Bourne shell. Terminal 243 ** initialization moved to before any information 244 ** output so screen clears would not screw you. 245 ** '-Q' option added. 246 ** 8/79 -- '-' option alone changed to only output 247 ** type. '-s' option added. 'VERSION7' 248 ** changed to 'V6' for compatibility. 249 ** 12/78 -- modified for eventual migration to VAX/UNIX, 250 ** so the '-' option is changed to output only 251 ** the terminal type to STDOUT instead of 252 ** FILEDES. 253 ** 9/78 -- '-' and '-p' options added (now fully 254 ** compatible with ttytype!), and spaces are 255 ** permitted between the -d and the type. 256 ** 8/78 -- The sense of -h and -u were reversed, and the 257 ** -f flag is dropped -- same effect is available 258 ** by just stating the terminal type. 259 ** 10/77 -- Written. 260 */ 261 262 263 #define index strchr 264 #define rindex strrchr 265 #define curerase modes.c_cc[VERASE] 266 #define curkill modes.c_cc[VKILL] 267 #define curintr modes.c_cc[VINTR] 268 #define olderase oldmodes.c_cc[VERASE] 269 #define oldkill oldmodes.c_cc[VKILL] 270 #define oldintr oldmodes.c_cc[VINTR] 271 272 #include <stdio.h> 273 #include <termio.h> 274 #include <signal.h> 275 276 277 #define YES 1 278 #define NO 0 279 #undef CNTL 280 #define CNTL(c) ((c)&037) 281 #define BACKSPACE (CNTL('H')) 282 #define isdigit(c) (c >= '0' && c <= '9') 283 #define isalnum(c) (c > ' ' && (index("<@=>!:|\177", c) == NULL)) 284 #define OLDERASE '#' 285 286 /* default special characters */ 287 #ifndef CERASE 288 #define CERASE '\177' 289 #endif 290 #ifndef CKILL 291 #define CKILL CNTL('U') 292 #endif 293 #ifndef CINTR 294 #define CINTR CNTL('C') 295 #endif 296 #ifndef CDSUSP 297 #define CQUIT 034 /* FS, ^\ */ 298 #define CSTART CNTL('Q') 299 #define CSTOP CNTL('S') 300 #define CEOF CNTL('D') 301 #define CEOT CEOF 302 #define CBRK 0377 303 #define CSUSP CNTL('Z') 304 #define CDSUSP CNTL('Y') 305 #define CRPRNT CNTL('R') 306 #define CFLUSH CNTL('O') 307 #define CWERASE CNTL('W') 308 #define CLNEXT CNTL('V') 309 #endif 310 311 #define FILEDES 2 /* do gtty/stty on this descriptor */ 312 #define STDOUT 1 /* output of -s/-S to this descriptor */ 313 314 #define UIDMASK -1 315 316 #define USAGE "usage: tset [-] [-rsIQS] [-eC] [-kC] [-iC] [-m [ident][test speed]:type] [type]\n" 317 318 #define OLDFLAGS 319 #define DIALUP "dialup" 320 #define OLDDIALUP "sd" 321 #define PLUGBOARD "plugboard" 322 #define OLDPLUGBOARD "sp" 323 /*** 324 #define ARPANET "arpanet" 325 #define OLDARPANET "sa" 326 /***/ 327 328 #define DEFTYPE "unknown" 329 330 #define NOTTY 'x' 331 332 /* 333 * Baud Rate Conditionals 334 */ 335 #define ANY 0 336 #define GT 1 337 #define EQ 2 338 #define LT 4 339 #define GE (GT|EQ) 340 #define LE (LT|EQ) 341 #define NE (GT|LT) 342 #define ALL (GT|EQ|LT) 343 344 345 346 #define NMAP 10 347 348 struct map { 349 char *Ident; 350 char Test; 351 char Speed; 352 char *Type; 353 } map[NMAP]; 354 355 struct map *Map = map; 356 357 /* This should be available in an include file */ 358 struct 359 { 360 char *string; 361 int speed; 362 int baudrate; 363 } speeds[] = { 364 "0", B0, 0, 365 "50", B50, 50, 366 "75", B75, 75, 367 "110", B110, 110, 368 "134", B134, 134, 369 "134.5",B134, 134, 370 "150", B150, 150, 371 "200", B200, 200, 372 "300", B300, 300, 373 "600", B600, 600, 374 "1200", B1200, 1200, 375 "1800", B1800, 1800, 376 "2400", B2400, 2400, 377 "4800", B4800, 4800, 378 "9600", B9600, 9600, 379 "19200",EXTA, 19200, 380 "exta", EXTA, 19200, 381 "extb", EXTB, 38400, 382 "57600",B57600, 57600, 383 "76800",B76800, 76800, 384 "115200",B115200,115200, 385 "153600",B153600,153600, 386 "230400",B230400,230400, 387 "307200",B307200,307200, 388 "460800",B460800,460800, 389 0, 390 }; 391 392 signed char Erase_char; /* new erase character */ 393 char Kill_char; /* new kill character */ 394 char Intr_char; /* new interrupt character */ 395 char Specialerase; /* set => Erase_char only on terminals with backspace */ 396 397 char Ttyid = NOTTY; /* terminal identifier */ 398 char *TtyType; /* type of terminal */ 399 char *DefType; /* default type if none other computed */ 400 char *NewType; /* mapping identifier based on old flags */ 401 int Mapped; /* mapping has been specified */ 402 int Dash_u; /* don't update htmp */ 403 int Dash_h; /* don't read htmp */ 404 int DoSetenv; /* output setenv commands */ 405 int BeQuiet; /* be quiet */ 406 int NoInit; /* don't output initialization string */ 407 int IsReset; /* invoked as reset */ 408 int Report; /* report current type */ 409 int Ureport; /* report to user */ 410 int RepOnly; /* report only */ 411 int CmndLine; /* output full command lines (-s option) */ 412 int Ask; /* ask user for termtype */ 413 int DoVirtTerm = YES; /* Set up a virtual terminal */ 414 int PadBaud; /* Min rate of padding needed */ 415 416 #define CAPBUFSIZ 1024 417 char Capbuf[CAPBUFSIZ]; /* line from /etc/termcap for this TtyType */ 418 char *Ttycap; /* termcap line from termcap or environ */ 419 420 char Aliasbuf[128]; 421 char *Alias[16]; 422 423 extern char *strcpy(); 424 extern char *index(); 425 426 struct delay 427 { 428 int d_delay; 429 int d_bits; 430 }; 431 432 #include "tset.delays.h" 433 434 struct termio mode; 435 struct termio oldmode; 436 struct termios modes; 437 struct termios oldmodes; 438 int istermios; 439 440 char reset(); /* Routine for checking&resetting chars */ 441 int prc(); 442 443 main(argc, argv) 444 int argc; 445 char *argv[]; 446 { 447 char buf[CAPBUFSIZ]; 448 char termbuf[32]; 449 auto char *bufp; 450 register char *p; 451 char *command; 452 register int i; 453 int Break; 454 int Not; 455 char *nextarg(); 456 char *mapped(); 457 extern char *rindex(); 458 struct winsize win; 459 extern char *getenv(); 460 extern char *tgetstr(); 461 char bs_char; 462 int csh; 463 int settle = NO; 464 void setmode(); 465 extern char PC; 466 extern short ospeed; 467 468 if ((istermios = ioctl(FILEDES, TCGETS, (char *)&modes)) < 0) { 469 if (ioctl(FILEDES, TCGETA, (char *)&mode) < 0) 470 { 471 prs("Not a terminal\n"); 472 exit(1); 473 } 474 bmove((char *)&mode, (char *)&oldmode, sizeof mode); 475 modes.c_lflag = oldmodes.c_lflag = mode.c_lflag; 476 modes.c_oflag = oldmodes.c_oflag = mode.c_oflag; 477 modes.c_iflag = oldmodes.c_iflag = mode.c_iflag; 478 modes.c_cflag = oldmodes.c_cflag = mode.c_cflag; 479 for(i = 0; i < NCC; i++) 480 modes.c_cc[i] = oldmodes.c_cc[i] = mode.c_cc[i]; 481 } else 482 bmove((char *)&modes, (char *)&oldmodes, sizeof modes); 483 ospeed = cfgetospeed(&modes); 484 (void) signal(SIGINT, setmode); 485 (void) signal(SIGQUIT, setmode); 486 (void) signal(SIGTERM, setmode); 487 488 if (command = rindex(argv[0], '/')) 489 command++; 490 else 491 command = argv[0]; 492 if (sequal(command, "reset") ) 493 { 494 /* 495 * Reset the teletype mode bits to a sensible state. 496 * Copied from the program by Kurt Shoens & Mark Horton. 497 * Very useful after crapping out in raw. 498 */ 499 if ((istermios = ioctl(FILEDES, TCGETS, (char *)&modes)) < 0) { 500 (void) ioctl(FILEDES, TCGETA, (char *)&mode); 501 modes.c_lflag = mode.c_lflag; 502 modes.c_oflag = mode.c_oflag; 503 modes.c_iflag = mode.c_iflag; 504 modes.c_cflag = mode.c_cflag; 505 for(i = 0; i < NCC; i++) 506 modes.c_cc[i] = mode.c_cc[i]; 507 } 508 curerase = reset(curerase, CERASE); 509 curkill = reset(curkill, CKILL); 510 curintr = reset(curintr, CINTR); 511 modes.c_cc[VQUIT] = reset(modes.c_cc[VQUIT], CQUIT); 512 modes.c_cc[VEOF] = reset(modes.c_cc[VEOF], CEOF); 513 514 modes.c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON); 515 modes.c_iflag &= ~(IGNBRK|PARMRK|INPCK|INLCR|IGNCR|IUCLC|IXOFF); 516 modes.c_oflag |= (OPOST|ONLCR); 517 modes.c_oflag &= ~(OLCUC|OCRNL|ONOCR|ONLRET|OFILL|OFDEL| 518 NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); 519 modes.c_cflag |= (CS7|CREAD); 520 modes.c_cflag &= ~(PARODD|CLOCAL); 521 modes.c_lflag |= (ISIG|ICANON|ECHO|ECHOK); 522 modes.c_lflag &= ~(XCASE|ECHONL|NOFLSH); 523 if (istermios < 0) { 524 mode.c_lflag = modes.c_lflag; 525 mode.c_oflag = modes.c_oflag; 526 mode.c_iflag = modes.c_iflag; 527 mode.c_cflag = modes.c_cflag; 528 for(i = 0; i < NCC; i++) 529 mode.c_cc[i] = modes.c_cc[i]; 530 (void) ioctl(FILEDES, TCSETAW, (char *)&mode); 531 } else 532 (void) ioctl(FILEDES, TCSETSW, (char *)&modes); 533 Dash_u = YES; 534 BeQuiet = YES; 535 IsReset = YES; 536 } 537 else if (argc == 2 && sequal(argv[1], "-")) 538 { 539 RepOnly = YES; 540 Dash_u = YES; 541 } 542 argc--; 543 544 /* scan argument list and collect flags */ 545 while (--argc >= 0) 546 { 547 p = *++argv; 548 if (*p == '-') 549 { 550 if (*++p == NULL) 551 Report = YES; /* report current terminal type */ 552 else while (*p) switch (*p++) 553 { 554 555 case 'r': /* report to user */ 556 Ureport = YES; 557 continue; 558 559 case 'E': /* special erase: operate on all but TTY33 */ 560 Specialerase = YES; 561 /* explicit fall-through to -e case */ 562 563 case 'e': /* erase character */ 564 if (*p == NULL) 565 Erase_char = -1; 566 else 567 { 568 if (*p == '^' && p[1] != NULL) 569 if (*++p == '?') 570 Erase_char = '\177'; 571 else 572 Erase_char = CNTL(*p); 573 else 574 Erase_char = *p; 575 p++; 576 } 577 continue; 578 579 case 'i': /* interrupt character */ 580 if (*p == NULL) 581 Intr_char = CNTL('C'); 582 else 583 { 584 if (*p == '^' && p[1] != NULL) 585 if (*++p == '?') 586 Intr_char = '\177'; 587 else 588 Intr_char = CNTL(*p); 589 else 590 Intr_char = *p; 591 p++; 592 } 593 continue; 594 595 case 'k': /* kill character */ 596 if (*p == NULL) 597 Kill_char = CNTL('U'); 598 else 599 { 600 if (*p == '^' && p[1] != NULL) 601 if (*++p == '?') 602 Kill_char = '\177'; 603 else 604 Kill_char = CNTL(*p); 605 else 606 Kill_char = *p; 607 p++; 608 } 609 continue; 610 611 # ifdef OLDFLAGS 612 # ifdef OLDDIALUP 613 case 'd': /* dialup type */ 614 NewType = DIALUP; 615 goto mapold; 616 # endif 617 618 # ifdef OLDPLUGBOARD 619 case 'p': /* plugboard type */ 620 NewType = PLUGBOARD; 621 goto mapold; 622 # endif 623 624 # ifdef OLDARPANET 625 case 'a': /* arpanet type */ 626 Newtype = ARPANET; 627 goto mapold; 628 # endif 629 630 mapold: Map->Ident = NewType; 631 Map->Test = ALL; 632 if (*p == NULL) 633 { 634 p = nextarg(argc--, argv++); 635 } 636 Map->Type = p; 637 Map++; 638 Mapped = YES; 639 p = ""; 640 continue; 641 # endif 642 643 case 'm': /* map identifier to type */ 644 /* This code is very loose. Almost no 645 ** syntax checking is done!! However, 646 ** illegal syntax will only produce 647 ** weird results. 648 */ 649 if (*p == NULL) 650 { 651 p = nextarg(argc--, argv++); 652 } 653 if (isalnum(*p)) 654 { 655 Map->Ident = p; /* identifier */ 656 while (isalnum(*p)) p++; 657 } 658 else 659 Map->Ident = ""; 660 Break = NO; 661 Not = NO; 662 while (!Break) switch (*p) 663 { 664 case NULL: 665 p = nextarg(argc--, argv++); 666 continue; 667 668 case ':': /* mapped type */ 669 *p++ = NULL; 670 Break = YES; 671 continue; 672 673 case '>': /* conditional */ 674 Map->Test |= GT; 675 *p++ = NULL; 676 continue; 677 678 case '<': /* conditional */ 679 Map->Test |= LT; 680 *p++ = NULL; 681 continue; 682 683 case '=': /* conditional */ 684 case '@': 685 Map->Test |= EQ; 686 *p++ = NULL; 687 continue; 688 689 case '!': /* invert conditions */ 690 Not = ~Not; 691 *p++ = NULL; 692 continue; 693 694 case 'B': /* Baud rate */ 695 p++; 696 /* intentional fallthru */ 697 default: 698 if (isdigit(*p) || *p == 'e') 699 { 700 Map->Speed = baudrate(p); 701 while (isalnum(*p) || *p == '.') 702 p++; 703 } 704 else 705 Break = YES; 706 continue; 707 } 708 if (Not) /* invert sense of test */ 709 { 710 Map->Test = (~(Map->Test))&ALL; 711 } 712 if (*p == NULL) 713 { 714 p = nextarg(argc--, argv++); 715 } 716 Map->Type = p; 717 p = ""; 718 Map++; 719 Mapped = YES; 720 continue; 721 722 case 'h': /* don't get type from htmp or env */ 723 Dash_h = YES; 724 continue; 725 726 case 'u': /* don't update htmp */ 727 Dash_u = YES; 728 continue; 729 730 case 's': /* output setenv commands */ 731 DoSetenv = YES; 732 CmndLine = YES; 733 continue; 734 735 case 'S': /* output setenv strings */ 736 DoSetenv = YES; 737 CmndLine = NO; 738 continue; 739 740 case 'Q': /* be quiet */ 741 BeQuiet = YES; 742 continue; 743 744 case 'I': /* no initialization */ 745 NoInit = YES; 746 continue; 747 748 case 'A': /* Ask user */ 749 Ask = YES; 750 continue; 751 752 case 'v': /* no virtual terminal */ 753 DoVirtTerm = NO; 754 continue; 755 756 default: 757 *p-- = NULL; 758 fatal("Bad flag -", p); 759 } 760 } 761 else 762 { 763 /* terminal type */ 764 DefType = p; 765 } 766 } 767 768 if (DefType) 769 { 770 if (Mapped) 771 { 772 Map->Ident = ""; /* means "map any type" */ 773 Map->Test = ALL; /* at all baud rates */ 774 Map->Type = DefType; /* to the default type */ 775 } 776 else 777 TtyType = DefType; 778 } 779 780 /* 781 * Get rid of $TERMCAP, if it's there, so we get a real 782 * entry from /etc/termcap. This prevents us from being 783 * fooled by out of date stuff in the environment, and 784 * makes tabs work right on CB/Unix. 785 */ 786 bufp = getenv("TERMCAP"); 787 if (bufp && *bufp != '/') 788 (void) strcpy(bufp-8, "NOTHING"); /* overwrite only "TERMCAP" */ 789 /* get current idea of terminal type from environment */ 790 if (!Dash_h && TtyType == 0) 791 TtyType = getenv("TERM"); 792 793 if (!RepOnly && Ttyid == NOTTY && (TtyType == 0 || !Dash_h)) 794 Ttyid = ttyname(FILEDES); 795 796 /* If still undefined, use DEFTYPE */ 797 if (TtyType == 0) 798 { 799 TtyType = DEFTYPE; 800 } 801 802 /* check for dialup or other mapping */ 803 if (Mapped) 804 { 805 if (!(Alias[0] && isalias(TtyType))) 806 if (tgetent(Capbuf, TtyType) > 0) 807 makealias(Capbuf); 808 TtyType = mapped(TtyType); 809 } 810 811 /* TtyType now contains a pointer to the type of the terminal */ 812 /* If the first character is '?', ask the user */ 813 if (TtyType[0] == '?') 814 { 815 Ask = YES; 816 TtyType++; 817 if (TtyType[0] == '\0') 818 TtyType = DEFTYPE; 819 } 820 if (Ask) 821 { 822 ask: 823 prs("TERM = ("); 824 prs(TtyType); 825 prs(") "); 826 flush(); 827 828 /* read the terminal. If not empty, set type */ 829 i = read(2, termbuf, sizeof termbuf - 1); 830 if (i > 0) 831 { 832 if (termbuf[i - 1] == '\n') 833 i--; 834 termbuf[i] = '\0'; 835 if (termbuf[0] != '\0') 836 TtyType = termbuf; 837 } 838 } 839 840 /* get terminal capabilities */ 841 if (!(Alias[0] && isalias(TtyType))) { 842 switch (tgetent(Capbuf, TtyType)) 843 { 844 case -1: 845 prs("Cannot find termcap\n"); 846 flush(); 847 exit(-1); 848 849 case 0: 850 prs("Type "); 851 prs(TtyType); 852 prs(" unknown\n"); 853 flush(); 854 if (DoSetenv) 855 { 856 TtyType = DEFTYPE; 857 Alias[0] = '\0'; 858 goto ask; 859 } 860 else 861 exit(1); 862 } 863 } 864 Ttycap = Capbuf; 865 866 if (!RepOnly) 867 { 868 /* determine erase and kill characters */ 869 if (Specialerase && !tgetflag("bs")) 870 Erase_char = 0; 871 bufp = buf; 872 p = tgetstr("kb", &bufp); 873 if (p == NULL || p[1] != '\0') 874 p = tgetstr("bc", &bufp); 875 if (p != NULL && p[1] == '\0') 876 bs_char = p[0]; 877 else if (tgetflag("bs")) 878 bs_char = BACKSPACE; 879 else 880 bs_char = 0; 881 /* 882 * The next statement can't be fixed, because now users 883 * depend on keeping their erase character as DEL if the 884 * system set it there. People who want backspace have 885 * to say tset -e. 886 */ 887 if (Erase_char == 0 && !tgetflag("os") && curerase == OLDERASE) 888 { 889 if (tgetflag("bs") || bs_char != 0) 890 Erase_char = -1; 891 } 892 if (Erase_char < 0) 893 Erase_char = (bs_char != 0) ? bs_char : BACKSPACE; 894 895 if (curerase == 0) 896 curerase = CERASE; 897 if (Erase_char != 0) 898 curerase = Erase_char; 899 900 if (curintr == 0) 901 curintr = CINTR; 902 if (Intr_char != 0) 903 curintr = Intr_char; 904 905 if (curkill == 0) 906 curkill = CKILL; 907 if (Kill_char != 0) 908 curkill = Kill_char; 909 910 /* set modes */ 911 PadBaud = tgetnum("pb"); /* OK if fails */ 912 for (i=0; speeds[i].string; i++) 913 if (speeds[i].baudrate == PadBaud) { 914 PadBaud = speeds[i].speed; 915 break; 916 } 917 setdelay("dC", CRdelay, CRbits, &modes.c_oflag); 918 setdelay("dN", NLdelay, NLbits, &modes.c_oflag); 919 setdelay("dB", BSdelay, BSbits, &modes.c_oflag); 920 setdelay("dF", FFdelay, FFbits, &modes.c_oflag); 921 setdelay("dT", TBdelay, TBbits, &modes.c_oflag); 922 setdelay("dV", VTdelay, VTbits, &modes.c_oflag); 923 924 if (tgetflag("UC") || (command[0] & 0140) == 0100) { 925 modes.c_iflag |= IUCLC; 926 modes.c_oflag |= OLCUC; 927 modes.c_cflag |= XCASE; 928 } 929 else if (tgetflag("LC")) { 930 modes.c_iflag &= ~IUCLC; 931 modes.c_oflag &= ~OLCUC; 932 modes.c_cflag &= ~XCASE; 933 } 934 modes.c_iflag &= ~(PARMRK|INPCK); 935 modes.c_lflag |= ICANON; 936 if (tgetflag("EP")) { 937 modes.c_iflag |= INPCK; 938 modes.c_cflag |= PARENB; 939 modes.c_cflag &= ~PARODD; 940 } 941 if (tgetflag("OP")) { 942 modes.c_iflag |= INPCK; 943 modes.c_cflag |= PARENB; 944 modes.c_cflag |= PARODD; 945 } 946 947 modes.c_oflag |= ONLCR; 948 modes.c_iflag |= ICRNL; 949 modes.c_lflag |= ECHO; 950 modes.c_oflag |= TAB3; 951 if (tgetflag("NL")) { /* new line, not line feed */ 952 modes.c_oflag &= ~ONLCR; 953 modes.c_iflag &= ~ICRNL; 954 } 955 if (tgetflag("HD")) /* half duplex */ 956 modes.c_lflag &= ~ECHO; 957 if (tgetflag("pt")) /* print tabs */ 958 modes.c_oflag &= ~TAB3; 959 960 modes.c_lflag |= (ECHOE|ECHOK); 961 if (tgetflag("hc")) 962 { /** set printer modes **/ 963 modes.c_lflag &= ~ECHOE; 964 } 965 966 /* get pad character */ 967 bufp = buf; 968 if (tgetstr("pc", &bufp) != 0) 969 PC = buf[0]; 970 971 /* output startup string */ 972 if (!NoInit) 973 { 974 if (oldmodes.c_oflag&(TAB3|ONLCR|OCRNL|ONLRET)) 975 { 976 oldmodes.c_oflag &= (TAB3|ONLCR|OCRNL|ONLRET); 977 setmode(-1); 978 } 979 if (settabs()) { 980 settle = YES; 981 flush(); 982 } 983 bufp = buf; 984 if (IsReset && tgetstr("rs", &bufp) != 0 || 985 tgetstr("is", &bufp) != 0) 986 { 987 tputs(buf, 0, prc); 988 settle = YES; 989 flush(); 990 } 991 bufp = buf; 992 if (IsReset && tgetstr("rf", &bufp) != 0 || 993 tgetstr("if", &bufp) != 0) 994 { 995 cat(buf); 996 settle = YES; 997 } 998 if (settle) 999 { 1000 prc('\r'); 1001 if (IsReset) 1002 prc('\n'); /* newline too */ 1003 flush(); 1004 sleep(1); /* let terminal settle down */ 1005 } 1006 } 1007 1008 setmode(0); /* set new modes, if they've changed */ 1009 1010 /* set up environment for the shell we are using */ 1011 /* (this code is rather heuristic, checking for $SHELL */ 1012 /* ending in the 3 characters "csh") */ 1013 csh = NO; 1014 if (DoSetenv) 1015 { 1016 char *sh; 1017 1018 if ((sh = getenv("SHELL")) && (i = strlen(sh)) >= 3) 1019 { 1020 if ((csh = sequal(&sh[i-3], "csh")) && CmndLine) 1021 (void) write(STDOUT, "set noglob;\n", 12); 1022 } 1023 if (!csh) 1024 /* running Bourne shell */ 1025 (void) write(STDOUT, "export TERMCAP TERM;\n", 21); 1026 } 1027 } 1028 1029 /* report type if appropriate */ 1030 if (DoSetenv || Report || Ureport) 1031 { 1032 /* if type is the short name, find first alias (if any) */ 1033 makealias(Ttycap); 1034 if (sequal(TtyType, Alias[0]) && Alias[1]) { 1035 TtyType = Alias[1]; 1036 } 1037 1038 if (DoSetenv) 1039 { 1040 if (csh) 1041 { 1042 if (CmndLine) 1043 (void) write(STDOUT, "setenv TERM ", 12); 1044 (void) write(STDOUT, TtyType, strlen(TtyType)); 1045 (void) write(STDOUT, " ", 1); 1046 if (CmndLine) 1047 (void) write(STDOUT, ";\n", 2); 1048 } 1049 else 1050 { 1051 (void) write(STDOUT, "TERM=", 5); 1052 (void) write(STDOUT, TtyType, strlen(TtyType)); 1053 (void) write(STDOUT, ";\n", 2); 1054 } 1055 } 1056 else if (Report) 1057 { 1058 (void) write(STDOUT, TtyType, strlen(TtyType)); 1059 (void) write(STDOUT, "\n", 1); 1060 } 1061 if (Ureport) 1062 { 1063 prs("Terminal type is "); 1064 prs(TtyType); 1065 prs("\n"); 1066 flush(); 1067 } 1068 1069 if (DoSetenv) 1070 { 1071 if (csh) 1072 { 1073 if (CmndLine) 1074 (void) write(STDOUT, "setenv TERMCAP '", 16); 1075 } 1076 else 1077 (void) write(STDOUT, "TERMCAP='", 9); 1078 wrtermcap(Ttycap); 1079 if (csh) 1080 { 1081 if (CmndLine) 1082 { 1083 (void) write(STDOUT, "';\n", 3); 1084 (void) write(STDOUT, "unset noglob;\n", 14); 1085 } 1086 } 1087 else 1088 (void) write(STDOUT, "';\n", 3); 1089 } 1090 } 1091 1092 if (RepOnly) 1093 exit(0); 1094 1095 /* tell about changing erase, kill and interrupt characters */ 1096 reportek("Erase", curerase, olderase, CERASE); 1097 reportek("Kill", curkill, oldkill, CKILL); 1098 reportek("Interrupt", curintr, oldintr, CINTR); 1099 1100 exit(0); 1101 } 1102 1103 /* 1104 * Set the hardware tabs on the terminal, using the ct (clear all tabs), 1105 * st (set one tab) and ch (horizontal cursor addressing) capabilities. 1106 * This is done before if and is, so they can patch in case we blow this. 1107 */ 1108 settabs() 1109 { 1110 char caps[100]; 1111 char *capsp = caps; 1112 char *clear_tabs, *set_tab, *set_column, *set_pos; 1113 char *tg_out, *tgoto(); 1114 int c; 1115 extern char *tgetstr(); 1116 int lines, columns; 1117 1118 clear_tabs = tgetstr("ct", &capsp); 1119 set_tab = tgetstr("st", &capsp); 1120 set_column = tgetstr("ch", &capsp); 1121 if (set_column == 0) 1122 set_pos = tgetstr("cm", &capsp); 1123 1124 if (clear_tabs && set_tab) { 1125 prc('\r'); /* force to be at left margin */ 1126 tputs(clear_tabs, 0, prc); 1127 } 1128 if (set_tab) { 1129 columns = tgetnum("co"); 1130 lines = tgetnum("li"); 1131 for (c=0; c<columns; c += 8) { 1132 /* get to that column. */ 1133 tg_out = "OOPS"; /* also returned by tgoto */ 1134 if (set_column) 1135 tg_out = tgoto(set_column, 0, c); 1136 if (*tg_out == 'O' && set_pos) 1137 tg_out = tgoto(set_pos, c, lines-1); 1138 if (*tg_out != 'O') 1139 tputs(tg_out, 1, prc); 1140 else if (c != 0) { 1141 prc(' '); prc(' '); prc(' '); prc(' '); 1142 prc(' '); prc(' '); prc(' '); prc(' '); 1143 } 1144 /* set the tab */ 1145 tputs(set_tab, 0, prc); 1146 } 1147 prc('\r'); 1148 return 1; 1149 } 1150 return 0; 1151 } 1152 1153 void setmode(flag) 1154 int flag; 1155 /* flag serves several purposes: 1156 * if called as the result of a signal, flag will be > 0. 1157 * if called from terminal init, flag == -1 means reset "oldmode". 1158 * called with flag == 0 at end of normal mode processing. 1159 */ 1160 { 1161 struct termio *ttymode; 1162 struct termios *ttymodes; 1163 register int i; 1164 1165 ttymode = (struct termio *)0; 1166 ttymodes = (struct termios *)0; 1167 1168 if (flag < 0) { /* unconditionally reset oldmode (called from init) */ 1169 if (istermios < 0) { 1170 oldmode.c_lflag = oldmodes.c_lflag; 1171 oldmode.c_oflag = oldmodes.c_oflag; 1172 oldmode.c_iflag = oldmodes.c_iflag; 1173 oldmode.c_cflag = oldmodes.c_cflag; 1174 for(i = 0; i < NCC; i++) 1175 oldmode.c_cc[i] = oldmodes.c_cc[i]; 1176 ttymode = &oldmode; 1177 } else 1178 ttymodes = &oldmodes; 1179 } else { 1180 if (istermios < 0) { 1181 oldmode.c_lflag = oldmodes.c_lflag; 1182 oldmode.c_oflag = oldmodes.c_oflag; 1183 oldmode.c_iflag = oldmodes.c_iflag; 1184 oldmode.c_cflag = oldmodes.c_cflag; 1185 for(i = 0; i < NCC; i++) 1186 oldmode.c_cc[i] = oldmodes.c_cc[i]; 1187 mode.c_lflag = modes.c_lflag; 1188 mode.c_oflag = modes.c_oflag; 1189 mode.c_iflag = modes.c_iflag; 1190 mode.c_cflag = modes.c_cflag; 1191 for(i = 0; i < NCC; i++) 1192 mode.c_cc[i] = modes.c_cc[i]; 1193 if (!bequal((char *)&mode, (char *)&oldmode, sizeof mode)) 1194 ttymode = &mode; 1195 } else if (!bequal((char *)&modes, (char *)&oldmodes, 1196 sizeof modes)) 1197 ttymodes = &modes; 1198 } 1199 1200 if (ttymode) 1201 { 1202 (void) ioctl(FILEDES, TCSETAW, (char *)ttymode); 1203 } else if (ttymodes) { 1204 (void) ioctl(FILEDES, TCSETSW, (char *)ttymodes); 1205 } 1206 if (flag > 0) /* trapped signal */ 1207 exit(1); 1208 } 1209 1210 reportek(name, new, old, def) 1211 char *name; 1212 char old; 1213 char new; 1214 char def; 1215 { 1216 register char o; 1217 register char n; 1218 register char *p; 1219 char buf[32]; 1220 char *bufp; 1221 extern char *tgetstr(); 1222 1223 if (BeQuiet) 1224 return; 1225 o = old; 1226 n = new; 1227 1228 if (o == n && n == def) 1229 return; 1230 prs(name); 1231 if (o == n) 1232 prs(" is "); 1233 else 1234 prs(" set to "); 1235 bufp = buf; 1236 if (tgetstr("kb", &bufp) > (char *)0 && n == buf[0] && buf[1] == NULL) 1237 prs("Backspace\n"); 1238 else if (n == 0177) 1239 prs("Delete\n"); 1240 else 1241 { 1242 if (n < 040) 1243 { 1244 prs("Ctrl-"); 1245 n ^= 0100; 1246 } 1247 p = "x\n"; 1248 p[0] = n; 1249 prs(p); 1250 } 1251 flush(); 1252 } 1253 1254 1255 1256 1257 setdelay(cap, dtab, bits, flags) 1258 char *cap; 1259 struct delay dtab[]; 1260 int bits; 1261 short *flags; 1262 { 1263 register int i; 1264 register struct delay *p; 1265 extern short ospeed; 1266 1267 /* see if this capability exists at all */ 1268 i = tgetnum(cap); 1269 if (i < 0) 1270 i = 0; 1271 /* No padding at speeds below PadBaud */ 1272 if (PadBaud > ospeed) 1273 i = 0; 1274 1275 /* clear out the bits, replace with new ones */ 1276 *flags &= ~bits; 1277 1278 /* scan dtab for first entry with adequate delay */ 1279 for (p = dtab; p->d_delay >= 0; p++) 1280 { 1281 if (p->d_delay >= i) 1282 { 1283 p++; 1284 break; 1285 } 1286 } 1287 1288 /* use last entry if none will do */ 1289 *flags |= (--p)->d_bits; 1290 } 1291 1292 1293 prs(s) 1294 char *s; 1295 { 1296 while (*s != '\0') 1297 prc(*s++); 1298 } 1299 1300 1301 char OutBuf[256]; 1302 int OutPtr; 1303 1304 prc(c) 1305 char c; 1306 { 1307 OutBuf[OutPtr++] = c; 1308 if (OutPtr >= sizeof OutBuf) 1309 flush(); 1310 } 1311 1312 flush() 1313 { 1314 if (OutPtr > 0) 1315 (void) write(2, OutBuf, OutPtr); 1316 OutPtr = 0; 1317 } 1318 1319 1320 cat(file) 1321 char *file; 1322 { 1323 register int fd; 1324 register int i; 1325 char buf[BUFSIZ]; 1326 1327 fd = open(file, 0); 1328 if (fd < 0) 1329 { 1330 prs("Cannot open "); 1331 prs(file); 1332 prs("\n"); 1333 flush(); 1334 return; 1335 } 1336 1337 while ((i = read(fd, buf, BUFSIZ)) > 0) 1338 (void) write(FILEDES, buf, i); 1339 1340 (void) close(fd); 1341 } 1342 1343 1344 1345 bmove(from, to, length) 1346 char *from; 1347 char *to; 1348 int length; 1349 { 1350 register char *p, *q; 1351 register int i; 1352 1353 i = length; 1354 p = from; 1355 q = to; 1356 1357 while (i-- > 0) 1358 *q++ = *p++; 1359 } 1360 1361 1362 1363 bequal(a, b, len) /* must be same thru len chars */ 1364 char *a; 1365 char *b; 1366 int len; 1367 { 1368 register char *p, *q; 1369 register int i; 1370 1371 i = len; 1372 p = a; 1373 q = b; 1374 1375 while ((*p == *q) && --i > 0) 1376 { 1377 p++; q++; 1378 } 1379 return ((*p == *q) && i >= 0); 1380 } 1381 1382 sequal(a, b) /* must be same thru NULL */ 1383 char *a; 1384 char *b; 1385 { 1386 register char *p = a, *q = b; 1387 1388 while (*p && *q && (*p == *q)) 1389 { 1390 p++; q++; 1391 } 1392 return (*p == *q); 1393 } 1394 1395 makealias(buf) 1396 char *buf; 1397 { 1398 register int i; 1399 register char *a; 1400 register char *b; 1401 1402 Alias[0] = a = Aliasbuf; 1403 b = buf; 1404 i = 1; 1405 while (*b && *b != ':') { 1406 if (*b == '|') { 1407 *a++ = NULL; 1408 Alias[i++] = a; 1409 b++; 1410 } 1411 else 1412 *a++ = *b++; 1413 } 1414 *a = NULL; 1415 Alias[i] = NULL; 1416 # ifdef DEB 1417 for(i = 0; Alias[i]; printf("A:%s\n", Alias[i++])); 1418 # endif 1419 } 1420 1421 isalias(ident) /* is ident same as one of the aliases? */ 1422 char *ident; 1423 { 1424 char **a = Alias; 1425 1426 if (*a) 1427 while (*a) 1428 if (sequal(ident, *a)) 1429 return(YES); 1430 else 1431 a++; 1432 return(NO); 1433 } 1434 1435 1436 /* 1437 * routine to output the string for the environment TERMCAP variable 1438 */ 1439 #define WHITE(c) (c == ' ' || c == '\t') 1440 char delcap[128][2]; 1441 int ncap = 0; 1442 1443 wrtermcap(bp) 1444 char *bp; 1445 { 1446 char buf[CAPBUFSIZ]; 1447 char *p = buf; 1448 char *tp; 1449 char *putbuf(); 1450 int space, empty; 1451 1452 /* discard names with blanks */ 1453 /** May not be desireable ? **/ 1454 while (*bp && *bp != ':') { 1455 if (*bp == '|') { 1456 tp = bp+1; 1457 space = NO; 1458 while (*tp && *tp != '|' && *tp != ':') { 1459 space = (space || WHITE(*tp) ); 1460 tp++; 1461 } 1462 if (space) { 1463 bp = tp; 1464 continue; 1465 } 1466 } 1467 *p++ = *bp++; 1468 } 1469 /**/ 1470 1471 while (*bp) { 1472 switch (*bp) { 1473 case ':': /* discard empty, cancelled or dupl fields */ 1474 tp = bp+1; 1475 empty = YES; 1476 while (*tp && *tp != ':') { 1477 empty = (empty && WHITE(*tp) ); 1478 tp++; 1479 } 1480 if (empty || cancelled(bp+1)) { 1481 bp = tp; 1482 continue; 1483 } 1484 break; 1485 1486 case ' ': /* no spaces in output */ 1487 p = putbuf(p, "\\040"); 1488 bp++; 1489 continue; 1490 1491 case '!': /* the shell thinks this is history */ 1492 p = putbuf(p, "\\041"); 1493 bp++; 1494 continue; 1495 1496 case ',': /* the shell thinks this is history */ 1497 p = putbuf(p, "\\054"); 1498 bp++; 1499 continue; 1500 1501 case '"': /* no quotes in output */ 1502 p = putbuf(p, "\\042"); 1503 bp++; 1504 continue; 1505 1506 case '\'': /* no quotes in output */ 1507 p = putbuf(p, "\\047"); 1508 bp++; 1509 continue; 1510 1511 case '`': /* no back quotes in output */ 1512 p = putbuf(p, "\\140"); 1513 bp++; 1514 continue; 1515 1516 case '\\': 1517 case '^': /* anything following is OK */ 1518 *p++ = *bp++; 1519 } 1520 *p++ = *bp++; 1521 } 1522 *p++ = ':'; /* we skipped the last : with the : lookahead hack */ 1523 (void) write (STDOUT, buf, p-buf); 1524 } 1525 1526 cancelled(cap) 1527 char *cap; 1528 { 1529 register int i; 1530 1531 for (i = 0; i < ncap; i++) 1532 { 1533 if (cap[0] == delcap[i][0] && cap[1] == delcap[i][1]) 1534 return (YES); 1535 } 1536 /* delete a second occurrance of the same capability */ 1537 delcap[ncap][0] = cap[0]; 1538 delcap[ncap][1] = cap[1]; 1539 ncap++; 1540 return (cap[2] == '@'); 1541 } 1542 1543 char * 1544 putbuf(ptr, str) 1545 char *ptr; 1546 char *str; 1547 { 1548 char buf[20]; 1549 1550 while (*str) { 1551 switch (*str) { 1552 case '\033': 1553 ptr = putbuf(ptr, "\\E"); 1554 str++; 1555 break; 1556 default: 1557 if (*str <= ' ') { 1558 (void) sprintf(buf, "\\%03o", *str); 1559 ptr = putbuf(ptr, buf); 1560 str++; 1561 } else 1562 *ptr++ = *str++; 1563 } 1564 } 1565 return (ptr); 1566 } 1567 1568 1569 baudrate(p) 1570 char *p; 1571 { 1572 char buf[8]; 1573 int i = 0; 1574 1575 while (i < 7 && (isalnum(*p) || *p == '.')) 1576 buf[i++] = *p++; 1577 buf[i] = NULL; 1578 for (i=0; speeds[i].string; i++) 1579 if (sequal(speeds[i].string, buf)) 1580 return (speeds[i].speed); 1581 return (-1); 1582 } 1583 1584 char * 1585 mapped(type) 1586 char *type; 1587 { 1588 extern short ospeed; 1589 int match; 1590 1591 # ifdef DEB 1592 printf ("spd:%d\n", ospeed); 1593 prmap(); 1594 # endif 1595 Map = map; 1596 while (Map->Ident) 1597 { 1598 if (*(Map->Ident) == NULL || sequal(Map->Ident, type) || isalias(Map->Ident)) 1599 { 1600 match = NO; 1601 switch (Map->Test) 1602 { 1603 case ANY: /* no test specified */ 1604 case ALL: 1605 match = YES; 1606 break; 1607 1608 case GT: 1609 match = (ospeed > Map->Speed); 1610 break; 1611 1612 case GE: 1613 match = (ospeed >= Map->Speed); 1614 break; 1615 1616 case EQ: 1617 match = (ospeed == Map->Speed); 1618 break; 1619 1620 case LE: 1621 match = (ospeed <= Map->Speed); 1622 break; 1623 1624 case LT: 1625 match = (ospeed < Map->Speed); 1626 break; 1627 1628 case NE: 1629 match = (ospeed != Map->Speed); 1630 break; 1631 } 1632 if (match) 1633 return (Map->Type); 1634 } 1635 Map++; 1636 } 1637 /* no match found; return given type */ 1638 return (type); 1639 } 1640 1641 # ifdef DEB 1642 prmap() 1643 { 1644 Map = map; 1645 while (Map->Ident) 1646 { 1647 printf ("%s t:%d s:%d %s\n", 1648 Map->Ident, Map->Test, Map->Speed, Map->Type); 1649 Map++; 1650 } 1651 } 1652 # endif 1653 1654 char * 1655 nextarg(argc, argv) 1656 int argc; 1657 char *argv[]; 1658 { 1659 if (argc <= 0) 1660 fatal ("Too few args: ", *argv); 1661 if (*(*++argv) == '-') 1662 fatal ("Unexpected arg: ", *argv); 1663 return (*argv); 1664 } 1665 1666 fatal (mesg, obj) 1667 char *mesg; 1668 char *obj; 1669 { 1670 prs (mesg); 1671 prs (obj); 1672 prc ('\n'); 1673 prs (USAGE); 1674 flush(); 1675 exit(1); 1676 } 1677 1678 1679 /* 1680 * Stolen from /usr/src/ucb/reset.c, which this mod obsoletes. 1681 */ 1682 char 1683 reset(ch, def) 1684 char ch; 1685 int def; 1686 { 1687 1688 if (ch == 0 || (ch&0377) == 0377) 1689 return def; 1690 return ch; 1691 } 1692