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