1 /* tty.c 6.11 84/09/10 */ 2 3 #include "../machine/reg.h" 4 5 #include "param.h" 6 #include "systm.h" 7 #include "dir.h" 8 #include "user.h" 9 #include "ioctl.h" 10 #include "tty.h" 11 #include "proc.h" 12 #include "inode.h" 13 #include "file.h" 14 #include "conf.h" 15 #include "buf.h" 16 #include "dk.h" 17 #include "uio.h" 18 #include "kernel.h" 19 20 /* 21 * Table giving parity for characters and indicating 22 * character classes to tty driver. In particular, 23 * if the low 6 bits are 0, then the character needs 24 * no special processing on output. 25 */ 26 27 char partab[] = { 28 0001,0201,0201,0001,0201,0001,0001,0201, 29 0202,0004,0003,0201,0005,0206,0201,0001, 30 0201,0001,0001,0201,0001,0201,0201,0001, 31 0001,0201,0201,0001,0201,0001,0001,0201, 32 0200,0000,0000,0200,0000,0200,0200,0000, 33 0000,0200,0200,0000,0200,0000,0000,0200, 34 0000,0200,0200,0000,0200,0000,0000,0200, 35 0200,0000,0000,0200,0000,0200,0200,0000, 36 0200,0000,0000,0200,0000,0200,0200,0000, 37 0000,0200,0200,0000,0200,0000,0000,0200, 38 0000,0200,0200,0000,0200,0000,0000,0200, 39 0200,0000,0000,0200,0000,0200,0200,0000, 40 0000,0200,0200,0000,0200,0000,0000,0200, 41 0200,0000,0000,0200,0000,0200,0200,0000, 42 0200,0000,0000,0200,0000,0200,0200,0000, 43 0000,0200,0200,0000,0200,0000,0000,0201, 44 45 /* 46 * 7 bit ascii ends with the last character above, 47 * but we contine through all 256 codes for the sake 48 * of the tty output routines which use special vax 49 * instructions which need a 256 character trt table. 50 */ 51 52 0007,0007,0007,0007,0007,0007,0007,0007, 53 0007,0007,0007,0007,0007,0007,0007,0007, 54 0007,0007,0007,0007,0007,0007,0007,0007, 55 0007,0007,0007,0007,0007,0007,0007,0007, 56 0007,0007,0007,0007,0007,0007,0007,0007, 57 0007,0007,0007,0007,0007,0007,0007,0007, 58 0007,0007,0007,0007,0007,0007,0007,0007, 59 0007,0007,0007,0007,0007,0007,0007,0007, 60 0007,0007,0007,0007,0007,0007,0007,0007, 61 0007,0007,0007,0007,0007,0007,0007,0007, 62 0007,0007,0007,0007,0007,0007,0007,0007, 63 0007,0007,0007,0007,0007,0007,0007,0007, 64 0007,0007,0007,0007,0007,0007,0007,0007, 65 0007,0007,0007,0007,0007,0007,0007,0007, 66 0007,0007,0007,0007,0007,0007,0007,0007, 67 0007,0007,0007,0007,0007,0007,0007,0007 68 }; 69 70 /* 71 * Input mapping table-- if an entry is non-zero, when the 72 * corresponding character is typed preceded by "\" the escape 73 * sequence is replaced by the table value. Mostly used for 74 * upper-case only terminals. 75 */ 76 char maptab[] ={ 77 000,000,000,000,000,000,000,000, 78 000,000,000,000,000,000,000,000, 79 000,000,000,000,000,000,000,000, 80 000,000,000,000,000,000,000,000, 81 000,'|',000,000,000,000,000,'`', 82 '{','}',000,000,000,000,000,000, 83 000,000,000,000,000,000,000,000, 84 000,000,000,000,000,000,000,000, 85 000,000,000,000,000,000,000,000, 86 000,000,000,000,000,000,000,000, 87 000,000,000,000,000,000,000,000, 88 000,000,000,000,000,000,'~',000, 89 000,'A','B','C','D','E','F','G', 90 'H','I','J','K','L','M','N','O', 91 'P','Q','R','S','T','U','V','W', 92 'X','Y','Z',000,000,000,000,000, 93 }; 94 95 short tthiwat[16] = 96 { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 }; 97 short ttlowat[16] = 98 { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 }; 99 100 struct ttychars ttydefaults = { 101 CERASE, CKILL, CINTR, CQUIT, CSTART, CSTOP, CEOF, 102 CBRK, CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT 103 }; 104 105 ttychars(tp) 106 struct tty *tp; 107 { 108 109 tp->t_chars = ttydefaults; 110 } 111 112 /* 113 * Wait for output to drain, then flush input waiting. 114 */ 115 ttywflush(tp) 116 register struct tty *tp; 117 { 118 119 ttywait(tp); 120 ttyflush(tp, FREAD); 121 } 122 123 ttywait(tp) 124 register struct tty *tp; 125 { 126 register int s = spl5(); 127 128 while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) && 129 tp->t_state&TS_CARR_ON && tp->t_oproc) { /* kludge for pty */ 130 (*tp->t_oproc)(tp); 131 tp->t_state |= TS_ASLEEP; 132 sleep((caddr_t)&tp->t_outq, TTOPRI); 133 } 134 splx(s); 135 } 136 137 /* 138 * Flush all TTY queues 139 */ 140 ttyflush(tp, rw) 141 register struct tty *tp; 142 { 143 register s; 144 145 s = spl6(); 146 if (rw & FREAD) { 147 while (getc(&tp->t_canq) >= 0) 148 ; 149 wakeup((caddr_t)&tp->t_rawq); 150 } 151 if (rw & FWRITE) { 152 wakeup((caddr_t)&tp->t_outq); 153 tp->t_state &= ~TS_TTSTOP; 154 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 155 while (getc(&tp->t_outq) >= 0) 156 ; 157 } 158 if (rw & FREAD) { 159 while (getc(&tp->t_rawq) >= 0) 160 ; 161 tp->t_rocount = 0; 162 tp->t_rocol = 0; 163 tp->t_state &= ~TS_LOCAL; 164 } 165 splx(s); 166 } 167 168 /* 169 * Send stop character on input overflow. 170 */ 171 ttyblock(tp) 172 register struct tty *tp; 173 { 174 register x; 175 176 x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 177 if (tp->t_rawq.c_cc > TTYHOG) { 178 ttyflush(tp, FREAD|FWRITE); 179 tp->t_state &= ~TS_TBLOCK; 180 } 181 /* 182 * Block further input iff: 183 * Current input > threshold AND input is available to user program 184 */ 185 if (x >= TTYHOG/2 && 186 ((tp->t_flags & (RAW|CBREAK)) || (tp->t_canq.c_cc > 0))) { 187 if (putc(tp->t_stopc, &tp->t_outq)==0) { 188 tp->t_state |= TS_TBLOCK; 189 ttstart(tp); 190 } 191 } 192 } 193 194 /* 195 * Restart typewriter output following a delay 196 * timeout. 197 * The name of the routine is passed to the timeout 198 * subroutine and it is called during a clock interrupt. 199 */ 200 ttrstrt(tp) 201 register struct tty *tp; 202 { 203 204 if (tp == 0) 205 panic("ttrstrt"); 206 tp->t_state &= ~TS_TIMEOUT; 207 ttstart(tp); 208 } 209 210 /* 211 * Start output on the typewriter. It is used from the top half 212 * after some characters have been put on the output queue, 213 * from the interrupt routine to transmit the next 214 * character, and after a timeout has finished. 215 */ 216 ttstart(tp) 217 register struct tty *tp; 218 { 219 register s; 220 221 s = spl5(); 222 if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 && 223 tp->t_oproc) /* kludge for pty */ 224 (*tp->t_oproc)(tp); 225 splx(s); 226 } 227 228 /* 229 * Common code for tty ioctls. 230 */ 231 /*ARGSUSED*/ 232 ttioctl(tp, com, data, flag) 233 register struct tty *tp; 234 caddr_t data; 235 { 236 int dev = tp->t_dev; 237 extern int nldisp; 238 int s; 239 register int newflags; 240 241 /* 242 * If the ioctl involves modification, 243 * insist on being able to write the device, 244 * and hang if in the background. 245 */ 246 switch (com) { 247 248 case TIOCSETD: 249 case TIOCSETP: 250 case TIOCSETN: 251 case TIOCFLUSH: 252 case TIOCSETC: 253 case TIOCSLTC: 254 case TIOCSPGRP: 255 case TIOCLBIS: 256 case TIOCLBIC: 257 case TIOCLSET: 258 case TIOCSTI: 259 #define bit(a) (1<<(a-1)) 260 while (tp->t_line == NTTYDISC && 261 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 262 (u.u_procp->p_flag&SVFORK) == 0 && 263 !(u.u_procp->p_sigignore & bit(SIGTTOU)) && 264 !(u.u_procp->p_sigmask & bit(SIGTTOU))) { 265 gsignal(u.u_procp->p_pgrp, SIGTTOU); 266 sleep((caddr_t)&lbolt, TTOPRI); 267 } 268 break; 269 } 270 #undef bit 271 272 /* 273 * Process the ioctl. 274 */ 275 switch (com) { 276 277 /* get discipline number */ 278 case TIOCGETD: 279 *(int *)data = tp->t_line; 280 break; 281 282 /* set line discipline */ 283 case TIOCSETD: { 284 register int t = *(int *)data; 285 int error = 0; 286 287 if ((unsigned) t >= nldisp) 288 return (ENXIO); 289 s = spl5(); 290 if (tp->t_line) 291 (*linesw[tp->t_line].l_close)(tp); 292 if (t) 293 error = (*linesw[t].l_open)(dev, tp); 294 splx(s); 295 if (error) { 296 s = spl5(); 297 if (tp->t_line) 298 (void) (*linesw[tp->t_line].l_open)(dev, tp); 299 splx(s); 300 return (error); 301 } 302 tp->t_line = t; 303 break; 304 } 305 306 /* prevent more opens on channel */ 307 case TIOCEXCL: 308 tp->t_state |= TS_XCLUDE; 309 break; 310 311 case TIOCNXCL: 312 tp->t_state &= ~TS_XCLUDE; 313 break; 314 315 /* hang up line on last close */ 316 case TIOCHPCL: 317 tp->t_state |= TS_HUPCLS; 318 break; 319 320 case TIOCFLUSH: { 321 register int flags = *(int *)data; 322 323 if (flags == 0) 324 flags = FREAD|FWRITE; 325 else 326 flags &= FREAD|FWRITE; 327 ttyflush(tp, flags); 328 break; 329 } 330 331 /* return number of characters immediately available */ 332 case FIONREAD: 333 *(off_t *)data = ttnread(tp); 334 break; 335 336 case TIOCOUTQ: 337 *(int *)data = tp->t_outq.c_cc; 338 break; 339 340 case TIOCSTOP: 341 s = spl5(); 342 if ((tp->t_state&TS_TTSTOP) == 0) { 343 tp->t_state |= TS_TTSTOP; 344 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 345 } 346 splx(s); 347 break; 348 349 case TIOCSTART: 350 s = spl5(); 351 if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) { 352 tp->t_state &= ~TS_TTSTOP; 353 tp->t_flags &= ~FLUSHO; 354 ttstart(tp); 355 } 356 splx(s); 357 break; 358 359 /* 360 * Simulate typing of a character at the terminal. 361 */ 362 case TIOCSTI: 363 if (u.u_uid && (flag & FREAD) == 0) 364 return (EPERM); 365 if (u.u_uid && u.u_ttyp != tp) 366 return (EACCES); 367 (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 368 break; 369 370 case TIOCSETP: 371 case TIOCSETN: { 372 register struct sgttyb *sg = (struct sgttyb *)data; 373 374 tp->t_erase = sg->sg_erase; 375 tp->t_kill = sg->sg_kill; 376 tp->t_ispeed = sg->sg_ispeed; 377 tp->t_ospeed = sg->sg_ospeed; 378 newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff); 379 s = spl5(); 380 if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) { 381 ttywait(tp); 382 ttyflush(tp, FREAD); 383 } else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) { 384 if (newflags&CBREAK) { 385 struct clist tq; 386 387 catq(&tp->t_rawq, &tp->t_canq); 388 tq = tp->t_rawq; 389 tp->t_rawq = tp->t_canq; 390 tp->t_canq = tq; 391 } else { 392 tp->t_flags |= PENDIN; 393 newflags |= PENDIN; 394 ttwakeup(tp); 395 } 396 } 397 tp->t_flags = newflags; 398 if (tp->t_flags&RAW) { 399 tp->t_state &= ~TS_TTSTOP; 400 ttstart(tp); 401 } 402 splx(s); 403 break; 404 } 405 406 /* send current parameters to user */ 407 case TIOCGETP: { 408 register struct sgttyb *sg = (struct sgttyb *)data; 409 410 sg->sg_ispeed = tp->t_ispeed; 411 sg->sg_ospeed = tp->t_ospeed; 412 sg->sg_erase = tp->t_erase; 413 sg->sg_kill = tp->t_kill; 414 sg->sg_flags = tp->t_flags; 415 break; 416 } 417 418 case FIONBIO: 419 if (*(int *)data) 420 tp->t_state |= TS_NBIO; 421 else 422 tp->t_state &= ~TS_NBIO; 423 break; 424 425 case FIOASYNC: 426 if (*(int *)data) 427 tp->t_state |= TS_ASYNC; 428 else 429 tp->t_state &= ~TS_ASYNC; 430 break; 431 432 case TIOCGETC: 433 bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars)); 434 break; 435 436 case TIOCSETC: 437 bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars)); 438 break; 439 440 /* set/get local special characters */ 441 case TIOCSLTC: 442 bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars)); 443 break; 444 445 case TIOCGLTC: 446 bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars)); 447 break; 448 449 /* 450 * Modify local mode word. 451 */ 452 case TIOCLBIS: 453 tp->t_flags |= *(int *)data << 16; 454 break; 455 456 case TIOCLBIC: 457 tp->t_flags &= ~(*(int *)data << 16); 458 break; 459 460 case TIOCLSET: 461 tp->t_flags &= 0xffff; 462 tp->t_flags |= *(int *)data << 16; 463 break; 464 465 case TIOCLGET: 466 *(int *)data = ((unsigned) tp->t_flags) >> 16; 467 break; 468 469 /* should allow SPGRP and GPGRP only if tty open for reading */ 470 case TIOCSPGRP: 471 tp->t_pgrp = *(int *)data; 472 break; 473 474 case TIOCGPGRP: 475 *(int *)data = tp->t_pgrp; 476 break; 477 478 default: 479 return (-1); 480 } 481 return (0); 482 } 483 484 ttnread(tp) 485 struct tty *tp; 486 { 487 int nread = 0; 488 489 if (tp->t_flags & PENDIN) 490 ttypend(tp); 491 nread = tp->t_canq.c_cc; 492 if (tp->t_flags & (RAW|CBREAK)) 493 nread += tp->t_rawq.c_cc; 494 return (nread); 495 } 496 497 ttselect(dev, rw) 498 dev_t dev; 499 int rw; 500 { 501 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 502 int nread; 503 int s = spl5(); 504 505 switch (rw) { 506 507 case FREAD: 508 nread = ttnread(tp); 509 if (nread > 0) 510 goto win; 511 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 512 tp->t_state |= TS_RCOLL; 513 else 514 tp->t_rsel = u.u_procp; 515 break; 516 517 case FWRITE: 518 if (tp->t_outq.c_cc <= TTLOWAT(tp)) 519 goto win; 520 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 521 tp->t_state |= TS_WCOLL; 522 else 523 tp->t_wsel = u.u_procp; 524 break; 525 } 526 splx(s); 527 return (0); 528 win: 529 splx(s); 530 return (1); 531 } 532 533 /* 534 * Establish a process group for distribution of 535 * quits and interrupts from the tty. 536 */ 537 ttyopen(dev, tp) 538 dev_t dev; 539 register struct tty *tp; 540 { 541 register struct proc *pp; 542 543 pp = u.u_procp; 544 tp->t_dev = dev; 545 if (pp->p_pgrp == 0) { 546 u.u_ttyp = tp; 547 u.u_ttyd = dev; 548 if (tp->t_pgrp == 0) 549 tp->t_pgrp = pp->p_pid; 550 pp->p_pgrp = tp->t_pgrp; 551 } 552 tp->t_state &= ~TS_WOPEN; 553 tp->t_state |= TS_ISOPEN; 554 if (tp->t_line != NTTYDISC) 555 ttywflush(tp); 556 return (0); 557 } 558 559 /* 560 * clean tp on last close 561 */ 562 ttyclose(tp) 563 register struct tty *tp; 564 { 565 566 if (tp->t_line) { 567 ttywflush(tp); 568 tp->t_line = 0; 569 return; 570 } 571 tp->t_pgrp = 0; 572 ttywflush(tp); 573 tp->t_state = 0; 574 } 575 576 /* 577 * reinput pending characters after state switch 578 * call at spl5(). 579 */ 580 ttypend(tp) 581 register struct tty *tp; 582 { 583 struct clist tq; 584 register c; 585 586 tp->t_flags &= ~PENDIN; 587 tp->t_state |= TS_TYPEN; 588 tq = tp->t_rawq; 589 tp->t_rawq.c_cc = 0; 590 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 591 while ((c = getc(&tq)) >= 0) 592 ttyinput(c, tp); 593 tp->t_state &= ~TS_TYPEN; 594 } 595 596 /* 597 * Place a character on raw TTY input queue, 598 * putting in delimiters and waking up top 599 * half as needed. Also echo if required. 600 * The arguments are the character and the 601 * appropriate tty structure. 602 */ 603 ttyinput(c, tp) 604 register c; 605 register struct tty *tp; 606 { 607 register int t_flags = tp->t_flags; 608 int i; 609 610 /* 611 * If input is pending take it first. 612 */ 613 if (t_flags&PENDIN) 614 ttypend(tp); 615 tk_nin++; 616 c &= 0377; 617 618 /* 619 * In tandem mode, check high water mark. 620 */ 621 if (t_flags&TANDEM) 622 ttyblock(tp); 623 624 if (t_flags&RAW) { 625 /* 626 * Raw mode, just put character 627 * in input q w/o interpretation. 628 */ 629 if (tp->t_rawq.c_cc > TTYHOG) 630 ttyflush(tp, FREAD|FWRITE); 631 else { 632 if (putc(c, &tp->t_rawq) >= 0) 633 ttwakeup(tp); 634 ttyecho(c, tp); 635 } 636 goto endcase; 637 } 638 639 /* 640 * Ignore any high bit added during 641 * previous ttyinput processing. 642 */ 643 if ((tp->t_state&TS_TYPEN) == 0) 644 c &= 0177; 645 /* 646 * Check for literal nexting very first 647 */ 648 if (tp->t_state&TS_LNCH) { 649 c |= 0200; 650 tp->t_state &= ~TS_LNCH; 651 } 652 653 /* 654 * Scan for special characters. This code 655 * is really just a big case statement with 656 * non-constant cases. The bottom of the 657 * case statement is labeled ``endcase'', so goto 658 * it after a case match, or similar. 659 */ 660 if (tp->t_line == NTTYDISC) { 661 if (c == tp->t_lnextc) { 662 if (tp->t_flags&ECHO) 663 ttyout("^\b", tp); 664 tp->t_state |= TS_LNCH; 665 goto endcase; 666 } 667 if (c == tp->t_flushc) { 668 if (tp->t_flags&FLUSHO) 669 tp->t_flags &= ~FLUSHO; 670 else { 671 ttyflush(tp, FWRITE); 672 ttyecho(c, tp); 673 if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 674 ttyretype(tp); 675 tp->t_flags |= FLUSHO; 676 } 677 goto startoutput; 678 } 679 if (c == tp->t_suspc) { 680 if ((tp->t_flags&NOFLSH) == 0) 681 ttyflush(tp, FREAD); 682 ttyecho(c, tp); 683 gsignal(tp->t_pgrp, SIGTSTP); 684 goto endcase; 685 } 686 } 687 688 /* 689 * Handle start/stop characters. 690 */ 691 if (c == tp->t_stopc) { 692 if ((tp->t_state&TS_TTSTOP) == 0) { 693 tp->t_state |= TS_TTSTOP; 694 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 695 return; 696 } 697 if (c != tp->t_startc) 698 return; 699 goto endcase; 700 } 701 if (c == tp->t_startc) 702 goto restartoutput; 703 704 /* 705 * Look for interrupt/quit chars. 706 */ 707 if (c == tp->t_intrc || c == tp->t_quitc) { 708 if ((tp->t_flags&NOFLSH) == 0) 709 ttyflush(tp, FREAD|FWRITE); 710 ttyecho(c, tp); 711 gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT); 712 goto endcase; 713 } 714 715 /* 716 * Cbreak mode, don't process line editing 717 * characters; check high water mark for wakeup. 718 */ 719 if (t_flags&CBREAK) { 720 if (tp->t_rawq.c_cc > TTYHOG) { 721 if (tp->t_outq.c_cc < TTHIWAT(tp) && 722 tp->t_line == NTTYDISC) 723 (void) ttyoutput(CTRL(g), tp); 724 } else if (putc(c, &tp->t_rawq) >= 0) { 725 ttwakeup(tp); 726 ttyecho(c, tp); 727 } 728 goto endcase; 729 } 730 731 /* 732 * From here on down cooked mode character 733 * processing takes place. 734 */ 735 if ((tp->t_state&TS_QUOT) && 736 (c == tp->t_erase || c == tp->t_kill)) { 737 ttyrub(unputc(&tp->t_rawq), tp); 738 c |= 0200; 739 } 740 if (c == tp->t_erase) { 741 if (tp->t_rawq.c_cc) 742 ttyrub(unputc(&tp->t_rawq), tp); 743 goto endcase; 744 } 745 if (c == tp->t_kill) { 746 if (tp->t_flags&CRTKIL && 747 tp->t_rawq.c_cc == tp->t_rocount) { 748 while (tp->t_rawq.c_cc) 749 ttyrub(unputc(&tp->t_rawq), tp); 750 } else { 751 ttyecho(c, tp); 752 ttyecho('\n', tp); 753 while (getc(&tp->t_rawq) > 0) 754 ; 755 tp->t_rocount = 0; 756 } 757 tp->t_state &= ~TS_LOCAL; 758 goto endcase; 759 } 760 761 /* 762 * New line discipline, 763 * check word erase/reprint line. 764 */ 765 if (tp->t_line == NTTYDISC) { 766 if (c == tp->t_werasc) { 767 if (tp->t_rawq.c_cc == 0) 768 goto endcase; 769 do { 770 c = unputc(&tp->t_rawq); 771 if (c != ' ' && c != '\t') 772 goto erasenb; 773 ttyrub(c, tp); 774 } while (tp->t_rawq.c_cc); 775 goto endcase; 776 erasenb: 777 do { 778 ttyrub(c, tp); 779 if (tp->t_rawq.c_cc == 0) 780 goto endcase; 781 c = unputc(&tp->t_rawq); 782 } while (c != ' ' && c != '\t'); 783 (void) putc(c, &tp->t_rawq); 784 goto endcase; 785 } 786 if (c == tp->t_rprntc) { 787 ttyretype(tp); 788 goto endcase; 789 } 790 } 791 792 /* 793 * Check for input buffer overflow 794 */ 795 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 796 if (tp->t_line == NTTYDISC) 797 (void) ttyoutput(CTRL(g), tp); 798 goto endcase; 799 } 800 801 /* 802 * Put data char in q for user and 803 * wakeup on seeing a line delimiter. 804 */ 805 if (putc(c, &tp->t_rawq) >= 0) { 806 if (ttbreakc(c, tp)) { 807 tp->t_rocount = 0; 808 catq(&tp->t_rawq, &tp->t_canq); 809 ttwakeup(tp); 810 } else if (tp->t_rocount++ == 0) 811 tp->t_rocol = tp->t_col; 812 tp->t_state &= ~TS_QUOT; 813 if (c == '\\') 814 tp->t_state |= TS_QUOT; 815 if (tp->t_state&TS_ERASE) { 816 tp->t_state &= ~TS_ERASE; 817 (void) ttyoutput('/', tp); 818 } 819 i = tp->t_col; 820 ttyecho(c, tp); 821 if (c == tp->t_eofc && tp->t_flags&ECHO) { 822 i = MIN(2, tp->t_col - i); 823 while (i > 0) { 824 (void) ttyoutput('\b', tp); 825 i--; 826 } 827 } 828 } 829 830 endcase: 831 /* 832 * If DEC-style start/stop is enabled don't restart 833 * output until seeing the start character. 834 */ 835 if (tp->t_flags&DECCTQ && tp->t_state&TS_TTSTOP && 836 tp->t_startc != tp->t_stopc) 837 return; 838 839 restartoutput: 840 tp->t_state &= ~TS_TTSTOP; 841 tp->t_flags &= ~FLUSHO; 842 843 startoutput: 844 ttstart(tp); 845 } 846 847 /* 848 * Put character on TTY output queue, adding delays, 849 * expanding tabs, and handling the CR/NL bit. 850 * This is called both from the top half for output, 851 * and from interrupt level for echoing. 852 * The arguments are the character and the tty structure. 853 * Returns < 0 if putc succeeds, otherwise returns char to resend 854 * Must be recursive. 855 */ 856 ttyoutput(c, tp) 857 register c; 858 register struct tty *tp; 859 { 860 register char *colp; 861 register ctype; 862 863 if (tp->t_flags & (RAW|LITOUT)) { 864 if (tp->t_flags&FLUSHO) 865 return (-1); 866 if (putc(c, &tp->t_outq)) 867 return (c); 868 tk_nout++; 869 return (-1); 870 } 871 872 /* 873 * Ignore EOT in normal mode to avoid 874 * hanging up certain terminals. 875 */ 876 c &= 0177; 877 if (c == CEOT && (tp->t_flags&CBREAK) == 0) 878 return (-1); 879 /* 880 * Turn tabs to spaces as required 881 */ 882 if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) { 883 register int s; 884 885 c = 8 - (tp->t_col&7); 886 if ((tp->t_flags&FLUSHO) == 0) { 887 s = spl5(); /* don't interrupt tabs */ 888 c -= b_to_q(" ", c, &tp->t_outq); 889 tk_nout += c; 890 splx(s); 891 } 892 tp->t_col += c; 893 return (c ? -1 : '\t'); 894 } 895 tk_nout++; 896 /* 897 * for upper-case-only terminals, 898 * generate escapes. 899 */ 900 if (tp->t_flags&LCASE) { 901 colp = "({)}!|^~'`"; 902 while (*colp++) 903 if (c == *colp++) { 904 if (ttyoutput('\\', tp) >= 0) 905 return (c); 906 c = colp[-2]; 907 break; 908 } 909 if ('A' <= c && c <= 'Z') { 910 if (ttyoutput('\\', tp) >= 0) 911 return (c); 912 } else if ('a' <= c && c <= 'z') 913 c += 'A' - 'a'; 914 } 915 916 /* 917 * turn <nl> to <cr><lf> if desired. 918 */ 919 if (c == '\n' && tp->t_flags&CRMOD) 920 if (ttyoutput('\r', tp) >= 0) 921 return (c); 922 if (c == '~' && tp->t_flags&TILDE) 923 c = '`'; 924 if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq)) 925 return (c); 926 /* 927 * Calculate delays. 928 * The numbers here represent clock ticks 929 * and are not necessarily optimal for all terminals. 930 * The delays are indicated by characters above 0200. 931 * In raw mode there are no delays and the 932 * transmission path is 8 bits wide. 933 * 934 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS 935 */ 936 colp = &tp->t_col; 937 ctype = partab[c]; 938 c = 0; 939 switch (ctype&077) { 940 941 case ORDINARY: 942 (*colp)++; 943 944 case CONTROL: 945 break; 946 947 case BACKSPACE: 948 if (*colp) 949 (*colp)--; 950 break; 951 952 /* 953 * This macro is close enough to the correct thing; 954 * it should be replaced by real user settable delays 955 * in any event... 956 */ 957 #define mstohz(ms) (((ms) * hz) >> 10) 958 case NEWLINE: 959 ctype = (tp->t_flags >> 8) & 03; 960 if (ctype == 1) { /* tty 37 */ 961 if (*colp > 0) 962 c = max((((unsigned)*colp) >> 4) + 3, 963 (unsigned)6); 964 } else if (ctype == 2) /* vt05 */ 965 c = mstohz(100); 966 *colp = 0; 967 break; 968 969 case TAB: 970 ctype = (tp->t_flags >> 10) & 03; 971 if (ctype == 1) { /* tty 37 */ 972 c = 1 - (*colp | ~07); 973 if (c < 5) 974 c = 0; 975 } 976 *colp |= 07; 977 (*colp)++; 978 break; 979 980 case VTAB: 981 if (tp->t_flags&VTDELAY) /* tty 37 */ 982 c = 0177; 983 break; 984 985 case RETURN: 986 ctype = (tp->t_flags >> 12) & 03; 987 if (ctype == 1) /* tn 300 */ 988 c = mstohz(83); 989 else if (ctype == 2) /* ti 700 */ 990 c = mstohz(166); 991 else if (ctype == 3) { /* concept 100 */ 992 int i; 993 994 if ((i = *colp) >= 0) 995 for (; i < 9; i++) 996 (void) putc(0177, &tp->t_outq); 997 } 998 *colp = 0; 999 } 1000 if (c && (tp->t_flags&FLUSHO) == 0) 1001 (void) putc(c|0200, &tp->t_outq); 1002 return (-1); 1003 } 1004 #undef mstohz 1005 1006 /* 1007 * Called from device's read routine after it has 1008 * calculated the tty-structure given as argument. 1009 */ 1010 ttread(tp, uio) 1011 register struct tty *tp; 1012 struct uio *uio; 1013 { 1014 register struct clist *qp; 1015 register c, t_flags; 1016 int s, first, error = 0; 1017 1018 if ((tp->t_state&TS_CARR_ON)==0) 1019 return (EIO); 1020 loop: 1021 /* 1022 * Take any pending input first. 1023 */ 1024 s = spl5(); 1025 if (tp->t_flags&PENDIN) 1026 ttypend(tp); 1027 splx(s); 1028 1029 /* 1030 * Hang process if it's in the background. 1031 */ 1032 #define bit(a) (1<<(a-1)) 1033 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 1034 if ((u.u_procp->p_sigignore & bit(SIGTTIN)) || 1035 (u.u_procp->p_sigmask & bit(SIGTTIN)) || 1036 /* 1037 (u.u_procp->p_flag&SDETACH) || 1038 */ 1039 u.u_procp->p_flag&SVFORK) 1040 return (EIO); 1041 gsignal(u.u_procp->p_pgrp, SIGTTIN); 1042 sleep((caddr_t)&lbolt, TTIPRI); 1043 } 1044 t_flags = tp->t_flags; 1045 #undef bit 1046 1047 /* 1048 * In raw mode take characters directly from the 1049 * raw queue w/o processing. Interlock against 1050 * device interrupts when interrogating rawq. 1051 */ 1052 if (t_flags&RAW) { 1053 s = spl5(); 1054 if (tp->t_rawq.c_cc <= 0) { 1055 if ((tp->t_state&TS_CARR_ON) == 0 || 1056 (tp->t_state&TS_NBIO)) { 1057 splx(s); 1058 return (EWOULDBLOCK); 1059 } 1060 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1061 splx(s); 1062 goto loop; 1063 } 1064 splx(s); 1065 while (!error && tp->t_rawq.c_cc && uio->uio_resid) 1066 error = ureadc(getc(&tp->t_rawq), uio); 1067 goto checktandem; 1068 } 1069 1070 /* 1071 * In cbreak mode use the rawq, otherwise 1072 * take characters from the canonicalized q. 1073 */ 1074 qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq; 1075 1076 /* 1077 * No input, sleep on rawq awaiting hardware 1078 * receipt and notification. 1079 */ 1080 s = spl5(); 1081 if (qp->c_cc <= 0) { 1082 if ((tp->t_state&TS_CARR_ON) == 0 || 1083 (tp->t_state&TS_NBIO)) { 1084 splx(s); 1085 return (EWOULDBLOCK); 1086 } 1087 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1088 splx(s); 1089 goto loop; 1090 } 1091 splx(s); 1092 1093 /* 1094 * Input present, perform input mapping 1095 * and processing (we're not in raw mode). 1096 */ 1097 first = 1; 1098 while ((c = getc(qp)) >= 0) { 1099 if (t_flags&CRMOD && c == '\r') 1100 c = '\n'; 1101 /* 1102 * Hack lower case simulation on 1103 * upper case only terminals. 1104 */ 1105 if (t_flags&LCASE && c <= 0177) 1106 if (tp->t_state&TS_BKSL) { 1107 if (maptab[c]) 1108 c = maptab[c]; 1109 tp->t_state &= ~TS_BKSL; 1110 } else if (c >= 'A' && c <= 'Z') 1111 c += 'a' - 'A'; 1112 else if (c == '\\') { 1113 tp->t_state |= TS_BKSL; 1114 continue; 1115 } 1116 /* 1117 * Check for delayed suspend character. 1118 */ 1119 if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) { 1120 gsignal(tp->t_pgrp, SIGTSTP); 1121 if (first) { 1122 sleep((caddr_t)&lbolt, TTIPRI); 1123 goto loop; 1124 } 1125 break; 1126 } 1127 /* 1128 * Interpret EOF only in cooked mode. 1129 */ 1130 if (c == tp->t_eofc && (t_flags&CBREAK) == 0) 1131 break; 1132 /* 1133 * Give user character. 1134 */ 1135 error = ureadc(c & 0177, uio); 1136 if (error) 1137 break; 1138 if (uio->uio_resid == 0) 1139 break; 1140 /* 1141 * In cooked mode check for a "break character" 1142 * marking the end of a "line of input". 1143 */ 1144 if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp)) 1145 break; 1146 first = 0; 1147 } 1148 tp->t_state &= ~TS_BKSL; 1149 1150 checktandem: 1151 /* 1152 * Look to unblock output now that (presumably) 1153 * the input queue has gone down. 1154 */ 1155 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) 1156 if (putc(tp->t_startc, &tp->t_outq) == 0) { 1157 tp->t_state &= ~TS_TBLOCK; 1158 ttstart(tp); 1159 } 1160 return (error); 1161 } 1162 1163 /* 1164 * Called from the device's write routine after it has 1165 * calculated the tty-structure given as argument. 1166 */ 1167 ttwrite(tp, uio) 1168 register struct tty *tp; 1169 register struct uio *uio; 1170 { 1171 register char *cp; 1172 register int cc, ce, c; 1173 int i, hiwat, cnt, error, s; 1174 char obuf[OBUFSIZ]; 1175 1176 if ((tp->t_state&TS_CARR_ON) == 0) 1177 return (EIO); 1178 hiwat = TTHIWAT(tp); 1179 cnt = uio->uio_resid; 1180 error = 0; 1181 loop: 1182 /* 1183 * Hang the process if it's in the background. 1184 */ 1185 #define bit(a) (1<<(a-1)) 1186 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 1187 (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 1188 !(u.u_procp->p_sigignore & bit(SIGTTOU)) && 1189 !(u.u_procp->p_sigmask & bit(SIGTTOU)) 1190 /* 1191 && 1192 (u.u_procp->p_flag&SDETACH)==0) { 1193 */ 1194 ) { 1195 gsignal(u.u_procp->p_pgrp, SIGTTOU); 1196 sleep((caddr_t)&lbolt, TTIPRI); 1197 } 1198 #undef bit 1199 1200 /* 1201 * Process the user's data in at most OBUFSIZ 1202 * chunks. Perform lower case simulation and 1203 * similar hacks. Keep track of high water 1204 * mark, sleep on overflow awaiting device aid 1205 * in acquiring new space. 1206 */ 1207 while (uio->uio_resid > 0) { 1208 /* 1209 * Grab a hunk of data from the user. 1210 */ 1211 cc = uio->uio_iov->iov_len; 1212 if (cc == 0) { 1213 uio->uio_iovcnt--; 1214 uio->uio_iov++; 1215 if (uio->uio_iovcnt < 0) 1216 panic("ttwrite"); 1217 continue; 1218 } 1219 if (cc > OBUFSIZ) 1220 cc = OBUFSIZ; 1221 cp = obuf; 1222 error = uiomove(cp, cc, UIO_WRITE, uio); 1223 if (error) 1224 break; 1225 if (tp->t_outq.c_cc > hiwat) 1226 goto ovhiwat; 1227 if (tp->t_flags&FLUSHO) 1228 continue; 1229 /* 1230 * If we're mapping lower case or kludging tildes, 1231 * then we've got to look at each character, so 1232 * just feed the stuff to ttyoutput... 1233 */ 1234 if (tp->t_flags & (LCASE|TILDE)) { 1235 while (cc > 0) { 1236 c = *cp++; 1237 tp->t_rocount = 0; 1238 while ((c = ttyoutput(c, tp)) >= 0) { 1239 /* out of clists, wait a bit */ 1240 ttstart(tp); 1241 sleep((caddr_t)&lbolt, TTOPRI); 1242 tp->t_rocount = 0; 1243 } 1244 --cc; 1245 if (tp->t_outq.c_cc > hiwat) 1246 goto ovhiwat; 1247 } 1248 continue; 1249 } 1250 /* 1251 * If nothing fancy need be done, grab those characters we 1252 * can handle without any of ttyoutput's processing and 1253 * just transfer them to the output q. For those chars 1254 * which require special processing (as indicated by the 1255 * bits in partab), call ttyoutput. After processing 1256 * a hunk of data, look for FLUSHO so ^O's will take effect 1257 * immediately. 1258 */ 1259 while (cc > 0) { 1260 if (tp->t_flags & (RAW|LITOUT)) 1261 ce = cc; 1262 else { 1263 ce = cc - scanc((unsigned)cc, (caddr_t)cp, 1264 (caddr_t)partab, 077); 1265 /* 1266 * If ce is zero, then we're processing 1267 * a special character through ttyoutput. 1268 */ 1269 if (ce == 0) { 1270 tp->t_rocount = 0; 1271 if (ttyoutput(*cp, tp) >= 0) { 1272 /* no c-lists, wait a bit */ 1273 ttstart(tp); 1274 sleep((caddr_t)&lbolt, TTOPRI); 1275 continue; 1276 } 1277 cp++, cc--; 1278 if (tp->t_flags&FLUSHO || 1279 tp->t_outq.c_cc > hiwat) 1280 goto ovhiwat; 1281 continue; 1282 } 1283 } 1284 /* 1285 * A bunch of normal characters have been found, 1286 * transfer them en masse to the output queue and 1287 * continue processing at the top of the loop. 1288 * If there are any further characters in this 1289 * <= OBUFSIZ chunk, the first should be a character 1290 * requiring special handling by ttyoutput. 1291 */ 1292 tp->t_rocount = 0; 1293 i = b_to_q(cp, ce, &tp->t_outq); 1294 ce -= i; 1295 tp->t_col += ce; 1296 cp += ce, cc -= ce, tk_nout += ce; 1297 if (i > 0) { 1298 /* out of c-lists, wait a bit */ 1299 ttstart(tp); 1300 sleep((caddr_t)&lbolt, TTOPRI); 1301 } 1302 if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat) 1303 goto ovhiwat; 1304 } 1305 } 1306 ttstart(tp); 1307 return (error); 1308 1309 ovhiwat: 1310 s = spl5(); 1311 if (cc != 0) { 1312 uio->uio_iov->iov_base -= cc; 1313 uio->uio_iov->iov_len += cc; 1314 uio->uio_resid += cc; 1315 uio->uio_offset -= cc; 1316 } 1317 /* 1318 * This can only occur if FLUSHO 1319 * is also set in t_flags. 1320 */ 1321 if (tp->t_outq.c_cc <= hiwat) { 1322 splx(s); 1323 goto loop; 1324 } 1325 ttstart(tp); 1326 if (tp->t_state&TS_NBIO) { 1327 if (uio->uio_resid == cnt) 1328 return (EWOULDBLOCK); 1329 return (0); 1330 } 1331 tp->t_state |= TS_ASLEEP; 1332 sleep((caddr_t)&tp->t_outq, TTOPRI); 1333 splx(s); 1334 goto loop; 1335 } 1336 1337 /* 1338 * Rubout one character from the rawq of tp 1339 * as cleanly as possible. 1340 */ 1341 ttyrub(c, tp) 1342 register c; 1343 register struct tty *tp; 1344 { 1345 register char *cp; 1346 register int savecol; 1347 int s; 1348 char *nextc(); 1349 1350 if ((tp->t_flags&ECHO) == 0) 1351 return; 1352 tp->t_flags &= ~FLUSHO; 1353 c &= 0377; 1354 if (tp->t_flags&CRTBS) { 1355 if (tp->t_rocount == 0) { 1356 /* 1357 * Screwed by ttwrite; retype 1358 */ 1359 ttyretype(tp); 1360 return; 1361 } 1362 if (c == ('\t'|0200) || c == ('\n'|0200)) 1363 ttyrubo(tp, 2); 1364 else switch (partab[c&=0177]&0177) { 1365 1366 case ORDINARY: 1367 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z') 1368 ttyrubo(tp, 2); 1369 else 1370 ttyrubo(tp, 1); 1371 break; 1372 1373 case VTAB: 1374 case BACKSPACE: 1375 case CONTROL: 1376 case RETURN: 1377 if (tp->t_flags&CTLECH) 1378 ttyrubo(tp, 2); 1379 break; 1380 1381 case TAB: 1382 if (tp->t_rocount < tp->t_rawq.c_cc) { 1383 ttyretype(tp); 1384 return; 1385 } 1386 s = spl5(); 1387 savecol = tp->t_col; 1388 tp->t_state |= TS_CNTTB; 1389 tp->t_flags |= FLUSHO; 1390 tp->t_col = tp->t_rocol; 1391 cp = tp->t_rawq.c_cf; 1392 for (; cp; cp = nextc(&tp->t_rawq, cp)) 1393 ttyecho(*cp, tp); 1394 tp->t_flags &= ~FLUSHO; 1395 tp->t_state &= ~TS_CNTTB; 1396 splx(s); 1397 /* 1398 * savecol will now be length of the tab 1399 */ 1400 savecol -= tp->t_col; 1401 tp->t_col += savecol; 1402 if (savecol > 8) 1403 savecol = 8; /* overflow screw */ 1404 while (--savecol >= 0) 1405 (void) ttyoutput('\b', tp); 1406 break; 1407 1408 default: 1409 panic("ttyrub"); 1410 } 1411 } else if (tp->t_flags&PRTERA) { 1412 if ((tp->t_state&TS_ERASE) == 0) { 1413 (void) ttyoutput('\\', tp); 1414 tp->t_state |= TS_ERASE; 1415 } 1416 ttyecho(c, tp); 1417 } else 1418 ttyecho(tp->t_erase, tp); 1419 tp->t_rocount--; 1420 } 1421 1422 /* 1423 * Crt back over cnt chars perhaps 1424 * erasing them. 1425 */ 1426 ttyrubo(tp, cnt) 1427 register struct tty *tp; 1428 int cnt; 1429 { 1430 register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b"; 1431 1432 while (--cnt >= 0) 1433 ttyout(rubostring, tp); 1434 } 1435 1436 /* 1437 * Reprint the rawq line. 1438 * We assume c_cc has already been checked. 1439 */ 1440 ttyretype(tp) 1441 register struct tty *tp; 1442 { 1443 register char *cp; 1444 char *nextc(); 1445 int s; 1446 1447 if (tp->t_rprntc != 0377) 1448 ttyecho(tp->t_rprntc, tp); 1449 (void) ttyoutput('\n', tp); 1450 s = spl5(); 1451 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp)) 1452 ttyecho(*cp, tp); 1453 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 1454 ttyecho(*cp, tp); 1455 tp->t_state &= ~TS_ERASE; 1456 splx(s); 1457 tp->t_rocount = tp->t_rawq.c_cc; 1458 tp->t_rocol = 0; 1459 } 1460 1461 /* 1462 * Echo a typed character to the terminal 1463 */ 1464 ttyecho(c, tp) 1465 register c; 1466 register struct tty *tp; 1467 { 1468 1469 if ((tp->t_state&TS_CNTTB) == 0) 1470 tp->t_flags &= ~FLUSHO; 1471 if ((tp->t_flags&ECHO) == 0) 1472 return; 1473 c &= 0377; 1474 if (tp->t_flags&RAW) { 1475 (void) ttyoutput(c, tp); 1476 return; 1477 } 1478 if (c == '\r' && tp->t_flags&CRMOD) 1479 c = '\n'; 1480 if (tp->t_flags&CTLECH) { 1481 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) { 1482 (void) ttyoutput('^', tp); 1483 c &= 0177; 1484 if (c == 0177) 1485 c = '?'; 1486 else if (tp->t_flags&LCASE) 1487 c += 'a' - 1; 1488 else 1489 c += 'A' - 1; 1490 } 1491 } 1492 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z')) 1493 c += 'a' - 'A'; 1494 (void) ttyoutput(c&0177, tp); 1495 } 1496 1497 /* 1498 * Is c a break char for tp? 1499 */ 1500 ttbreakc(c, tp) 1501 register c; 1502 register struct tty *tp; 1503 { 1504 return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc || 1505 c == '\r' && (tp->t_flags&CRMOD)); 1506 } 1507 1508 /* 1509 * send string cp to tp 1510 */ 1511 ttyout(cp, tp) 1512 register char *cp; 1513 register struct tty *tp; 1514 { 1515 register char c; 1516 1517 while (c = *cp++) 1518 (void) ttyoutput(c, tp); 1519 } 1520 1521 ttwakeup(tp) 1522 struct tty *tp; 1523 { 1524 1525 if (tp->t_rsel) { 1526 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 1527 tp->t_state &= ~TS_RCOLL; 1528 tp->t_rsel = 0; 1529 } 1530 if (tp->t_state & TS_ASYNC) 1531 gsignal(tp->t_pgrp, SIGIO); 1532 wakeup((caddr_t)&tp->t_rawq); 1533 } 1534 1535 #if !defined(vax) 1536 scanc(size, cp, table, mask) 1537 register int size; 1538 register char *cp, table[]; 1539 register int mask; 1540 { 1541 register int i = 0; 1542 1543 while ((table[*(u_char *)(cp + i)]&mask) == 0 && i < size) 1544 i++; 1545 return (size - i); 1546 } 1547 #endif 1548