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