1: /*
   2:  *	SCCS id	@(#)tty.c	2.1 (Berkeley)	8/5/83
   3:  */
   4: 
   5: /*
   6:  * TTY subroutines common to more than one line discipline
   7:  */
   8: 
   9: #include "param.h"
  10: #include <sys/systm.h>
  11: #include <sys/dir.h>
  12: #include <sys/user.h>
  13: #include <sys/tty.h>
  14: #include <sys/proc.h>
  15: #ifdef  MPX_FILS
  16: #include <sys/mx.h>
  17: #endif
  18: #include <sys/inode.h>
  19: #include <sys/file.h>
  20: #include <sys/reg.h>
  21: #include <sys/conf.h>
  22: #include <sys/buf.h>
  23: #include "bk.h"
  24: 
  25: extern  char    partab[];
  26: 
  27: /*
  28:  * Input mapping table-- if an entry is non-zero, when the
  29:  * corresponding character is typed preceded by "\" the escape
  30:  * sequence is replaced by the table value.  Only used for
  31:  * upper-case only terminals.
  32:  */
  33: 
  34: char    maptab[] ={
  35:     000,000,000,000,000,000,000,000,
  36:     000,000,000,000,000,000,000,000,
  37:     000,000,000,000,000,000,000,000,
  38:     000,000,000,000,000,000,000,000,
  39:     000,'|',000,000,000,000,000,'`',
  40:     '{','}',000,000,000,000,000,000,
  41:     000,000,000,000,000,000,000,000,
  42:     000,000,000,000,000,000,000,000,
  43:     000,000,000,000,000,000,000,000,
  44:     000,000,000,000,000,000,000,000,
  45:     000,000,000,000,000,000,000,000,
  46:     000,000,000,000,000,000,'~',000,
  47:     000,'A','B','C','D','E','F','G',
  48:     'H','I','J','K','L','M','N','O',
  49:     'P','Q','R','S','T','U','V','W',
  50:     'X','Y','Z',000,000,000,000,000,
  51: };
  52: 
  53: short   tthiwat[16] =
  54:    { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 };
  55: short   ttlowat[16] =
  56:    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
  57: 
  58: #define OBUFSIZ 100
  59: 
  60: /*
  61:  * routine called on teletype open.
  62:  * establishes a process group for distribution
  63:  * of quits and interrupts from the tty.
  64:  * Then calls open routine for default line discipline.
  65:  */
  66: ttyopen(dev, tp)
  67: dev_t dev;
  68: register struct tty *tp;
  69: {
  70:     register struct proc *pp;
  71: 
  72:     pp = u.u_procp;
  73:     tp->t_dev = dev;
  74:     if(pp->p_pgrp == 0) {
  75:         u.u_ttyp = tp;
  76:         u.u_ttyd = dev;
  77:         if (tp->t_pgrp == 0)
  78:             tp->t_pgrp = pp->p_pid;
  79:         pp->p_pgrp = tp->t_pgrp;
  80:     }
  81:     tp->t_state &= ~WOPEN;
  82:     tp->t_state |= ISOPEN;
  83:     (*linesw[tp->t_line].l_open)(tp);
  84: }
  85: 
  86: /*
  87:  * clean tp on last close
  88:  */
  89: ttyclose(tp)
  90: register struct tty *tp;
  91: {
  92:     (*linesw[tp->t_line].l_close)(tp);
  93:     tp->t_pgrp = 0;
  94:     wflushtty(tp);
  95:     tp->t_state = 0;
  96: }
  97: /*
  98:  * set default control characters.
  99:  */
 100: ttychars(tp)
 101: register struct tty *tp;
 102: {
 103: 
 104:     tun.t_intrc = CINTR;
 105:     tun.t_quitc = CQUIT;
 106:     tun.t_startc = CSTART;
 107:     tun.t_stopc = CSTOP;
 108:     tun.t_eofc = CEOT;
 109:     tun.t_brkc = CBRK;
 110:     tp->t_erase = CERASE;
 111:     tp->t_kill = CKILL;
 112: #ifdef  UCB_NTTY
 113:     tlun.t_suspc = CTRL(z);
 114:     tlun.t_dsuspc = CTRL(y);
 115:     tlun.t_rprntc = CTRL(r);
 116:     tlun.t_flushc = CTRL(o);
 117:     tlun.t_werasc = CTRL(w);
 118:     tlun.t_lnextc = CTRL(v);
 119:     tp->t_local = 0;
 120:     tp->t_lstate = 0;
 121: #endif
 122: }
 123: 
 124: /*
 125:  * Wait for output to drain, then flush input waiting.
 126:  */
 127: wflushtty(tp)
 128: register struct tty *tp;
 129: {
 130: 
 131:     (void) _spl5();
 132:     while (tp->t_outq.c_cc && tp->t_state&CARR_ON) {
 133:         (*tp->t_oproc)(tp);
 134:         tp->t_state |= ASLEEP;
 135:         sleep((caddr_t)&tp->t_outq, TTOPRI);
 136:     }
 137:     flushtty(tp, FREAD|FWRITE);
 138:     (void) _spl0();
 139: }
 140: 
 141: /*
 142:  * flush all TTY queues
 143:  */
 144: flushtty(tp, rw)
 145: register struct tty *tp;
 146: register rw;
 147: {
 148:     register s;
 149: 
 150: #if NBK > 0
 151:     if (tp->t_line == NETLDISC)
 152:         return;
 153: #endif
 154:     s = spl6();
 155:     if (rw & FREAD) {
 156:         while (getc(&tp->t_canq) >= 0)
 157:             ;
 158:         wakeup((caddr_t)&tp->t_rawq);
 159:     }
 160:     if (rw & FWRITE) {
 161:         tp->t_state &= ~TTSTOP;
 162:         (*cdevsw[major(tp->t_dev)].d_stop)(tp);
 163:         while (getc(&tp->t_outq) >= 0)
 164:             ;
 165:         wakeup((caddr_t)&tp->t_outq);
 166:     }
 167:     if (rw & FREAD) {
 168:         while (getc(&tp->t_rawq) >= 0)
 169:             ;
 170:         tp->t_delct = 0;
 171: #ifdef  UCB_NTTY
 172:         tp->t_rocount = 0;
 173:         tp->t_rocol = 0;
 174:         tp->t_lstate = 0;
 175: #endif
 176:     }
 177:     splx(s);
 178: }
 179: 
 180: /*
 181:  * Send stop character on input overflow.
 182:  */
 183: ttyblock(tp)
 184: register struct tty *tp;
 185: {
 186:     register x;
 187:     x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
 188:     if (tp->t_rawq.c_cc > TTYHOG) {
 189:         flushtty(tp, FREAD|FWRITE);
 190:         tp->t_state &= ~TBLOCK;
 191:     }
 192:     /*
 193: 	 * Block further input iff:
 194: 	 * Current input > threshold AND input is available to user program
 195: 	 */
 196:     if (x >= TTYHOG/2 && (tp->t_delct>0 || (tp->t_flags&(RAW|CBREAK)))) {
 197:         if (putc(tun.t_stopc, &tp->t_outq)==0) {
 198:             tp->t_state |= TBLOCK;
 199:             ttstart(tp);
 200:         }
 201:     }
 202: }
 203: 
 204: /*
 205:  * Restart typewriter output following a delay
 206:  * timeout.
 207:  * The name of the routine is passed to the timeout
 208:  * subroutine and it is called during a clock interrupt.
 209:  */
 210: ttrstrt(tp)
 211: register struct tty *tp;
 212: {
 213: 
 214: #ifdef  DIAGNOSTIC
 215:     if (tp == 0) {
 216:         printf("ttrstrt: arg was 0!\n");
 217:         return;
 218:     }
 219: #endif
 220:     tp->t_state &= ~TIMEOUT;
 221:     ttstart(tp);
 222: }
 223: 
 224: /*
 225:  * Start output on the typewriter. It is used from the top half
 226:  * after some characters have been put on the output queue,
 227:  * from the interrupt routine to transmit the next
 228:  * character, and after a timeout has finished.
 229:  */
 230: ttstart(tp)
 231: register struct tty *tp;
 232: {
 233:     register s;
 234: 
 235:     s = spl5();
 236:     if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0)
 237:         (*tp->t_oproc)(tp);
 238:     splx(s);
 239: }
 240: 
 241: /*
 242:  * Common code for tty ioctls.
 243:  * Return values:
 244:  *	cmd			cmd is not done (driver must do some/all)
 245:  *	0			cmd is done
 246:  *	0 (u.u_error set)	cmd was rejected by line disc. code
 247:  */
 248: /*ARGSUSED*/
 249: ttioctl(tp, com, addr, flag)
 250: register struct tty *tp;
 251: caddr_t addr;
 252: {
 253:     register dev_t dev;
 254:     unsigned t;
 255:     struct sgttyb iocb;
 256:     struct clist tq;
 257:     extern int nldisp;
 258:     register c;
 259:     int temp;
 260:     extern nodev();
 261: 
 262:     /*
 263: 	 *  First, give the line discipline a chance.
 264: 	 *  If it returns 0, either the work is done
 265: 	 *  or the request was refused.
 266: 	 *  Return 0 to keep the device driver from continuing.
 267: 	 */
 268:     if ((com = (*linesw[tp->t_line].l_ioctl)(tp,com,addr,flag)) == 0)
 269:         return(0);
 270:     /*
 271: 	 * This is especially so that isatty() will
 272: 	 * fail when carrier is gone.
 273: 	 */
 274:     if ((tp->t_state&CARR_ON) == 0) {
 275:         u.u_error = EBADF;
 276:         return (0);
 277:     }
 278: 
 279:     dev = tp->t_dev;
 280:     /*
 281: 	 * If the ioctl involves modification,
 282: 	 * hang if in the background.
 283: 	 */
 284: #ifdef  MENLO_JCL
 285:     switch(com) {
 286: 
 287:     case TIOCSETD:
 288:     case TIOCSETP:
 289:     case TIOCSETN:
 290:     case TIOCFLUSH:
 291:     case TIOCSETC:
 292:     case TIOCSLTC:
 293:     case TIOCSPGRP:
 294:     case TIOCLBIS:
 295:     case TIOCLBIC:
 296:     case TIOCLSET:
 297:     case TIOCSTI:
 298:         while (tp->t_line == NTTYDISC &&
 299:            u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
 300: #ifdef  VIRUS_VFORK
 301:            (u.u_procp->p_flag&SVFORK) == 0 &&
 302: #endif
 303:            u.u_signal[SIGTTOU] != SIG_IGN &&
 304:            u.u_signal[SIGTTOU] != SIG_HOLD &&
 305:            (u.u_procp->p_flag&SDETACH)==0) {
 306:             gsignal(u.u_procp->p_pgrp, SIGTTOU);
 307:             sleep((caddr_t)&lbolt, TTOPRI);
 308:         }
 309:         break;
 310:     }
 311: #endif
 312: 
 313:     /*
 314: 	 * Process the ioctl.
 315: 	 */
 316:     switch(com) {
 317: 
 318:     /*
 319: 	 * Get discipline number
 320: 	 */
 321:     case TIOCGETD:
 322:         t = tp->t_line;
 323:         if (copyout((caddr_t)&t, addr, sizeof(t)))
 324:             u.u_error = EFAULT;
 325:         break;
 326: 
 327:     /*
 328: 	 * Set line discipline
 329: 	 */
 330:     case TIOCSETD:
 331:         if (copyin(addr, (caddr_t)&t, sizeof(t))) {
 332:             u.u_error = EFAULT;
 333:             break;
 334:         }
 335:         if ((t >= nldisp) || (linesw[t].l_open == nodev)) {
 336:             u.u_error = ENXIO;
 337:             break;
 338:         }
 339:         if (t != tp->t_line) {
 340:             (void) _spl5();
 341:             (*linesw[tp->t_line].l_close)(tp);
 342:             (*linesw[t].l_open)(tp);
 343:             if (u.u_error==0)
 344:                 tp->t_line = t;
 345:             (void) _spl0();
 346:         }
 347:         break;
 348: 
 349:     /*
 350: 	 * Prevent more opens on channel
 351: 	 */
 352:     case TIOCEXCL:
 353:         tp->t_state |= XCLUDE;
 354:         break;
 355: 
 356:     case TIOCNXCL:
 357:         tp->t_state &= ~XCLUDE;
 358:         break;
 359: 
 360:     /*
 361: 	 * Set new parameters
 362: 	 */
 363:     case TIOCSETP:
 364:     case TIOCSETN:
 365:         if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
 366:             u.u_error = EFAULT;
 367:             return(0);
 368:         }
 369:         (void) _spl5();
 370: #ifdef  OLDTTY
 371:         if (tp->t_line == OTTYDISC) {
 372:             if (com == TIOCSETP)
 373:                 wflushtty(tp);
 374:             while (canon(tp)>=0)
 375:                 ;
 376:         }
 377: #endif	OLDTTY
 378: #ifdef  UCB_NTTY
 379:         if (tp->t_line == NTTYDISC) {
 380:             if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
 381:                 com == TIOCSETP)
 382:                 wflushtty(tp);
 383:             else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
 384:                 if (iocb.sg_flags & CBREAK) {
 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_local |= LPENDIN;
 391: #ifdef  DIAGNOSTIC
 392:                     if (tp->t_canq.c_cc)
 393:                         panic("ttioctl canq");
 394: #endif
 395: #ifdef MPX_FILS
 396:                     if (tp->t_chan)
 397:                         (void) sdata(tp->t_chan);
 398:                     else
 399: #endif
 400:                         wakeup((caddr_t)&tp->t_rawq);
 401:                 }
 402:             }
 403: #endif
 404:         }
 405:         if ((tp->t_state&SPEEDS)==0) {
 406:             tp->t_ispeed = iocb.sg_ispeed;
 407:             tp->t_ospeed = iocb.sg_ospeed;
 408:         }
 409:         tp->t_erase = iocb.sg_erase;
 410:         tp->t_kill = iocb.sg_kill;
 411:         tp->t_flags = iocb.sg_flags;
 412:         (void) _spl0();
 413:         return(com);
 414: 
 415:     /*
 416: 	 * Send current parameters to user
 417: 	 */
 418:     case TIOCGETP:
 419:         iocb.sg_ispeed = tp->t_ispeed;
 420:         iocb.sg_ospeed = tp->t_ospeed;
 421:         iocb.sg_erase = tp->t_erase;
 422:         iocb.sg_kill = tp->t_kill;
 423:         iocb.sg_flags = tp->t_flags;
 424:         if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
 425:             u.u_error = EFAULT;
 426:         break;
 427: 
 428:     /*
 429: 	 * Hang up line on last close
 430: 	 */
 431:     case TIOCHPCL:
 432:         tp->t_state |= HUPCLS;
 433:         break;
 434: 
 435:     case TIOCFLUSH: {
 436:         int flags;
 437:         if (copyin(addr, (caddr_t) &flags, sizeof (flags))) {
 438:             u.u_error = EFAULT;
 439:             return (1);
 440:         }
 441:         if (flags == 0)
 442:             flags = FREAD | FWRITE;
 443:         else
 444:             flags &= FREAD | FWRITE;
 445:         flushtty(tp, flags);
 446:         break;
 447:     }
 448: 
 449: #ifdef  UCB_NET
 450:     case FIONBIO: {
 451:         int nbio;
 452:         if (copyin(addr, (caddr_t)&nbio, sizeof (nbio))) {
 453:             u.u_error = EFAULT;
 454:             return(1);
 455:         }
 456:         if (nbio)
 457:             tp->t_state |= TS_NBIO;
 458:         else
 459:             tp->t_state &= ~TS_NBIO;
 460:         break;
 461:     }
 462: 
 463:     case FIOASYNC: {
 464:         int async;
 465:         if (copyin(addr, (caddr_t)&async, sizeof (async))) {
 466:             u.u_error = EFAULT;
 467:             return(1);
 468:         }
 469:         if (async)
 470:             tp->t_state |= TS_ASYNC;
 471:         else
 472:             tp->t_state &= ~TS_ASYNC;
 473:         break;
 474:     }
 475: #endif
 476: 
 477:     /*
 478: 	 * Set and fetch special characters
 479: 	 */
 480:     case TIOCSETC:
 481:         if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars)))
 482:             u.u_error = EFAULT;
 483:         break;
 484: 
 485:     case TIOCGETC:
 486:         if (copyout((caddr_t)&tun, addr, sizeof(struct tchars)))
 487:             u.u_error = EFAULT;
 488:         break;
 489: 
 490: #ifdef  UCB_NTTY
 491:     /*
 492: 	 * Set/get local special characters.
 493: 	 */
 494:     case TIOCSLTC:
 495:         if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars)))
 496:             u.u_error = EFAULT;
 497:         break;
 498: 
 499:     case TIOCGLTC:
 500:         if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars)))
 501:             u.u_error = EFAULT;
 502:         break;
 503: 
 504:     /*
 505: 	 * Return number of characters immediately available.
 506: 	 */
 507:     case FIONREAD: {
 508:         off_t nread;
 509: 
 510:         switch (tp->t_line) {
 511: 
 512: #if NBK > 0
 513:         case NETLDISC:
 514:             nread = tp->t_rec ? tp->t_inbuf : 0;
 515:             break;
 516: #endif
 517: 
 518: #ifdef  OLDTTY
 519:         case OTTYDISC:
 520:             (void) _spl5();
 521:             while (canon(tp)>=0)
 522:                 ;
 523:             (void) _spl0();
 524:             /* fall into ... */
 525: #endif
 526: 
 527:         case NTTYDISC:
 528: #ifdef  UCB_NET
 529:             nread = ttnread(tp);
 530: #else
 531:             nread = tp->t_canq.c_cc;
 532:             if (tp->t_flags & (RAW|CBREAK))
 533:                 nread += tp->t_rawq.c_cc;
 534: #endif
 535:             break;
 536: 
 537:         }
 538:         if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
 539:             u.u_error = EFAULT;
 540:         break;
 541:         }
 542: 
 543:     /*
 544: 	 * Should allow SPGRP and GPGRP only if tty open for reading.
 545: 	 */
 546:     case TIOCSPGRP:
 547:         if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp)))
 548:             u.u_error = EFAULT;
 549:         break;
 550: 
 551:     case TIOCGPGRP:
 552:         if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp)))
 553:             u.u_error = EFAULT;
 554:         break;
 555: 
 556:     /*
 557: 	 * Modify local mode word.
 558: 	 */
 559:     case TIOCLBIS:
 560:         if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
 561:             u.u_error = EFAULT;
 562:         else
 563:             tp->t_local |= temp;
 564:         break;
 565: 
 566:     case TIOCLBIC:
 567:         if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
 568:             u.u_error = EFAULT;
 569:         else
 570:             tp->t_local &= ~temp;
 571:         break;
 572: 
 573:     case TIOCLSET:
 574:         if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
 575:             u.u_error = EFAULT;
 576:         else
 577:             tp->t_local = temp;
 578:         break;
 579: 
 580:     case TIOCLGET:
 581:         if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local)))
 582:             u.u_error = EFAULT;
 583:         break;
 584: 
 585:     /*
 586: 	 * Return number of characters in
 587: 	 * the output.
 588: 	 */
 589:     case TIOCOUTQ:
 590:         if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc)))
 591:             u.u_error = EFAULT;
 592:         break;
 593: 
 594:     /*
 595: 	 * Simulate typing of a character at the terminal.
 596: 	 */
 597:     case TIOCSTI:
 598:         c = fubyte(addr);
 599:         if (u.u_uid && u.u_ttyp != tp || c < 0)
 600:             u.u_error = EFAULT;
 601:         else
 602:             (*linesw[tp->t_line].l_input)(c, tp);
 603:         break;
 604: #endif
 605: 
 606: #ifdef  TEXAS_AUTOBAUD
 607:     case TIOCSIMG:
 608:         tp->t_xflags |= LIMAGE;
 609:         break;
 610: 
 611:     case TIOCCIMG:
 612:         tp->t_xflags &= ~LIMAGE;
 613:         break;
 614: #endif
 615: 
 616:     default:
 617:         return(com);
 618:     }
 619:     return(0);
 620: }
 621: 
 622: #ifdef  UCB_NET
 623: ttnread(tp)
 624:     struct tty *tp;
 625: {
 626:     int nread = 0;
 627: 
 628:     if (tp->t_local & LPENDIN)
 629:         ttypend(tp);
 630:     nread = tp->t_canq.c_cc;
 631:     if (tp->t_flags & (RAW|CBREAK))
 632:         nread += tp->t_rawq.c_cc;
 633:     return (nread);
 634: }
 635: #endif
 636: 
 637: #ifdef  UCB_NET
 638: ttselect(dev, rw)
 639:     dev_t dev;
 640:     int rw;
 641: {
 642:     register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
 643:     int nread;
 644:     int s = spl5();
 645: 
 646:     switch (rw) {
 647: 
 648:     case FREAD:
 649:         nread = ttnread(tp);
 650:         if (nread > 0)
 651:             goto win;
 652:         if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
 653:             tp->t_state |= TS_RCOLL;
 654:         else
 655:             tp->t_rsel = u.u_procp;
 656:         break;
 657: 
 658:     case FWRITE:
 659:         if (tp->t_outq.c_cc <= TTLOWAT(tp))
 660:             goto win;
 661:         if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
 662:             tp->t_state |= TS_WCOLL;
 663:         else
 664:             tp->t_wsel = u.u_procp;
 665:         break;
 666:     }
 667:     splx(s);
 668:     return (0);
 669: win:
 670:     splx(s);
 671:     return (1);
 672: }
 673: #endif

Defined functions

ttnread defined in line 623; used 2 times
ttselect defined in line 638; never used
ttyblock defined in line 183; used 2 times
wflushtty defined in line 127; used 5 times

Defined variables

maptab defined in line 34; never used
tthiwat defined in line 53; never used
ttlowat defined in line 55; never used

Defined macros

OBUFSIZ defined in line 58; never used
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1486
Valid CSS Valid XHTML 1.0 Strict