1 /* tty.c 6.7 83/10/01 */ 2 3 #include "../machine/reg.h" 4 5 #include "../h/param.h" 6 #include "../h/systm.h" 7 #include "../h/dir.h" 8 #include "../h/user.h" 9 #include "../h/ioctl.h" 10 #include "../h/tty.h" 11 #include "../h/proc.h" 12 #include "../h/inode.h" 13 #include "../h/file.h" 14 #include "../h/conf.h" 15 #include "../h/buf.h" 16 #include "../h/dk.h" 17 #include "../h/uio.h" 18 #include "../h/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_delct = 0; 162 tp->t_rocount = 0; 163 tp->t_rocol = 0; 164 tp->t_state &= ~TS_LOCAL; 165 } 166 splx(s); 167 } 168 169 /* 170 * Send stop character on input overflow. 171 */ 172 ttyblock(tp) 173 register struct tty *tp; 174 { 175 register x; 176 177 x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 178 if (tp->t_rawq.c_cc > TTYHOG) { 179 ttyflush(tp, FREAD|FWRITE); 180 tp->t_state &= ~TS_TBLOCK; 181 } 182 /* 183 * Block further input iff: 184 * Current input > threshold AND input is available to user program 185 */ 186 if (x >= TTYHOG/2 && (tp->t_delct>0 || (tp->t_flags&(RAW|CBREAK)))) { 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 && u.u_ttyp != tp) 364 return (EACCES); 365 (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 366 break; 367 368 case TIOCSETP: 369 case TIOCSETN: { 370 register struct sgttyb *sg = (struct sgttyb *)data; 371 372 tp->t_erase = sg->sg_erase; 373 tp->t_kill = sg->sg_kill; 374 tp->t_ispeed = sg->sg_ispeed; 375 tp->t_ospeed = sg->sg_ospeed; 376 newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff); 377 s = spl5(); 378 if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) { 379 ttywait(tp); 380 ttyflush(tp, FREAD); 381 } else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) { 382 if (newflags&CBREAK) { 383 struct clist tq; 384 385 catq(&tp->t_rawq, &tp->t_canq); 386 tq = tp->t_rawq; 387 tp->t_rawq = tp->t_canq; 388 tp->t_canq = tq; 389 } else { 390 tp->t_flags |= PENDIN; 391 newflags |= PENDIN; 392 ttwakeup(tp); 393 } 394 } 395 tp->t_flags = newflags; 396 if (tp->t_flags&RAW) { 397 tp->t_state &= ~TS_TTSTOP; 398 ttstart(tp); 399 } 400 splx(s); 401 break; 402 } 403 404 /* send current parameters to user */ 405 case TIOCGETP: { 406 register struct sgttyb *sg = (struct sgttyb *)data; 407 408 sg->sg_ispeed = tp->t_ispeed; 409 sg->sg_ospeed = tp->t_ospeed; 410 sg->sg_erase = tp->t_erase; 411 sg->sg_kill = tp->t_kill; 412 sg->sg_flags = tp->t_flags; 413 break; 414 } 415 416 case FIONBIO: 417 if (*(int *)data) 418 tp->t_state |= TS_NBIO; 419 else 420 tp->t_state &= ~TS_NBIO; 421 break; 422 423 case FIOASYNC: 424 if (*(int *)data) 425 tp->t_state |= TS_ASYNC; 426 else 427 tp->t_state &= ~TS_ASYNC; 428 break; 429 430 case TIOCGETC: 431 bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars)); 432 break; 433 434 case TIOCSETC: 435 bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars)); 436 break; 437 438 /* set/get local special characters */ 439 case TIOCSLTC: 440 bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars)); 441 break; 442 443 case TIOCGLTC: 444 bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars)); 445 break; 446 447 /* 448 * Modify local mode word. 449 */ 450 case TIOCLBIS: 451 tp->t_flags |= *(int *)data << 16; 452 break; 453 454 case TIOCLBIC: 455 tp->t_flags &= ~(*(int *)data << 16); 456 break; 457 458 case TIOCLSET: 459 tp->t_flags &= 0xffff; 460 tp->t_flags |= *(int *)data << 16; 461 break; 462 463 case TIOCLGET: 464 *(int *)data = tp->t_flags >> 16; 465 break; 466 467 /* should allow SPGRP and GPGRP only if tty open for reading */ 468 case TIOCSPGRP: 469 tp->t_pgrp = *(int *)data; 470 break; 471 472 case TIOCGPGRP: 473 *(int *)data = tp->t_pgrp; 474 break; 475 476 default: 477 return (-1); 478 } 479 return (0); 480 } 481 482 ttnread(tp) 483 struct tty *tp; 484 { 485 int nread = 0; 486 487 if (tp->t_flags & PENDIN) 488 ttypend(tp); 489 nread = tp->t_canq.c_cc; 490 if (tp->t_flags & (RAW|CBREAK)) 491 nread += tp->t_rawq.c_cc; 492 return (nread); 493 } 494 495 ttselect(dev, rw) 496 dev_t dev; 497 int rw; 498 { 499 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 500 int nread; 501 int s = spl5(); 502 503 switch (rw) { 504 505 case FREAD: 506 nread = ttnread(tp); 507 if (nread > 0) 508 goto win; 509 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 510 tp->t_state |= TS_RCOLL; 511 else 512 tp->t_rsel = u.u_procp; 513 break; 514 515 case FWRITE: 516 if (tp->t_outq.c_cc <= TTLOWAT(tp)) 517 goto win; 518 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 519 tp->t_state |= TS_WCOLL; 520 else 521 tp->t_wsel = u.u_procp; 522 break; 523 } 524 splx(s); 525 return (0); 526 win: 527 splx(s); 528 return (1); 529 } 530 531 /* 532 * Establish a process group for distribution of 533 * quits and interrupts from the tty. 534 */ 535 ttyopen(dev, tp) 536 dev_t dev; 537 register struct tty *tp; 538 { 539 register struct proc *pp; 540 541 pp = u.u_procp; 542 tp->t_dev = dev; 543 if (pp->p_pgrp == 0) { 544 u.u_ttyp = tp; 545 u.u_ttyd = dev; 546 if (tp->t_pgrp == 0) 547 tp->t_pgrp = pp->p_pid; 548 pp->p_pgrp = tp->t_pgrp; 549 } 550 tp->t_state &= ~TS_WOPEN; 551 tp->t_state |= TS_ISOPEN; 552 if (tp->t_line != NTTYDISC) 553 ttywflush(tp); 554 return (0); 555 } 556 557 /* 558 * clean tp on last close 559 */ 560 ttyclose(tp) 561 register struct tty *tp; 562 { 563 564 if (tp->t_line) { 565 ttywflush(tp); 566 tp->t_line = 0; 567 return; 568 } 569 tp->t_pgrp = 0; 570 ttywflush(tp); 571 tp->t_state = 0; 572 } 573 574 /* 575 * reinput pending characters after state switch 576 * call at spl5(). 577 */ 578 ttypend(tp) 579 register struct tty *tp; 580 { 581 struct clist tq; 582 register c; 583 584 tp->t_flags &= ~PENDIN; 585 tp->t_state |= TS_TYPEN; 586 tq = tp->t_rawq; 587 tp->t_rawq.c_cc = 0; 588 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 589 while ((c = getc(&tq)) >= 0) 590 ttyinput(c, tp); 591 tp->t_state &= ~TS_TYPEN; 592 } 593 594 /* 595 * Place a character on raw TTY input queue, 596 * putting in delimiters and waking up top 597 * half as needed. Also echo if required. 598 * The arguments are the character and the 599 * appropriate tty structure. 600 */ 601 ttyinput(c, tp) 602 register c; 603 register struct tty *tp; 604 { 605 register int t_flags = tp->t_flags; 606 int i; 607 608 /* 609 * If input is pending take it first. 610 */ 611 if (t_flags&PENDIN) 612 ttypend(tp); 613 tk_nin++; 614 c &= 0377; 615 616 /* 617 * In tandem mode, check high water mark. 618 */ 619 if (t_flags&TANDEM) 620 ttyblock(tp); 621 622 if (t_flags&RAW) { 623 /* 624 * Raw mode, just put character 625 * in input q w/o interpretation. 626 */ 627 if (tp->t_rawq.c_cc > TTYHOG) 628 ttyflush(tp, FREAD|FWRITE); 629 else { 630 if (putc(c, &tp->t_rawq) >= 0) 631 ttwakeup(tp); 632 ttyecho(c, tp); 633 } 634 goto endcase; 635 } 636 637 /* 638 * Ignore any high bit added during 639 * previous ttyinput processing. 640 */ 641 if ((tp->t_state&TS_TYPEN) == 0) 642 c &= 0177; 643 /* 644 * Check for literal nexting very first 645 */ 646 if (tp->t_state&TS_LNCH) { 647 c |= 0200; 648 tp->t_state &= ~TS_LNCH; 649 } 650 651 /* 652 * Scan for special characters. This code 653 * is really just a big case statement with 654 * non-constant cases. The bottom of the 655 * case statement is labeled ``endcase'', so goto 656 * it after a case match, or similar. 657 */ 658 if (tp->t_line == NTTYDISC) { 659 if (c == tp->t_lnextc) { 660 if (tp->t_flags&ECHO) 661 ttyout("^\b", tp); 662 tp->t_state |= TS_LNCH; 663 goto endcase; 664 } 665 if (c == tp->t_flushc) { 666 if (tp->t_flags&FLUSHO) 667 tp->t_flags &= ~FLUSHO; 668 else { 669 ttyflush(tp, FWRITE); 670 ttyecho(c, tp); 671 if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 672 ttyretype(tp); 673 tp->t_flags |= FLUSHO; 674 } 675 goto startoutput; 676 } 677 if (c == tp->t_suspc) { 678 if ((tp->t_flags&NOFLSH) == 0) 679 ttyflush(tp, FREAD); 680 ttyecho(c, tp); 681 gsignal(tp->t_pgrp, SIGTSTP); 682 goto endcase; 683 } 684 } 685 686 /* 687 * Handle start/stop characters. 688 */ 689 if (c == tp->t_stopc) { 690 if ((tp->t_state&TS_TTSTOP) == 0) { 691 tp->t_state |= TS_TTSTOP; 692 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 693 return; 694 } 695 if (c != tp->t_startc) 696 return; 697 goto endcase; 698 } 699 if (c == tp->t_startc) 700 goto restartoutput; 701 702 /* 703 * Look for interrupt/quit chars. 704 */ 705 if (c == tp->t_intrc || c == tp->t_quitc) { 706 if ((tp->t_flags&NOFLSH) == 0) 707 ttyflush(tp, FREAD|FWRITE); 708 ttyecho(c, tp); 709 gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT); 710 goto endcase; 711 } 712 713 /* 714 * Cbreak mode, don't process line editing 715 * characters; check high water mark for wakeup. 716 */ 717 if (t_flags&CBREAK) { 718 if (tp->t_rawq.c_cc > TTYHOG) { 719 if (tp->t_outq.c_cc < TTHIWAT(tp) && 720 tp->t_line == NTTYDISC) 721 (void) ttyoutput(CTRL(g), tp); 722 } else if (putc(c, &tp->t_rawq) >= 0) { 723 ttwakeup(tp); 724 ttyecho(c, tp); 725 } 726 goto endcase; 727 } 728 729 /* 730 * From here on down cooked mode character 731 * processing takes place. 732 */ 733 if ((tp->t_state&TS_QUOT) && 734 (c == tp->t_erase || c == tp->t_kill)) { 735 ttyrub(unputc(&tp->t_rawq), tp); 736 c |= 0200; 737 } 738 if (c == tp->t_erase) { 739 if (tp->t_rawq.c_cc) 740 ttyrub(unputc(&tp->t_rawq), tp); 741 goto endcase; 742 } 743 if (c == tp->t_kill) { 744 if (tp->t_flags&CRTKIL && 745 tp->t_rawq.c_cc == tp->t_rocount) { 746 while (tp->t_rawq.c_cc) 747 ttyrub(unputc(&tp->t_rawq), tp); 748 } else { 749 ttyecho(c, tp); 750 ttyecho('\n', tp); 751 while (getc(&tp->t_rawq) > 0) 752 ; 753 tp->t_rocount = 0; 754 } 755 tp->t_state &= ~TS_LOCAL; 756 goto endcase; 757 } 758 759 /* 760 * New line discipline, 761 * check word erase/reprint line. 762 */ 763 if (tp->t_line == NTTYDISC) { 764 if (c == tp->t_werasc) { 765 if (tp->t_rawq.c_cc == 0) 766 goto endcase; 767 do { 768 c = unputc(&tp->t_rawq); 769 if (c != ' ' && c != '\t') 770 goto erasenb; 771 ttyrub(c, tp); 772 } while (tp->t_rawq.c_cc); 773 goto endcase; 774 erasenb: 775 do { 776 ttyrub(c, tp); 777 if (tp->t_rawq.c_cc == 0) 778 goto endcase; 779 c = unputc(&tp->t_rawq); 780 } while (c != ' ' && c != '\t'); 781 (void) putc(c, &tp->t_rawq); 782 goto endcase; 783 } 784 if (c == tp->t_rprntc) { 785 ttyretype(tp); 786 goto endcase; 787 } 788 } 789 790 /* 791 * Check for input buffer overflow 792 */ 793 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 794 if (tp->t_line == NTTYDISC) 795 (void) ttyoutput(CTRL(g), tp); 796 goto endcase; 797 } 798 799 /* 800 * Put data char in q for user and 801 * wakeup on seeing a line delimiter. 802 */ 803 if (putc(c, &tp->t_rawq) >= 0) { 804 if (ttbreakc(c, tp)) { 805 tp->t_rocount = 0; 806 catq(&tp->t_rawq, &tp->t_canq); 807 ttwakeup(tp); 808 } else if (tp->t_rocount++ == 0) 809 tp->t_rocol = tp->t_col; 810 tp->t_state &= ~TS_QUOT; 811 if (c == '\\') 812 tp->t_state |= TS_QUOT; 813 if (tp->t_state&TS_ERASE) { 814 tp->t_state &= ~TS_ERASE; 815 (void) ttyoutput('/', tp); 816 } 817 i = tp->t_col; 818 ttyecho(c, tp); 819 if (c == tp->t_eofc && tp->t_flags&ECHO) { 820 i = MIN(2, tp->t_col - i); 821 while (i > 0) { 822 (void) ttyoutput('\b', tp); 823 i--; 824 } 825 } 826 } 827 828 endcase: 829 /* 830 * If DEC-style start/stop is enabled don't restart 831 * output until seeing the start character. 832 */ 833 if (tp->t_flags&DECCTQ && tp->t_state&TS_TTSTOP && 834 tp->t_startc != tp->t_stopc) 835 return; 836 837 restartoutput: 838 tp->t_state &= ~TS_TTSTOP; 839 tp->t_flags &= ~FLUSHO; 840 841 startoutput: 842 ttstart(tp); 843 } 844 845 /* 846 * Put character on TTY output queue, adding delays, 847 * expanding tabs, and handling the CR/NL bit. 848 * This is called both from the top half for output, 849 * and from interrupt level for echoing. 850 * The arguments are the character and the tty structure. 851 * Returns < 0 if putc succeeds, otherwise returns char to resend 852 * Must be recursive. 853 */ 854 ttyoutput(c, tp) 855 register c; 856 register struct tty *tp; 857 { 858 register char *colp; 859 register ctype; 860 861 if (tp->t_flags & (RAW|LITOUT)) { 862 if (tp->t_flags&FLUSHO) 863 return (-1); 864 if (putc(c, &tp->t_outq)) 865 return (c); 866 tk_nout++; 867 return (-1); 868 } 869 870 /* 871 * Ignore EOT in normal mode to avoid 872 * hanging up certain terminals. 873 */ 874 c &= 0177; 875 if (c == CEOT && (tp->t_flags&CBREAK) == 0) 876 return (-1); 877 /* 878 * Turn tabs to spaces as required 879 */ 880 if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) { 881 register int s; 882 883 c = 8 - (tp->t_col&7); 884 if ((tp->t_flags&FLUSHO) == 0) { 885 s = spl5(); /* don't interrupt tabs */ 886 c -= b_to_q(" ", c, &tp->t_outq); 887 tk_nout += c; 888 splx(s); 889 } 890 tp->t_col += c; 891 return (c ? -1 : '\t'); 892 } 893 tk_nout++; 894 /* 895 * for upper-case-only terminals, 896 * generate escapes. 897 */ 898 if (tp->t_flags&LCASE) { 899 colp = "({)}!|^~'`"; 900 while (*colp++) 901 if (c == *colp++) { 902 if (ttyoutput('\\', tp) >= 0) 903 return (c); 904 c = colp[-2]; 905 break; 906 } 907 if ('A' <= c && c <= 'Z') { 908 if (ttyoutput('\\', tp) >= 0) 909 return (c); 910 } else if ('a' <= c && c <= 'z') 911 c += 'A' - 'a'; 912 } 913 914 /* 915 * turn <nl> to <cr><lf> if desired. 916 */ 917 if (c == '\n' && tp->t_flags&CRMOD) 918 if (ttyoutput('\r', tp) >= 0) 919 return (c); 920 if (c == '~' && tp->t_flags&TILDE) 921 c = '`'; 922 if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq)) 923 return (c); 924 /* 925 * Calculate delays. 926 * The numbers here represent clock ticks 927 * and are not necessarily optimal for all terminals. 928 * The delays are indicated by characters above 0200. 929 * In raw mode there are no delays and the 930 * transmission path is 8 bits wide. 931 * 932 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS 933 */ 934 colp = &tp->t_col; 935 ctype = partab[c]; 936 c = 0; 937 switch (ctype&077) { 938 939 case ORDINARY: 940 (*colp)++; 941 942 case CONTROL: 943 break; 944 945 case BACKSPACE: 946 if (*colp) 947 (*colp)--; 948 break; 949 950 /* 951 * This macro is close enough to the correct thing; 952 * it should be replaced by real user settable delays 953 * in any event... 954 */ 955 #define mstohz(ms) (((ms) * hz) >> 10) 956 case NEWLINE: 957 ctype = (tp->t_flags >> 8) & 03; 958 if (ctype == 1) { /* tty 37 */ 959 if (*colp > 0) 960 c = max((((unsigned)*colp) >> 4) + 3, 961 (unsigned)6); 962 } else if (ctype == 2) /* vt05 */ 963 c = mstohz(100); 964 *colp = 0; 965 break; 966 967 case TAB: 968 ctype = (tp->t_flags >> 10) & 03; 969 if (ctype == 1) { /* tty 37 */ 970 c = 1 - (*colp | ~07); 971 if (c < 5) 972 c = 0; 973 } 974 *colp |= 07; 975 (*colp)++; 976 break; 977 978 case VTAB: 979 if (tp->t_flags&VTDELAY) /* tty 37 */ 980 c = 0177; 981 break; 982 983 case RETURN: 984 ctype = (tp->t_flags >> 12) & 03; 985 if (ctype == 1) /* tn 300 */ 986 c = mstohz(83); 987 else if (ctype == 2) /* ti 700 */ 988 c = mstohz(166); 989 else if (ctype == 3) { /* concept 100 */ 990 int i; 991 992 if ((i = *colp) >= 0) 993 for (; i < 9; i++) 994 (void) putc(0177, &tp->t_outq); 995 } 996 *colp = 0; 997 } 998 if (c && (tp->t_flags&FLUSHO) == 0) 999 (void) putc(c|0200, &tp->t_outq); 1000 return (-1); 1001 } 1002 #undef mstohz 1003 1004 /* 1005 * Called from device's read routine after it has 1006 * calculated the tty-structure given as argument. 1007 */ 1008 ttread(tp, uio) 1009 register struct tty *tp; 1010 struct uio *uio; 1011 { 1012 register struct clist *qp; 1013 register c, t_flags; 1014 int s, first, error = 0; 1015 1016 if ((tp->t_state&TS_CARR_ON)==0) 1017 return (EIO); 1018 loop: 1019 /* 1020 * Take any pending input first. 1021 */ 1022 s = spl5(); 1023 if (tp->t_flags&PENDIN) 1024 ttypend(tp); 1025 splx(s); 1026 1027 /* 1028 * Hang process if it's in the background. 1029 */ 1030 #define bit(a) (1<<(a-1)) 1031 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 1032 if ((u.u_procp->p_sigignore & bit(SIGTTIN)) || 1033 (u.u_procp->p_sigmask & bit(SIGTTIN)) || 1034 /* 1035 (u.u_procp->p_flag&SDETACH) || 1036 */ 1037 u.u_procp->p_flag&SVFORK) 1038 return (EIO); 1039 gsignal(u.u_procp->p_pgrp, SIGTTIN); 1040 sleep((caddr_t)&lbolt, TTIPRI); 1041 } 1042 t_flags = tp->t_flags; 1043 #undef bit 1044 1045 /* 1046 * In raw mode take characters directly from the 1047 * raw queue w/o processing. Interlock against 1048 * device interrupts when interrogating rawq. 1049 */ 1050 if (t_flags&RAW) { 1051 s = spl5(); 1052 if (tp->t_rawq.c_cc <= 0) { 1053 if ((tp->t_state&TS_CARR_ON) == 0 || 1054 (tp->t_state&TS_NBIO)) { 1055 splx(s); 1056 return (EWOULDBLOCK); 1057 } 1058 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1059 splx(s); 1060 goto loop; 1061 } 1062 splx(s); 1063 while (!error && tp->t_rawq.c_cc && uio->uio_resid) 1064 error = ureadc(getc(&tp->t_rawq), uio); 1065 goto checktandem; 1066 } 1067 1068 /* 1069 * In cbreak mode use the rawq, otherwise 1070 * take characters from the canonicalized q. 1071 */ 1072 qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq; 1073 1074 /* 1075 * No input, sleep on rawq awaiting hardware 1076 * receipt and notification. 1077 */ 1078 s = spl5(); 1079 if (qp->c_cc <= 0) { 1080 if ((tp->t_state&TS_CARR_ON) == 0 || 1081 (tp->t_state&TS_NBIO)) { 1082 splx(s); 1083 return (EWOULDBLOCK); 1084 } 1085 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1086 splx(s); 1087 goto loop; 1088 } 1089 splx(s); 1090 1091 /* 1092 * Input present, perform input mapping 1093 * and processing (we're not in raw mode). 1094 */ 1095 first = 1; 1096 while ((c = getc(qp)) >= 0) { 1097 if (t_flags&CRMOD && c == '\r') 1098 c = '\n'; 1099 /* 1100 * Hack lower case simulation on 1101 * upper case only terminals. 1102 */ 1103 if (t_flags&LCASE && c <= 0177) 1104 if (tp->t_state&TS_BKSL) { 1105 if (maptab[c]) 1106 c = maptab[c]; 1107 tp->t_state &= ~TS_BKSL; 1108 } else if (c >= 'A' && c <= 'Z') 1109 c += 'a' - 'A'; 1110 else if (c == '\\') { 1111 tp->t_state |= TS_BKSL; 1112 continue; 1113 } 1114 /* 1115 * Check for delayed suspend character. 1116 */ 1117 if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) { 1118 gsignal(tp->t_pgrp, SIGTSTP); 1119 if (first) { 1120 sleep((caddr_t)&lbolt, TTIPRI); 1121 goto loop; 1122 } 1123 break; 1124 } 1125 /* 1126 * Interpret EOF only in cooked mode. 1127 */ 1128 if (c == tp->t_eofc && (t_flags&CBREAK) == 0) 1129 break; 1130 /* 1131 * Give user character. 1132 */ 1133 error = ureadc(c & 0177, uio); 1134 if (error) 1135 break; 1136 if (uio->uio_resid == 0) 1137 break; 1138 /* 1139 * In cooked mode check for a "break character" 1140 * marking the end of a "line of input". 1141 */ 1142 if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp)) 1143 break; 1144 first = 0; 1145 } 1146 tp->t_state &= ~TS_BKSL; 1147 1148 checktandem: 1149 /* 1150 * Look to unblock output now that (presumably) 1151 * the input queue has gone down. 1152 */ 1153 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) 1154 if (putc(tp->t_startc, &tp->t_outq) == 0) { 1155 tp->t_state &= ~TS_TBLOCK; 1156 ttstart(tp); 1157 } 1158 return (error); 1159 } 1160 1161 /* 1162 * Called from the device's write routine after it has 1163 * calculated the tty-structure given as argument. 1164 */ 1165 ttwrite(tp, uio) 1166 register struct tty *tp; 1167 register struct uio *uio; 1168 { 1169 register char *cp; 1170 register int cc, ce, c; 1171 int i, hiwat, cnt, error, s; 1172 char obuf[OBUFSIZ]; 1173 1174 if ((tp->t_state&TS_CARR_ON) == 0) 1175 return (EIO); 1176 hiwat = TTHIWAT(tp); 1177 cnt = uio->uio_resid; 1178 error = 0; 1179 loop: 1180 /* 1181 * Hang the process if it's in the background. 1182 */ 1183 #define bit(a) (1<<(a-1)) 1184 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 1185 (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 1186 !(u.u_procp->p_sigignore & bit(SIGTTOU)) && 1187 !(u.u_procp->p_sigmask & bit(SIGTTOU)) 1188 /* 1189 && 1190 (u.u_procp->p_flag&SDETACH)==0) { 1191 */ 1192 ) { 1193 gsignal(u.u_procp->p_pgrp, SIGTTOU); 1194 sleep((caddr_t)&lbolt, TTIPRI); 1195 } 1196 #undef bit 1197 1198 /* 1199 * Process the user's data in at most OBUFSIZ 1200 * chunks. Perform lower case simulation and 1201 * similar hacks. Keep track of high water 1202 * mark, sleep on overflow awaiting device aid 1203 * in acquiring new space. 1204 */ 1205 while (uio->uio_resid > 0) { 1206 /* 1207 * Grab a hunk of data from the user. 1208 */ 1209 cc = uio->uio_iov->iov_len; 1210 if (cc == 0) { 1211 uio->uio_iovcnt--; 1212 uio->uio_iov++; 1213 if (uio->uio_iovcnt < 0) 1214 panic("ttwrite"); 1215 continue; 1216 } 1217 if (cc > OBUFSIZ) 1218 cc = OBUFSIZ; 1219 cp = obuf; 1220 error = uiomove(cp, cc, UIO_WRITE, uio); 1221 if (error) 1222 break; 1223 if (tp->t_outq.c_cc > hiwat) 1224 goto ovhiwat; 1225 if (tp->t_flags&FLUSHO) 1226 continue; 1227 /* 1228 * If we're mapping lower case or kludging tildes, 1229 * then we've got to look at each character, so 1230 * just feed the stuff to ttyoutput... 1231 */ 1232 if (tp->t_flags & (LCASE|TILDE)) { 1233 while (cc > 0) { 1234 c = *cp++; 1235 tp->t_rocount = 0; 1236 while ((c = ttyoutput(c, tp)) >= 0) { 1237 /* out of clists, wait a bit */ 1238 ttstart(tp); 1239 sleep((caddr_t)&lbolt, TTOPRI); 1240 tp->t_rocount = 0; 1241 } 1242 --cc; 1243 if (tp->t_outq.c_cc > hiwat) 1244 goto ovhiwat; 1245 } 1246 continue; 1247 } 1248 /* 1249 * If nothing fancy need be done, grab those characters we 1250 * can handle without any of ttyoutput's processing and 1251 * just transfer them to the output q. For those chars 1252 * which require special processing (as indicated by the 1253 * bits in partab), call ttyoutput. After processing 1254 * a hunk of data, look for FLUSHO so ^O's will take effect 1255 * immediately. 1256 */ 1257 while (cc > 0) { 1258 if (tp->t_flags & (RAW|LITOUT)) 1259 ce = cc; 1260 else { 1261 ce = cc - scanc((unsigned)cc, (caddr_t)cp, 1262 (caddr_t)partab, 077); 1263 /* 1264 * If ce is zero, then we're processing 1265 * a special character through ttyoutput. 1266 */ 1267 if (ce == 0) { 1268 tp->t_rocount = 0; 1269 if (ttyoutput(*cp, tp) >= 0) { 1270 /* no c-lists, wait a bit */ 1271 ttstart(tp); 1272 sleep((caddr_t)&lbolt, TTOPRI); 1273 continue; 1274 } 1275 cp++, cc--; 1276 if (tp->t_flags&FLUSHO || 1277 tp->t_outq.c_cc > hiwat) 1278 goto ovhiwat; 1279 continue; 1280 } 1281 } 1282 /* 1283 * A bunch of normal characters have been found, 1284 * transfer them en masse to the output queue and 1285 * continue processing at the top of the loop. 1286 * If there are any further characters in this 1287 * <= OBUFSIZ chunk, the first should be a character 1288 * requiring special handling by ttyoutput. 1289 */ 1290 tp->t_rocount = 0; 1291 i = b_to_q(cp, ce, &tp->t_outq); 1292 ce -= i; 1293 tp->t_col += ce; 1294 cp += ce, cc -= ce, tk_nout += ce; 1295 if (i > 0) { 1296 /* out of c-lists, wait a bit */ 1297 ttstart(tp); 1298 sleep((caddr_t)&lbolt, TTOPRI); 1299 } 1300 if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat) 1301 goto ovhiwat; 1302 } 1303 } 1304 ttstart(tp); 1305 return (error); 1306 1307 ovhiwat: 1308 s = spl5(); 1309 if (cc != 0) { 1310 uio->uio_iov->iov_base -= cc; 1311 uio->uio_iov->iov_len += cc; 1312 uio->uio_resid += cc; 1313 uio->uio_offset -= cc; 1314 } 1315 /* 1316 * This can only occur if FLUSHO 1317 * is also set in t_flags. 1318 */ 1319 if (tp->t_outq.c_cc <= hiwat) { 1320 splx(s); 1321 goto loop; 1322 } 1323 ttstart(tp); 1324 if (tp->t_state&TS_NBIO) { 1325 if (uio->uio_resid == cnt) 1326 return (EWOULDBLOCK); 1327 return (0); 1328 } 1329 tp->t_state |= TS_ASLEEP; 1330 sleep((caddr_t)&tp->t_outq, TTOPRI); 1331 splx(s); 1332 goto loop; 1333 } 1334 1335 /* 1336 * Rubout one character from the rawq of tp 1337 * as cleanly as possible. 1338 */ 1339 ttyrub(c, tp) 1340 register c; 1341 register struct tty *tp; 1342 { 1343 register char *cp; 1344 register int savecol; 1345 int s; 1346 char *nextc(); 1347 1348 if ((tp->t_flags&ECHO) == 0) 1349 return; 1350 tp->t_flags &= ~FLUSHO; 1351 c &= 0377; 1352 if (tp->t_flags&CRTBS) { 1353 if (tp->t_rocount == 0) { 1354 /* 1355 * Screwed by ttwrite; retype 1356 */ 1357 ttyretype(tp); 1358 return; 1359 } 1360 if (c == ('\t'|0200) || c == ('\n'|0200)) 1361 ttyrubo(tp, 2); 1362 else switch (partab[c&=0177]&0177) { 1363 1364 case ORDINARY: 1365 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z') 1366 ttyrubo(tp, 2); 1367 else 1368 ttyrubo(tp, 1); 1369 break; 1370 1371 case VTAB: 1372 case BACKSPACE: 1373 case CONTROL: 1374 case RETURN: 1375 if (tp->t_flags&CTLECH) 1376 ttyrubo(tp, 2); 1377 break; 1378 1379 case TAB: 1380 if (tp->t_rocount < tp->t_rawq.c_cc) { 1381 ttyretype(tp); 1382 return; 1383 } 1384 s = spl5(); 1385 savecol = tp->t_col; 1386 tp->t_state |= TS_CNTTB; 1387 tp->t_flags |= FLUSHO; 1388 tp->t_col = tp->t_rocol; 1389 cp = tp->t_rawq.c_cf; 1390 for (; cp; cp = nextc(&tp->t_rawq, cp)) 1391 ttyecho(*cp, tp); 1392 tp->t_flags &= ~FLUSHO; 1393 tp->t_state &= ~TS_CNTTB; 1394 splx(s); 1395 /* 1396 * savecol will now be length of the tab 1397 */ 1398 savecol -= tp->t_col; 1399 tp->t_col += savecol; 1400 if (savecol > 8) 1401 savecol = 8; /* overflow screw */ 1402 while (--savecol >= 0) 1403 (void) ttyoutput('\b', tp); 1404 break; 1405 1406 default: 1407 panic("ttyrub"); 1408 } 1409 } else if (tp->t_flags&PRTERA) { 1410 if ((tp->t_state&TS_ERASE) == 0) { 1411 (void) ttyoutput('\\', tp); 1412 tp->t_state |= TS_ERASE; 1413 } 1414 ttyecho(c, tp); 1415 } else 1416 ttyecho(tp->t_erase, tp); 1417 tp->t_rocount--; 1418 } 1419 1420 /* 1421 * Crt back over cnt chars perhaps 1422 * erasing them. 1423 */ 1424 ttyrubo(tp, cnt) 1425 register struct tty *tp; 1426 int cnt; 1427 { 1428 register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b"; 1429 1430 while (--cnt >= 0) 1431 ttyout(rubostring, tp); 1432 } 1433 1434 /* 1435 * Reprint the rawq line. 1436 * We assume c_cc has already been checked. 1437 */ 1438 ttyretype(tp) 1439 register struct tty *tp; 1440 { 1441 register char *cp; 1442 char *nextc(); 1443 int s; 1444 1445 if (tp->t_rprntc != 0377) 1446 ttyecho(tp->t_rprntc, tp); 1447 (void) ttyoutput('\n', tp); 1448 s = spl5(); 1449 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp)) 1450 ttyecho(*cp, tp); 1451 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 1452 ttyecho(*cp, tp); 1453 tp->t_state &= ~TS_ERASE; 1454 splx(s); 1455 tp->t_rocount = tp->t_rawq.c_cc; 1456 tp->t_rocol = 0; 1457 } 1458 1459 /* 1460 * Echo a typed character to the terminal 1461 */ 1462 ttyecho(c, tp) 1463 register c; 1464 register struct tty *tp; 1465 { 1466 1467 if ((tp->t_state&TS_CNTTB) == 0) 1468 tp->t_flags &= ~FLUSHO; 1469 if ((tp->t_flags&ECHO) == 0) 1470 return; 1471 c &= 0377; 1472 if (tp->t_flags&RAW) { 1473 (void) ttyoutput(c, tp); 1474 return; 1475 } 1476 if (c == '\r' && tp->t_flags&CRMOD) 1477 c = '\n'; 1478 if (tp->t_flags&CTLECH) { 1479 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) { 1480 (void) ttyoutput('^', tp); 1481 c &= 0177; 1482 if (c == 0177) 1483 c = '?'; 1484 else if (tp->t_flags&LCASE) 1485 c += 'a' - 1; 1486 else 1487 c += 'A' - 1; 1488 } 1489 } 1490 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z')) 1491 c += 'a' - 'A'; 1492 (void) ttyoutput(c&0177, tp); 1493 } 1494 1495 /* 1496 * Is c a break char for tp? 1497 */ 1498 ttbreakc(c, tp) 1499 register c; 1500 register struct tty *tp; 1501 { 1502 return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc || 1503 c == '\r' && (tp->t_flags&CRMOD)); 1504 } 1505 1506 /* 1507 * send string cp to tp 1508 */ 1509 ttyout(cp, tp) 1510 register char *cp; 1511 register struct tty *tp; 1512 { 1513 register char c; 1514 1515 while (c = *cp++) 1516 (void) ttyoutput(c, tp); 1517 } 1518 1519 ttwakeup(tp) 1520 struct tty *tp; 1521 { 1522 1523 if (tp->t_rsel) { 1524 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 1525 tp->t_state &= ~TS_RCOLL; 1526 tp->t_rsel = 0; 1527 } 1528 if (tp->t_state & TS_ASYNC) 1529 gsignal(tp->t_pgrp, SIGIO); 1530 wakeup((caddr_t)&tp->t_rawq); 1531 } 1532 1533 #if !defined(vax) 1534 scanc(size, cp, table, mask) 1535 register int size; 1536 register char *cp, table[]; 1537 register int mask; 1538 { 1539 register int i = 0; 1540 1541 while ((table[*(u_char *)(cp + i)]&mask) == 0 && i < size) 1542 i++; 1543 return (size - i); 1544 } 1545 #endif 1546