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