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

Defined functions

nullmodem defined in line 662; used 3 times
ttbreakc defined in line 1630; used 2 times
ttnread defined in line 513; used 2 times
ttread defined in line 1120; used 3 times
ttselect defined in line 526; used 8 times
ttwakeup defined in line 1651; used 5 times
ttwrite defined in line 1286; used 4 times
ttyblock defined in line 177; used 1 times
ttycheckoutq defined in line 1260; used 2 times
ttyecho defined in line 1596; used 14 times
ttyflush defined in line 146; used 13 times
ttyinput defined in line 701; used 6 times
ttylclose defined in line 595; used 3 times
ttymodem defined in line 620; used 3 times
ttyopen defined in line 567; used 3 times
ttyout defined in line 1641; used 6 times
ttyoutput defined in line 964; used 18 times
ttypend defined in line 678; used 3 times
ttyretype defined in line 1572; used 4 times
ttyrub defined in line 1473; used 6 times
ttyrubo defined in line 1558; used 4 times
ttywait defined in line 129; used 2 times
ttywflush defined in line 121; used 4 times

Defined variables

maptab defined in line 82; used 2 times
partab defined in line 33; used 3 times
tthiwat defined in line 101; never used
ttlowat defined in line 103; never used
ttydefaults defined in line 106; used 2 times

Defined macros

mstohz defined in line 1065; used 4 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3557
Valid CSS Valid XHTML 1.0 Strict