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