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