1 /* 2 * Copyright (c) 1983, 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 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 /*static char sccsid[] = "from: @(#)subr.c 8.1 (Berkeley) 6/4/93";*/ 36 static char rcsid[] = "$Id: subr.c,v 1.14 1994/09/05 09:09:51 pk Exp $"; 37 #endif /* not lint */ 38 39 /* 40 * Melbourne getty. 41 */ 42 #define COMPAT_43 43 #include <stdlib.h> 44 #include <unistd.h> 45 #include <string.h> 46 #include <termios.h> 47 #include <sys/ioctl.h> 48 49 #include "gettytab.h" 50 #include "pathnames.h" 51 #include "extern.h" 52 53 extern struct termios tmode, omode; 54 55 static void compatflags __P((long)); 56 57 /* 58 * Get a table entry. 59 */ 60 void 61 gettable(name, buf) 62 char *name, *buf; 63 { 64 register struct gettystrs *sp; 65 register struct gettynums *np; 66 register struct gettyflags *fp; 67 long n; 68 char *dba[2]; 69 dba[0] = _PATH_GETTYTAB; 70 dba[1] = 0; 71 72 if (cgetent(&buf, dba, name) != 0) 73 return; 74 75 for (sp = gettystrs; sp->field; sp++) 76 cgetstr(buf, sp->field, &sp->value); 77 for (np = gettynums; np->field; np++) { 78 if (cgetnum(buf, np->field, &n) == -1) 79 np->set = 0; 80 else { 81 np->set = 1; 82 np->value = n; 83 } 84 } 85 for (fp = gettyflags; fp->field; fp++) { 86 if (cgetcap(buf, fp->field, ':') == NULL) 87 fp->set = 0; 88 else { 89 fp->set = 1; 90 fp->value = 1 ^ fp->invrt; 91 } 92 } 93 #ifdef DEBUG 94 printf("name=\"%s\", buf=\"%s\"\n", name, buf); 95 for (sp = gettystrs; sp->field; sp++) 96 printf("cgetstr: %s=%s\n", sp->field, sp->value); 97 for (np = gettynums; np->field; np++) 98 printf("cgetnum: %s=%d\n", np->field, np->value); 99 for (fp = gettyflags; fp->field; fp++) 100 printf("cgetflags: %s='%c' set='%c'\n", fp->field, 101 fp->value + '0', fp->set + '0'); 102 exit(1); 103 #endif /* DEBUG */ 104 } 105 106 void 107 gendefaults() 108 { 109 register struct gettystrs *sp; 110 register struct gettynums *np; 111 register struct gettyflags *fp; 112 113 for (sp = gettystrs; sp->field; sp++) 114 if (sp->value) 115 sp->defalt = sp->value; 116 for (np = gettynums; np->field; np++) 117 if (np->set) 118 np->defalt = np->value; 119 for (fp = gettyflags; fp->field; fp++) 120 if (fp->set) 121 fp->defalt = fp->value; 122 else 123 fp->defalt = fp->invrt; 124 } 125 126 void 127 setdefaults() 128 { 129 register struct gettystrs *sp; 130 register struct gettynums *np; 131 register struct gettyflags *fp; 132 133 for (sp = gettystrs; sp->field; sp++) 134 if (!sp->value) 135 sp->value = sp->defalt; 136 for (np = gettynums; np->field; np++) 137 if (!np->set) 138 np->value = np->defalt; 139 for (fp = gettyflags; fp->field; fp++) 140 if (!fp->set) 141 fp->value = fp->defalt; 142 } 143 144 static char ** 145 charnames[] = { 146 &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK, 147 &SU, &DS, &RP, &FL, &WE, &LN, 0 148 }; 149 150 static char * 151 charvars[] = { 152 &tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR], 153 &tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP], 154 &tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP], 155 &tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD], 156 &tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0 157 }; 158 159 void 160 setchars() 161 { 162 register int i; 163 register char *p; 164 165 for (i = 0; charnames[i]; i++) { 166 p = *charnames[i]; 167 if (p && *p) 168 *charvars[i] = *p; 169 else 170 *charvars[i] = _POSIX_VDISABLE; 171 } 172 } 173 174 void 175 setflags(n) 176 int n; 177 { 178 register tcflag_t iflag, oflag, cflag, lflag; 179 180 #ifdef COMPAT_43 181 switch (n) { 182 case 0: 183 if (F0set) { 184 compatflags(F0); 185 return; 186 } 187 break; 188 case 1: 189 if (F1set) { 190 compatflags(F1); 191 return; 192 } 193 break; 194 default: 195 if (F2set) { 196 compatflags(F2); 197 return; 198 } 199 break; 200 } 201 #endif 202 203 switch (n) { 204 case 0: 205 if (C0set && I0set && L0set && O0set) { 206 tmode.c_cflag = C0; 207 tmode.c_iflag = I0; 208 tmode.c_lflag = L0; 209 tmode.c_oflag = O0; 210 return; 211 } 212 break; 213 case 1: 214 if (C1set && I1set && L1set && O1set) { 215 tmode.c_cflag = C1; 216 tmode.c_iflag = I1; 217 tmode.c_lflag = L1; 218 tmode.c_oflag = O1; 219 return; 220 } 221 break; 222 default: 223 if (C2set && I2set && L2set && O2set) { 224 tmode.c_cflag = C2; 225 tmode.c_iflag = I2; 226 tmode.c_lflag = L2; 227 tmode.c_oflag = O2; 228 return; 229 } 230 break; 231 } 232 233 #define BIC(v,c) (v) &= ~(c) 234 #define BIS(v,s) (v) |= (s) 235 #define BICS(v,c,s) BIC(v,c),BIS(v,s) 236 237 iflag = omode.c_iflag; 238 oflag = omode.c_oflag; 239 cflag = omode.c_cflag; 240 lflag = omode.c_lflag; 241 242 if (NP) { 243 BIC(iflag, ISTRIP|INPCK|IGNPAR); 244 BICS(cflag, CSIZE|PARENB|PARODD, CS8); 245 } else if (OP && !EP) { 246 BIS(iflag, ISTRIP|INPCK|IGNPAR); 247 BICS(cflag, CSIZE, PARENB|PARODD|CS7); 248 if (AP) 249 BIC(iflag, INPCK); 250 } else if (EP && !OP) { 251 BIS(iflag, ISTRIP|INPCK|IGNPAR); 252 BICS(cflag, CSIZE|PARODD, PARENB|CS7); 253 if (AP) 254 BIC(iflag, INPCK); 255 } else if (AP || EP && OP) { 256 BICS(iflag, INPCK|IGNPAR, ISTRIP); 257 BICS(cflag, CSIZE|PARODD, PARENB|CS7); 258 } /* else, leave as is */ 259 260 #if 0 261 if (UC) 262 f |= LCASE; 263 #endif 264 265 if (HC) 266 cflag |= HUPCL; 267 else 268 cflag &= ~HUPCL; 269 270 if (MB) 271 cflag |= MDMBUF; 272 else 273 cflag &= ~MDMBUF; 274 275 if (NL) { 276 iflag |= ICRNL; 277 oflag |= ONLCR; 278 } 279 280 #ifdef XXX_DELAY 281 f |= delaybits(); 282 #endif 283 284 if (n == 1) { /* read mode flags */ 285 if (RW) { 286 iflag = 0; 287 oflag = 0; 288 BICS(cflag, CSIZE|PARENB|PARODD, CS8); 289 lflag = 0; 290 } else { 291 lflag &= ~ICANON; 292 } 293 goto out; 294 } 295 296 if (HT) 297 oflag &= ~OXTABS; 298 else 299 oflag |= OXTABS; 300 301 if (n == 0) 302 goto out; 303 304 #if 0 305 if (CB) 306 f |= CRTBS; 307 #endif 308 309 if (CE) 310 lflag |= ECHOE; 311 312 if (CK) 313 lflag |= ECHOKE; 314 315 if (PE) 316 lflag |= ECHOPRT; 317 318 if (EC) 319 lflag |= ECHO; 320 321 if (XC) 322 lflag |= ECHOCTL; 323 324 if (DX) 325 lflag |= IXANY; 326 327 out: 328 tmode.c_iflag = iflag; 329 tmode.c_oflag = oflag; 330 tmode.c_cflag = cflag; 331 tmode.c_lflag = lflag; 332 } 333 334 #ifdef COMPAT_43 335 /* 336 * Old TTY => termios, snatched from <sys/kern/tty_compat.c> 337 */ 338 void 339 compatflags(flags) 340 register long flags; 341 { 342 register tcflag_t iflag, oflag, cflag, lflag; 343 344 iflag = (BRKINT|ICRNL|IMAXBEL|IXON|IXANY); 345 oflag = (OPOST|ONLCR|OXTABS); 346 cflag = (CREAD); 347 lflag = (ICANON|ISIG|IEXTEN); 348 349 if (flags & TANDEM) 350 iflag |= IXOFF; 351 else 352 iflag &= ~IXOFF; 353 if (flags & ECHO) 354 lflag |= ECHO; 355 else 356 lflag &= ~ECHO; 357 if (flags & CRMOD) { 358 iflag |= ICRNL; 359 oflag |= ONLCR; 360 } else { 361 iflag &= ~ICRNL; 362 oflag &= ~ONLCR; 363 } 364 if (flags & XTABS) 365 oflag |= OXTABS; 366 else 367 oflag &= ~OXTABS; 368 369 if (flags & RAW) { 370 iflag &= IXOFF; 371 lflag &= ~(ISIG|ICANON|IEXTEN); 372 } else { 373 iflag |= BRKINT|IXON|IMAXBEL; 374 lflag |= ISIG|IEXTEN; 375 if (flags & CBREAK) 376 lflag &= ~ICANON; 377 else 378 lflag |= ICANON; 379 } 380 381 switch (flags & ANYP) { 382 case EVENP: 383 iflag |= INPCK; 384 cflag &= ~PARODD; 385 break; 386 case ODDP: 387 iflag |= INPCK; 388 cflag |= PARODD; 389 break; 390 default: 391 iflag &= ~INPCK; 392 break; 393 } 394 395 if (flags & (RAW|LITOUT|PASS8)) { 396 cflag &= ~(CSIZE|PARENB); 397 cflag |= CS8; 398 if ((flags & (RAW|PASS8)) == 0) 399 iflag |= ISTRIP; 400 else 401 iflag &= ~ISTRIP; 402 if ((flags & (RAW|LITOUT)) == 0) 403 oflag |= OPOST; 404 else 405 oflag &= ~OPOST; 406 } else { 407 cflag &= ~CSIZE; 408 cflag |= CS7|PARENB; 409 iflag |= ISTRIP; 410 oflag |= OPOST; 411 } 412 413 if (flags & PRTERA) 414 lflag |= ECHOPRT; 415 else 416 lflag &= ~ECHOPRT; 417 if (flags & CRTERA) 418 lflag |= ECHOE; 419 else 420 lflag &= ~ECHOE; 421 if (flags & MDMBUF) 422 cflag |= MDMBUF; 423 else 424 cflag &= ~MDMBUF; 425 if (flags & NOHANG) 426 cflag &= ~HUPCL; 427 else 428 cflag |= HUPCL; 429 if (flags & CRTKIL) 430 lflag |= ECHOKE; 431 else 432 lflag &= ~ECHOKE; 433 if (flags & CTLECH) 434 lflag |= ECHOCTL; 435 else 436 lflag &= ~ECHOCTL; 437 if ((flags & DECCTQ) == 0) 438 lflag |= IXANY; 439 else 440 lflag &= ~IXANY; 441 lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH); 442 lflag |= flags & (TOSTOP|FLUSHO|PENDIN|NOFLSH); 443 444 if (flags & (RAW|LITOUT|PASS8)) { 445 cflag &= ~(CSIZE|PARENB); 446 cflag |= CS8; 447 if ((flags & (RAW|PASS8)) == 0) 448 iflag |= ISTRIP; 449 else 450 iflag &= ~ISTRIP; 451 if ((flags & (RAW|LITOUT)) == 0) 452 oflag |= OPOST; 453 else 454 oflag &= ~OPOST; 455 } else { 456 cflag &= ~CSIZE; 457 cflag |= CS7|PARENB; 458 iflag |= ISTRIP; 459 oflag |= OPOST; 460 } 461 462 tmode.c_iflag = iflag; 463 tmode.c_oflag = oflag; 464 tmode.c_cflag = cflag; 465 tmode.c_lflag = lflag; 466 } 467 #endif 468 469 #ifdef XXX_DELAY 470 struct delayval { 471 unsigned delay; /* delay in ms */ 472 int bits; 473 }; 474 475 /* 476 * below are random guesses, I can't be bothered checking 477 */ 478 479 struct delayval crdelay[] = { 480 { 1, CR1 }, 481 { 2, CR2 }, 482 { 3, CR3 }, 483 { 83, CR1 }, 484 { 166, CR2 }, 485 { 0, CR3 }, 486 }; 487 488 struct delayval nldelay[] = { 489 { 1, NL1 }, /* special, calculated */ 490 { 2, NL2 }, 491 { 3, NL3 }, 492 { 100, NL2 }, 493 { 0, NL3 }, 494 }; 495 496 struct delayval bsdelay[] = { 497 { 1, BS1 }, 498 { 0, 0 }, 499 }; 500 501 struct delayval ffdelay[] = { 502 { 1, FF1 }, 503 { 1750, FF1 }, 504 { 0, FF1 }, 505 }; 506 507 struct delayval tbdelay[] = { 508 { 1, TAB1 }, 509 { 2, TAB2 }, 510 { 3, XTABS }, /* this is expand tabs */ 511 { 100, TAB1 }, 512 { 0, TAB2 }, 513 }; 514 515 int 516 delaybits() 517 { 518 register int f; 519 520 f = adelay(CD, crdelay); 521 f |= adelay(ND, nldelay); 522 f |= adelay(FD, ffdelay); 523 f |= adelay(TD, tbdelay); 524 f |= adelay(BD, bsdelay); 525 return (f); 526 } 527 528 int 529 adelay(ms, dp) 530 register ms; 531 register struct delayval *dp; 532 { 533 if (ms == 0) 534 return (0); 535 while (dp->delay && ms > dp->delay) 536 dp++; 537 return (dp->bits); 538 } 539 #endif 540 541 char editedhost[32]; 542 543 void 544 edithost(pat) 545 register char *pat; 546 { 547 register char *host = HN; 548 register char *res = editedhost; 549 550 if (!pat) 551 pat = ""; 552 while (*pat) { 553 switch (*pat) { 554 555 case '#': 556 if (*host) 557 host++; 558 break; 559 560 case '@': 561 if (*host) 562 *res++ = *host++; 563 break; 564 565 default: 566 *res++ = *pat; 567 break; 568 569 } 570 if (res == &editedhost[sizeof editedhost - 1]) { 571 *res = '\0'; 572 return; 573 } 574 pat++; 575 } 576 if (*host) 577 strncpy(res, host, sizeof editedhost - (res - editedhost) - 1); 578 else 579 *res = '\0'; 580 editedhost[sizeof editedhost - 1] = '\0'; 581 } 582 583 void 584 makeenv(env) 585 char *env[]; 586 { 587 static char termbuf[128] = "TERM="; 588 register char *p, *q; 589 register char **ep; 590 591 ep = env; 592 if (TT && *TT) { 593 strcat(termbuf, TT); 594 *ep++ = termbuf; 595 } 596 if (p = EV) { 597 q = p; 598 while (q = strchr(q, ',')) { 599 *q++ = '\0'; 600 *ep++ = p; 601 p = q; 602 } 603 if (*p) 604 *ep++ = p; 605 } 606 *ep = (char *)0; 607 } 608 609 /* 610 * This speed select mechanism is written for the Develcon DATASWITCH. 611 * The Develcon sends a string of the form "B{speed}\n" at a predefined 612 * baud rate. This string indicates the user's actual speed. 613 * The routine below returns the terminal type mapped from derived speed. 614 */ 615 struct portselect { 616 char *ps_baud; 617 char *ps_type; 618 } portspeeds[] = { 619 { "B110", "std.110" }, 620 { "B134", "std.134" }, 621 { "B150", "std.150" }, 622 { "B300", "std.300" }, 623 { "B600", "std.600" }, 624 { "B1200", "std.1200" }, 625 { "B2400", "std.2400" }, 626 { "B4800", "std.4800" }, 627 { "B9600", "std.9600" }, 628 { "B19200", "std.19200" }, 629 { 0 } 630 }; 631 632 char * 633 portselector() 634 { 635 char c, baud[20], *type = "default"; 636 register struct portselect *ps; 637 int len; 638 639 alarm(5*60); 640 for (len = 0; len < sizeof (baud) - 1; len++) { 641 if (read(STDIN_FILENO, &c, 1) <= 0) 642 break; 643 c &= 0177; 644 if (c == '\n' || c == '\r') 645 break; 646 if (c == 'B') 647 len = 0; /* in case of leading garbage */ 648 baud[len] = c; 649 } 650 baud[len] = '\0'; 651 for (ps = portspeeds; ps->ps_baud; ps++) 652 if (strcmp(ps->ps_baud, baud) == 0) { 653 type = ps->ps_type; 654 break; 655 } 656 sleep(2); /* wait for connection to complete */ 657 return (type); 658 } 659 660 /* 661 * This auto-baud speed select mechanism is written for the Micom 600 662 * portselector. Selection is done by looking at how the character '\r' 663 * is garbled at the different speeds. 664 */ 665 #include <sys/time.h> 666 667 char * 668 autobaud() 669 { 670 int rfds; 671 struct timeval timeout; 672 char c, *type = "9600-baud"; 673 674 (void)tcflush(0, TCIOFLUSH); 675 rfds = 1 << 0; 676 timeout.tv_sec = 5; 677 timeout.tv_usec = 0; 678 if (select(32, (fd_set *)&rfds, (fd_set *)NULL, 679 (fd_set *)NULL, &timeout) <= 0) 680 return (type); 681 if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char)) 682 return (type); 683 timeout.tv_sec = 0; 684 timeout.tv_usec = 20; 685 (void) select(32, (fd_set *)NULL, (fd_set *)NULL, 686 (fd_set *)NULL, &timeout); 687 (void)tcflush(0, TCIOFLUSH); 688 switch (c & 0377) { 689 690 case 0200: /* 300-baud */ 691 type = "300-baud"; 692 break; 693 694 case 0346: /* 1200-baud */ 695 type = "1200-baud"; 696 break; 697 698 case 015: /* 2400-baud */ 699 case 0215: 700 type = "2400-baud"; 701 break; 702 703 default: /* 4800-baud */ 704 type = "4800-baud"; 705 break; 706 707 case 0377: /* 9600-baud */ 708 type = "9600-baud"; 709 break; 710 } 711 return (type); 712 } 713