1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1980, 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/param.h> 33 #include <sys/ioctl.h> 34 #include <sys/time.h> 35 #include <sys/resource.h> 36 #include <sys/stat.h> 37 #include <sys/ttydefaults.h> 38 #include <sys/utsname.h> 39 40 #include <ctype.h> 41 #include <errno.h> 42 #include <fcntl.h> 43 #include <locale.h> 44 #include <libutil.h> 45 #include <setjmp.h> 46 #include <signal.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <syslog.h> 51 #include <termios.h> 52 #include <time.h> 53 #include <unistd.h> 54 55 #include "gettytab.h" 56 #include "extern.h" 57 #include "pathnames.h" 58 59 /* 60 * Set the amount of running time that getty should accumulate 61 * before deciding that something is wrong and exit. 62 */ 63 #define GETTY_TIMEOUT 60 /* seconds */ 64 65 #undef CTRL 66 #define CTRL(x) (x&037) 67 68 /* defines for auto detection of incoming PPP calls (->PAP/CHAP) */ 69 70 #define PPP_FRAME 0x7e /* PPP Framing character */ 71 #define PPP_STATION 0xff /* "All Station" character */ 72 #define PPP_ESCAPE 0x7d /* Escape Character */ 73 #define PPP_CONTROL 0x03 /* PPP Control Field */ 74 #define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */ 75 #define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */ 76 #define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */ 77 78 /* original mode; flags've been reset using values from <sys/ttydefaults.h> */ 79 struct termios omode; 80 /* current mode */ 81 struct termios tmode; 82 83 static int crmod, digit, lower, upper; 84 85 char hostname[MAXHOSTNAMELEN]; 86 static char name[MAXLOGNAME*3]; 87 static char ttyn[32]; 88 89 #define OBUFSIZ 128 90 91 static const char *tname; 92 93 static char *env[128]; 94 95 static char partab[] = { 96 0001,0201,0201,0001,0201,0001,0001,0201, 97 0202,0004,0003,0205,0005,0206,0201,0001, 98 0201,0001,0001,0201,0001,0201,0201,0001, 99 0001,0201,0201,0001,0201,0001,0001,0201, 100 0200,0000,0000,0200,0000,0200,0200,0000, 101 0000,0200,0200,0000,0200,0000,0000,0200, 102 0000,0200,0200,0000,0200,0000,0000,0200, 103 0200,0000,0000,0200,0000,0200,0200,0000, 104 0200,0000,0000,0200,0000,0200,0200,0000, 105 0000,0200,0200,0000,0200,0000,0000,0200, 106 0000,0200,0200,0000,0200,0000,0000,0200, 107 0200,0000,0000,0200,0000,0200,0200,0000, 108 0000,0200,0200,0000,0200,0000,0000,0200, 109 0200,0000,0000,0200,0000,0200,0200,0000, 110 0200,0000,0000,0200,0000,0200,0200,0000, 111 0000,0200,0200,0000,0200,0000,0000,0201 112 }; 113 114 #define ERASE tmode.c_cc[VERASE] 115 #define KILL tmode.c_cc[VKILL] 116 #define EOT tmode.c_cc[VEOF] 117 118 #define puts Gputs 119 120 static void defttymode(void); 121 static void dingdong(int); 122 static void dogettytab(void); 123 static int getname(void); 124 static void interrupt(int); 125 static void oflush(void); 126 static void prompt(void); 127 static void putchr(int); 128 static void putf(const char *); 129 static void putpad(const char *); 130 static void puts(const char *); 131 static void timeoverrun(int); 132 static char *get_line(int); 133 static void setttymode(int); 134 static int opentty(const char *, int); 135 136 static jmp_buf timeout; 137 138 static void 139 dingdong(int signo __unused) 140 { 141 alarm(0); 142 longjmp(timeout, 1); 143 } 144 145 static jmp_buf intrupt; 146 147 static void 148 interrupt(int signo __unused) 149 { 150 longjmp(intrupt, 1); 151 } 152 153 /* 154 * Action to take when getty is running too long. 155 */ 156 static void 157 timeoverrun(int signo __unused) 158 { 159 160 syslog(LOG_ERR, "getty exiting due to excessive running time"); 161 exit(1); 162 } 163 164 int 165 main(int argc, char *argv[]) 166 { 167 int first_sleep = 1, first_time = 1; 168 struct rlimit limit; 169 int rval; 170 171 signal(SIGINT, SIG_IGN); 172 signal(SIGQUIT, SIG_IGN); 173 174 openlog("getty", LOG_CONS|LOG_PID, LOG_AUTH); 175 gethostname(hostname, sizeof(hostname) - 1); 176 hostname[sizeof(hostname) - 1] = '\0'; 177 if (hostname[0] == '\0') 178 snprintf(hostname, sizeof(hostname), "Amnesiac"); 179 180 /* 181 * Limit running time to deal with broken or dead lines. 182 */ 183 (void)signal(SIGXCPU, timeoverrun); 184 limit.rlim_max = RLIM_INFINITY; 185 limit.rlim_cur = GETTY_TIMEOUT; 186 (void)setrlimit(RLIMIT_CPU, &limit); 187 188 gettable("default"); 189 gendefaults(); 190 tname = "default"; 191 if (argc > 1) 192 tname = argv[1]; 193 194 /* 195 * The following is a work around for vhangup interactions 196 * which cause great problems getting window systems started. 197 * If the tty line is "-", we do the old style getty presuming 198 * that the file descriptors are already set up for us. 199 * J. Gettys - MIT Project Athena. 200 */ 201 if (argc <= 2 || strcmp(argv[2], "-") == 0) { 202 char *n = ttyname(STDIN_FILENO); 203 if (n == NULL) { 204 syslog(LOG_ERR, "ttyname: %m"); 205 exit(1); 206 } 207 snprintf(ttyn, sizeof(ttyn), "%s", n); 208 } else { 209 snprintf(ttyn, sizeof(ttyn), "%s%s", _PATH_DEV, argv[2]); 210 if (strcmp(argv[0], "+") != 0) { 211 chown(ttyn, 0, 0); 212 chmod(ttyn, 0600); 213 revoke(ttyn); 214 215 /* 216 * Do the first scan through gettytab. 217 * Terminal mode parameters will be wrong until 218 * defttymode() called, but they're irrelevant for 219 * the initial setup of the terminal device. 220 */ 221 dogettytab(); 222 223 /* 224 * Init or answer modem sequence has been specified. 225 */ 226 if (IC || AC) { 227 if (!opentty(ttyn, O_RDWR|O_NONBLOCK)) 228 exit(1); 229 defttymode(); 230 setttymode(1); 231 } 232 233 if (IC) { 234 if (getty_chat(IC, CT, DC) > 0) { 235 syslog(LOG_ERR, "modem init problem on %s", ttyn); 236 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 237 exit(1); 238 } 239 } 240 241 if (AC) { 242 fd_set rfds; 243 struct timeval to; 244 int i; 245 246 FD_ZERO(&rfds); 247 FD_SET(0, &rfds); 248 to.tv_sec = RT; 249 to.tv_usec = 0; 250 i = select(32, &rfds, NULL, NULL, RT ? &to : NULL); 251 if (i < 0) { 252 syslog(LOG_ERR, "select %s: %m", ttyn); 253 } else if (i == 0) { 254 syslog(LOG_NOTICE, "recycle tty %s", ttyn); 255 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 256 exit(0); /* recycle for init */ 257 } 258 i = getty_chat(AC, CT, DC); 259 if (i > 0) { 260 syslog(LOG_ERR, "modem answer problem on %s", ttyn); 261 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 262 exit(1); 263 } 264 } else { /* maybe blocking open */ 265 if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 ))) 266 exit(1); 267 } 268 } 269 } 270 271 defttymode(); 272 for (;;) { 273 274 /* 275 * if a delay was specified then sleep for that 276 * number of seconds before writing the initial prompt 277 */ 278 if (first_sleep && DE) { 279 sleep(DE); 280 /* remove any noise */ 281 (void)tcflush(STDIN_FILENO, TCIOFLUSH); 282 } 283 first_sleep = 0; 284 285 setttymode(0); 286 if (AB) { 287 tname = autobaud(); 288 dogettytab(); 289 continue; 290 } 291 if (PS) { 292 tname = portselector(); 293 dogettytab(); 294 continue; 295 } 296 if (CL && *CL) 297 putpad(CL); 298 edithost(HE); 299 300 /* if this is the first time through this, and an 301 issue file has been given, then send it */ 302 if (first_time && IF) { 303 int fd; 304 305 if ((fd = open(IF, O_RDONLY)) != -1) { 306 char * cp; 307 308 while ((cp = get_line(fd)) != NULL) { 309 putf(cp); 310 } 311 close(fd); 312 } 313 } 314 first_time = 0; 315 316 if (IMP && *IMP && !(PL && PP)) 317 system(IMP); 318 if (IM && *IM && !(PL && PP)) 319 putf(IM); 320 if (setjmp(timeout)) { 321 cfsetispeed(&tmode, B0); 322 cfsetospeed(&tmode, B0); 323 (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); 324 exit(1); 325 } 326 if (TO) { 327 signal(SIGALRM, dingdong); 328 alarm(TO); 329 } 330 331 rval = 0; 332 if (AL) { 333 const char *p = AL; 334 char *q = name; 335 336 while (*p && q < &name[sizeof name - 1]) { 337 if (isupper(*p)) 338 upper = 1; 339 else if (islower(*p)) 340 lower = 1; 341 else if (isdigit(*p)) 342 digit = 1; 343 *q++ = *p++; 344 } 345 } else if (!(PL && PP)) 346 rval = getname(); 347 if (rval == 2 || (PL && PP)) { 348 oflush(); 349 alarm(0); 350 limit.rlim_max = RLIM_INFINITY; 351 limit.rlim_cur = RLIM_INFINITY; 352 (void)setrlimit(RLIMIT_CPU, &limit); 353 execle(PP, "ppplogin", ttyn, (char *) 0, env); 354 syslog(LOG_ERR, "%s: %m", PP); 355 exit(1); 356 } else if (rval || AL) { 357 int i; 358 359 oflush(); 360 alarm(0); 361 signal(SIGALRM, SIG_DFL); 362 if (name[0] == '\0') 363 continue; 364 if (name[0] == '-') { 365 puts("user names may not start with '-'."); 366 continue; 367 } 368 if (!(upper || lower || digit)) { 369 if (AL) { 370 syslog(LOG_ERR, 371 "invalid auto-login name: %s", AL); 372 exit(1); 373 } else 374 continue; 375 } 376 set_flags(2); 377 if (crmod) { 378 tmode.c_iflag |= ICRNL; 379 tmode.c_oflag |= ONLCR; 380 } 381 #if REALLY_OLD_TTYS 382 if (upper || UC) 383 tmode.sg_flags |= LCASE; 384 if (lower || LC) 385 tmode.sg_flags &= ~LCASE; 386 #endif 387 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 388 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); 389 exit(1); 390 } 391 signal(SIGINT, SIG_DFL); 392 for (i = 0; environ[i] != (char *)0; i++) 393 env[i] = environ[i]; 394 makeenv(&env[i]); 395 396 limit.rlim_max = RLIM_INFINITY; 397 limit.rlim_cur = RLIM_INFINITY; 398 (void)setrlimit(RLIMIT_CPU, &limit); 399 execle(LO, "login", AL ? "-fp" : "-p", name, 400 (char *) 0, env); 401 syslog(LOG_ERR, "%s: %m", LO); 402 exit(1); 403 } 404 alarm(0); 405 signal(SIGALRM, SIG_DFL); 406 signal(SIGINT, SIG_IGN); 407 if (NX && *NX) { 408 tname = NX; 409 dogettytab(); 410 } 411 } 412 } 413 414 static int 415 opentty(const char *tty, int flags) 416 { 417 int failopenlogged = 0, i, saved_errno; 418 419 while ((i = open(tty, flags)) == -1) 420 { 421 saved_errno = errno; 422 if (!failopenlogged) { 423 syslog(LOG_ERR, "open %s: %m", tty); 424 failopenlogged = 1; 425 } 426 if (saved_errno == ENOENT) 427 return 0; 428 sleep(60); 429 } 430 if (login_tty(i) < 0) { 431 if (daemon(0,0) < 0) { 432 syslog(LOG_ERR,"daemon: %m"); 433 close(i); 434 return 0; 435 } 436 if (login_tty(i) < 0) { 437 syslog(LOG_ERR, "login_tty %s: %m", tty); 438 close(i); 439 return 0; 440 } 441 } 442 return 1; 443 } 444 445 static void 446 defttymode(void) 447 { 448 struct termios def; 449 450 /* Start with default tty settings. */ 451 if (tcgetattr(STDIN_FILENO, &tmode) < 0) { 452 syslog(LOG_ERR, "tcgetattr %s: %m", ttyn); 453 exit(1); 454 } 455 omode = tmode; /* fill c_cc for dogettytab() */ 456 dogettytab(); 457 /* 458 * Don't rely on the driver too much, and initialize crucial 459 * things according to <sys/ttydefaults.h>. Avoid clobbering 460 * the c_cc[] settings however, the console drivers might wish 461 * to leave their idea of the preferred VERASE key value 462 * there. 463 */ 464 cfmakesane(&def); 465 tmode.c_iflag = def.c_iflag; 466 tmode.c_oflag = def.c_oflag; 467 tmode.c_lflag = def.c_lflag; 468 tmode.c_cflag = def.c_cflag; 469 if (NC) 470 tmode.c_cflag |= CLOCAL; 471 omode = tmode; 472 } 473 474 static void 475 setttymode(int raw) 476 { 477 int off = 0; 478 479 (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */ 480 ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */ 481 ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */ 482 483 if (IS) 484 cfsetispeed(&tmode, speed(IS)); 485 else if (SP) 486 cfsetispeed(&tmode, speed(SP)); 487 if (OS) 488 cfsetospeed(&tmode, speed(OS)); 489 else if (SP) 490 cfsetospeed(&tmode, speed(SP)); 491 set_flags(0); 492 setchars(); 493 if (raw) 494 cfmakeraw(&tmode); 495 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 496 syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); 497 exit(1); 498 } 499 } 500 501 502 static int 503 getname(void) 504 { 505 int c; 506 char *np; 507 unsigned char cs; 508 int ppp_state = 0; 509 int ppp_connection = 0; 510 511 /* 512 * Interrupt may happen if we use CBREAK mode 513 */ 514 if (setjmp(intrupt)) { 515 signal(SIGINT, SIG_IGN); 516 return (0); 517 } 518 signal(SIGINT, interrupt); 519 set_flags(1); 520 prompt(); 521 oflush(); 522 if (PF > 0) { 523 sleep(PF); 524 PF = 0; 525 } 526 if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { 527 syslog(LOG_ERR, "%s: %m", ttyn); 528 exit(1); 529 } 530 crmod = digit = lower = upper = 0; 531 np = name; 532 for (;;) { 533 oflush(); 534 if (read(STDIN_FILENO, &cs, 1) <= 0) 535 exit(0); 536 if ((c = cs&0177) == 0) 537 return (0); 538 539 /* PPP detection state machine.. 540 Look for sequences: 541 PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or 542 PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC) 543 See RFC1662. 544 Derived from code from Michael Hancock, <michaelh@cet.co.jp> 545 and Erik 'PPP' Olson, <eriko@wrq.com> 546 */ 547 548 if (PP && (cs == PPP_FRAME)) { 549 ppp_state = 1; 550 } else if (ppp_state == 1 && cs == PPP_STATION) { 551 ppp_state = 2; 552 } else if (ppp_state == 2 && cs == PPP_ESCAPE) { 553 ppp_state = 3; 554 } else if ((ppp_state == 2 && cs == PPP_CONTROL) 555 || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) { 556 ppp_state = 4; 557 } else if (ppp_state == 4 && cs == PPP_LCP_HI) { 558 ppp_state = 5; 559 } else if (ppp_state == 5 && cs == PPP_LCP_LOW) { 560 ppp_connection = 1; 561 break; 562 } else { 563 ppp_state = 0; 564 } 565 566 if (c == EOT || c == CTRL('d')) 567 exit(0); 568 if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) { 569 putf("\r\n"); 570 break; 571 } 572 if (islower(c)) 573 lower = 1; 574 else if (isupper(c)) 575 upper = 1; 576 else if (c == ERASE || c == '\b' || c == 0177) { 577 if (np > name) { 578 np--; 579 if (cfgetospeed(&tmode) >= 1200) 580 puts("\b \b"); 581 else 582 putchr(cs); 583 } 584 continue; 585 } else if (c == KILL || c == CTRL('u')) { 586 putchr('\r'); 587 if (cfgetospeed(&tmode) < 1200) 588 putchr('\n'); 589 /* this is the way they do it down under ... */ 590 else if (np > name) 591 puts(" \r"); 592 prompt(); 593 digit = lower = upper = 0; 594 np = name; 595 continue; 596 } else if (isdigit(c)) 597 digit = 1; 598 if (IG && (c <= ' ' || c > 0176)) 599 continue; 600 *np++ = c; 601 putchr(cs); 602 } 603 signal(SIGINT, SIG_IGN); 604 *np = 0; 605 if (c == '\r') 606 crmod = 1; 607 if ((upper && !lower && !LC) || UC) 608 for (np = name; *np; np++) 609 if (isupper(*np)) 610 *np = tolower(*np); 611 return (1 + ppp_connection); 612 } 613 614 static void 615 putpad(const char *s) 616 { 617 int pad = 0; 618 speed_t ospeed = cfgetospeed(&tmode); 619 620 if (isdigit(*s)) { 621 while (isdigit(*s)) { 622 pad *= 10; 623 pad += *s++ - '0'; 624 } 625 pad *= 10; 626 if (*s == '.' && isdigit(s[1])) { 627 pad += s[1] - '0'; 628 s += 2; 629 } 630 } 631 632 puts(s); 633 /* 634 * If no delay needed, or output speed is 635 * not comprehensible, then don't try to delay. 636 */ 637 if (pad == 0 || ospeed <= 0) 638 return; 639 640 /* 641 * Round up by a half a character frame, and then do the delay. 642 * Too bad there are no user program accessible programmed delays. 643 * Transmitting pad characters slows many terminals down and also 644 * loads the system. 645 */ 646 pad = (pad * ospeed + 50000) / 100000; 647 while (pad--) 648 putchr(*PC); 649 } 650 651 static void 652 puts(const char *s) 653 { 654 while (*s) 655 putchr(*s++); 656 } 657 658 static char outbuf[OBUFSIZ]; 659 static int obufcnt = 0; 660 661 static void 662 putchr(int cc) 663 { 664 char c; 665 666 c = cc; 667 if (!NP) { 668 c |= partab[c&0177] & 0200; 669 if (OP) 670 c ^= 0200; 671 } 672 if (!UB) { 673 outbuf[obufcnt++] = c; 674 if (obufcnt >= OBUFSIZ) 675 oflush(); 676 } else 677 write(STDOUT_FILENO, &c, 1); 678 } 679 680 static void 681 oflush(void) 682 { 683 if (obufcnt) 684 write(STDOUT_FILENO, outbuf, obufcnt); 685 obufcnt = 0; 686 } 687 688 static void 689 prompt(void) 690 { 691 692 putf(LM); 693 if (CO) 694 putchr('\n'); 695 } 696 697 698 static char * 699 get_line(int fd) 700 { 701 size_t i = 0; 702 static char linebuf[512]; 703 704 /* 705 * This is certainly slow, but it avoids having to include 706 * stdio.h unnecessarily. Issue files should be small anyway. 707 */ 708 while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) { 709 if (linebuf[i] == '\n') { 710 /* Don't rely on newline mode, assume raw */ 711 linebuf[i++] = '\r'; 712 linebuf[i++] = '\n'; 713 linebuf[i] = '\0'; 714 return linebuf; 715 } 716 ++i; 717 } 718 linebuf[i] = '\0'; 719 return i ? linebuf : 0; 720 } 721 722 static void 723 putf(const char *cp) 724 { 725 time_t t; 726 char db[100]; 727 const char *slash; 728 729 static struct utsname kerninfo; 730 731 if (!*kerninfo.sysname) 732 uname(&kerninfo); 733 734 while (*cp) { 735 if (*cp != '%') { 736 putchr(*cp++); 737 continue; 738 } 739 switch (*++cp) { 740 741 case 't': 742 slash = strrchr(ttyn, '/'); 743 if (slash == (char *) 0) 744 puts(ttyn); 745 else 746 puts(&slash[1]); 747 break; 748 749 case 'h': 750 puts(editedhost); 751 break; 752 753 case 'd': 754 t = (time_t)0; 755 (void)time(&t); 756 if (Lo) 757 (void)setlocale(LC_TIME, Lo); 758 (void)strftime(db, sizeof(db), DF, localtime(&t)); 759 puts(db); 760 break; 761 762 case 's': 763 puts(kerninfo.sysname); 764 break; 765 766 case 'm': 767 puts(kerninfo.machine); 768 break; 769 770 case 'r': 771 puts(kerninfo.release); 772 break; 773 774 case 'v': 775 puts(kerninfo.version); 776 break; 777 778 case '%': 779 putchr('%'); 780 break; 781 } 782 cp++; 783 } 784 } 785 786 /* 787 * Read a gettytab database entry and perform necessary quirks. 788 */ 789 static void 790 dogettytab(void) 791 { 792 793 /* Read the database entry. */ 794 gettable(tname); 795 796 /* 797 * Avoid inheriting the parity values from the default entry 798 * if any of them is set in the current entry. 799 * Mixing different parity settings is unreasonable. 800 */ 801 if (OPset || EPset || APset || NPset) 802 OPset = EPset = APset = NPset = 1; 803 804 /* Fill in default values for unset capabilities. */ 805 setdefaults(); 806 } 807