1: /*
   2:  * Copyright (c) 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_pty.c	1.3 (2.11BSD GTE) 1997/5/2
   7:  */
   8: 
   9: /*
  10:  * Pseudo-teletype Driver
  11:  * (Actually two drivers, requiring two entries in 'cdevsw')
  12:  */
  13: #include "pty.h"
  14: 
  15: #if NPTY > 0
  16: #include "param.h"
  17: #include "systm.h"
  18: #include "ioctl.h"
  19: #include "tty.h"
  20: #include "user.h"
  21: #include "conf.h"
  22: #include "file.h"
  23: #include "proc.h"
  24: #include "uio.h"
  25: #include "kernel.h"
  26: #include "inode.h"
  27: 
  28: extern  int TTYHOG;     /* see tty.c */
  29: 
  30: #if NPTY == 1
  31: #undef NPTY
  32: #define NPTY    16      /* crude XXX */
  33: #endif
  34: 
  35: #define BUFSIZ 100      /* Chunk size iomoved to/from user */
  36: 
  37: /*
  38:  * pts == /dev/tty[pqrs]?
  39:  * ptc == /dev/pty[pqrs]?
  40:  */
  41: struct  tty pt_tty[NPTY];
  42: struct  pt_ioctl {
  43:     int pt_flags;
  44:     struct  proc *pt_selr, *pt_selw;
  45:     u_char  pt_send;
  46:     u_char  pt_ucntl;
  47: } pt_ioctl[NPTY];
  48: int npty = NPTY;        /* for pstat -t */
  49: 
  50: #define PF_RCOLL    0x01
  51: #define PF_WCOLL    0x02
  52: #define PF_PKT      0x08        /* packet mode */
  53: #define PF_STOPPED  0x10        /* user told stopped */
  54: #define PF_REMOTE   0x20        /* remote and flow controlled input */
  55: #define PF_NOSTOP   0x40
  56: #define PF_UCNTL    0x80        /* user control mode */
  57: 
  58: /*ARGSUSED*/
  59: ptsopen(dev, flag)
  60:     dev_t dev;
  61: {
  62:     register struct tty *tp;
  63:     int error;
  64: 
  65: #ifdef lint
  66:     npty = npty;
  67: #endif
  68:     if (minor(dev) >= NPTY)
  69:         return (ENXIO);
  70:     tp = &pt_tty[minor(dev)];
  71:     if ((tp->t_state & TS_ISOPEN) == 0) {
  72:         ttychars(tp);       /* Set up default chars */
  73:         tp->t_ispeed = tp->t_ospeed = EXTB;
  74:         tp->t_flags = 0;    /* No features (nor raw mode) */
  75:     } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
  76:         return (EBUSY);
  77:     if (tp->t_oproc)            /* Ctrlr still around. */
  78:         tp->t_state |= TS_CARR_ON;
  79:     while ((tp->t_state & TS_CARR_ON) == 0) {
  80:         tp->t_state |= TS_WOPEN;
  81:         sleep((caddr_t)&tp->t_rawq, TTIPRI);
  82:     }
  83:     error = (*linesw[tp->t_line].l_open)(dev, tp);
  84:     ptcwakeup(tp, FREAD|FWRITE);
  85:     return (error);
  86: }
  87: 
  88: ptsclose(dev, flag)
  89:     dev_t dev;
  90:     int flag;
  91: {
  92:     register struct tty *tp;
  93: 
  94:     tp = &pt_tty[minor(dev)];
  95:     (*linesw[tp->t_line].l_close)(tp, flag);
  96:     ttyclose(tp);
  97:     ptcwakeup(tp, FREAD|FWRITE);
  98: }
  99: 
 100: ptsread(dev, uio, flag)
 101:     dev_t dev;
 102:     register struct uio *uio;
 103:     int flag;
 104: {
 105:     register struct tty *tp = &pt_tty[minor(dev)];
 106:     register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
 107:     int error = 0;
 108: 
 109: again:
 110:     if (pti->pt_flags & PF_REMOTE) {
 111:         while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
 112:             if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) ||
 113:                 (u.u_procp->p_sigmask & sigmask(SIGTTIN)) ||
 114:                 u.u_procp->p_flag&SVFORK)
 115:                 return (EIO);
 116:             gsignal(u.u_procp->p_pgrp, SIGTTIN);
 117:             sleep((caddr_t)&lbolt, TTIPRI);
 118:         }
 119:         if (tp->t_canq.c_cc == 0) {
 120:             if (flag & IO_NDELAY)
 121:                 return (EWOULDBLOCK);
 122:             sleep((caddr_t)&tp->t_canq, TTIPRI);
 123:             goto again;
 124:         }
 125:         while (tp->t_canq.c_cc > 1 && uio->uio_resid)
 126:             if (ureadc(getc(&tp->t_canq), uio) < 0) {
 127:                 error = EFAULT;
 128:                 break;
 129:             }
 130:         if (tp->t_canq.c_cc == 1)
 131:             (void) getc(&tp->t_canq);
 132:         if (tp->t_canq.c_cc)
 133:             return (error);
 134:     } else
 135:         if (tp->t_oproc)
 136:             error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
 137:     ptcwakeup(tp, FWRITE);
 138:     return (error);
 139: }
 140: 
 141: /*
 142:  * Write to pseudo-tty.
 143:  * Wakeups of controlling tty will happen
 144:  * indirectly, when tty driver calls ptsstart.
 145:  */
 146: ptswrite(dev, uio, flag)
 147:     dev_t dev;
 148:     register struct uio *uio;
 149:     int flag;
 150: {
 151:     register struct tty *tp;
 152: 
 153:     tp = &pt_tty[minor(dev)];
 154:     if (tp->t_oproc == 0)
 155:         return (EIO);
 156:     return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
 157: }
 158: 
 159: /*
 160:  * Start output on pseudo-tty.
 161:  * Wake up process selecting or sleeping for input from controlling tty.
 162:  */
 163: ptsstart(tp)
 164:     struct tty *tp;
 165: {
 166:     register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
 167: 
 168:     if (tp->t_state & TS_TTSTOP)
 169:         return;
 170:     if (pti->pt_flags & PF_STOPPED) {
 171:         pti->pt_flags &= ~PF_STOPPED;
 172:         pti->pt_send = TIOCPKT_START;
 173:     }
 174:     ptcwakeup(tp, FREAD);
 175: }
 176: 
 177: ptcwakeup(tp, flag)
 178:     struct tty *tp;
 179: {
 180:     struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
 181: 
 182:     if (flag & FREAD) {
 183:         if (pti->pt_selr) {
 184:             selwakeup(pti->pt_selr, (long)(pti->pt_flags & PF_RCOLL));
 185:             pti->pt_selr = 0;
 186:             pti->pt_flags &= ~PF_RCOLL;
 187:         }
 188:         wakeup((caddr_t)&tp->t_outq.c_cf);
 189:     }
 190:     if (flag & FWRITE) {
 191:         if (pti->pt_selw) {
 192:             selwakeup(pti->pt_selw, (long)(pti->pt_flags & PF_WCOLL));
 193:             pti->pt_selw = 0;
 194:             pti->pt_flags &= ~PF_WCOLL;
 195:         }
 196:         wakeup((caddr_t)&tp->t_rawq.c_cf);
 197:     }
 198: }
 199: 
 200: /*ARGSUSED*/
 201: ptcopen(dev, flag)
 202:     dev_t dev;
 203:     int flag;
 204: {
 205:     register struct tty *tp;
 206:     struct pt_ioctl *pti;
 207: 
 208:     if (minor(dev) >= NPTY)
 209:         return (ENXIO);
 210:     tp = &pt_tty[minor(dev)];
 211:     if (tp->t_oproc)
 212:         return (EIO);
 213:     tp->t_oproc = ptsstart;
 214:     (void)(*linesw[tp->t_line].l_modem)(tp, 1);
 215:     pti = &pt_ioctl[minor(dev)];
 216:     pti->pt_flags = 0;
 217:     pti->pt_send = 0;
 218:     pti->pt_ucntl = 0;
 219:     return (0);
 220: }
 221: 
 222: ptcclose(dev, flag)
 223:     dev_t dev;
 224:     int flag;
 225: {
 226:     register struct tty *tp;
 227: 
 228:     tp = &pt_tty[minor(dev)];
 229:     (void)(*linesw[tp->t_line].l_modem)(tp, 0);
 230:     tp->t_state &= ~TS_CARR_ON;
 231:     tp->t_oproc = 0;        /* mark closed */
 232: }
 233: 
 234: ptcread(dev, uio, flag)
 235:     dev_t dev;
 236:     register struct uio *uio;
 237:     int flag;
 238: {
 239:     register struct tty *tp = &pt_tty[minor(dev)];
 240:     struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
 241:     char buf[BUFSIZ];
 242:     int error = 0, cc;
 243: 
 244:     /*
 245: 	 * We want to block until the slave
 246: 	 * is open, and there's something to read;
 247: 	 * but if we lost the slave or we're NBIO,
 248: 	 * then return the appropriate error instead.
 249: 	 */
 250:     for (;;) {
 251:         if (tp->t_state&TS_ISOPEN) {
 252:             if (pti->pt_flags&PF_PKT && pti->pt_send) {
 253:                 error = ureadc((int)pti->pt_send, uio);
 254:                 if (error)
 255:                     return (error);
 256:                 pti->pt_send = 0;
 257:                 return (0);
 258:             }
 259:             if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
 260:                 error = ureadc((int)pti->pt_ucntl, uio);
 261:                 if (error)
 262:                     return (error);
 263:                 pti->pt_ucntl = 0;
 264:                 return (0);
 265:             }
 266:             if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
 267:                 break;
 268:         }
 269:         if ((tp->t_state&TS_CARR_ON) == 0)
 270:             return (0); /* EOF */
 271:         if (flag & IO_NDELAY)
 272:             return (EWOULDBLOCK);
 273:         sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI);
 274:     }
 275:     if (pti->pt_flags & (PF_PKT|PF_UCNTL))
 276:         error = ureadc(0, uio);
 277:     while (uio->uio_resid && error == 0) {
 278:         cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ));
 279:         if (cc <= 0)
 280:             break;
 281:         error = uiomove(buf, cc, uio);
 282:     }
 283:     if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
 284:         if (tp->t_state&TS_ASLEEP) {
 285:             tp->t_state &= ~TS_ASLEEP;
 286:             wakeup((caddr_t)&tp->t_outq);
 287:         }
 288:         if (tp->t_wsel) {
 289:             selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
 290:             tp->t_wsel = 0;
 291:             tp->t_state &= ~TS_WCOLL;
 292:         }
 293:     }
 294:     return (error);
 295: }
 296: 
 297: ptsstop(tp, flush)
 298:     register struct tty *tp;
 299:     int flush;
 300: {
 301:     struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
 302:     int flag;
 303: 
 304:     /* note: FLUSHREAD and FLUSHWRITE already ok */
 305:     if (flush == 0) {
 306:         flush = TIOCPKT_STOP;
 307:         pti->pt_flags |= PF_STOPPED;
 308:     } else
 309:         pti->pt_flags &= ~PF_STOPPED;
 310:     pti->pt_send |= flush;
 311:     /* change of perspective */
 312:     flag = 0;
 313:     if (flush & FREAD)
 314:         flag |= FWRITE;
 315:     if (flush & FWRITE)
 316:         flag |= FREAD;
 317:     ptcwakeup(tp, flag);
 318: }
 319: 
 320: ptcselect(dev, rw)
 321:     dev_t dev;
 322:     int rw;
 323: {
 324:     register struct tty *tp = &pt_tty[minor(dev)];
 325:     struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
 326:     struct proc *p;
 327:     int s;
 328: 
 329:     if ((tp->t_state&TS_CARR_ON) == 0)
 330:         return (1);
 331:     switch (rw) {
 332: 
 333:     case FREAD:
 334:         /*
 335: 		 * Need to block timeouts (ttrstart).
 336: 		 */
 337:         s = spltty();
 338:         if ((tp->t_state&TS_ISOPEN) &&
 339:              tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
 340:             splx(s);
 341:             return (1);
 342:         }
 343:         splx(s);
 344:         /* FALLTHROUGH */
 345: 
 346:     case 0:                 /* exceptional */
 347:         if ((tp->t_state&TS_ISOPEN) &&
 348:             (pti->pt_flags&PF_PKT && pti->pt_send ||
 349:              pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
 350:             return (1);
 351:         if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait)
 352:             pti->pt_flags |= PF_RCOLL;
 353:         else
 354:             pti->pt_selr = u.u_procp;
 355:         break;
 356: 
 357: 
 358:     case FWRITE:
 359:         if (tp->t_state&TS_ISOPEN) {
 360:             if (pti->pt_flags & PF_REMOTE) {
 361:                 if (tp->t_canq.c_cc == 0)
 362:                 return (1);
 363:             } else {
 364:                 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
 365:                     return (1);
 366:                 if (tp->t_canq.c_cc == 0 &&
 367:                     (tp->t_flags & (RAW|CBREAK)) == 0)
 368:                     return (1);
 369:             }
 370:         }
 371:         if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait)
 372:             pti->pt_flags |= PF_WCOLL;
 373:         else
 374:             pti->pt_selw = u.u_procp;
 375:         break;
 376: 
 377:     }
 378:     return (0);
 379: }
 380: 
 381: ptcwrite(dev, uio, flag)
 382:     dev_t dev;
 383:     register struct uio *uio;
 384:     int flag;
 385: {
 386:     register struct tty *tp = &pt_tty[minor(dev)];
 387:     register char *cp;
 388:     register int cc = 0;
 389:     char locbuf[BUFSIZ];
 390:     int cnt = 0;
 391:     struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
 392:     int error = 0;
 393: 
 394: again:
 395:     if ((tp->t_state&TS_ISOPEN) == 0)
 396:         goto block;
 397:     if (pti->pt_flags & PF_REMOTE) {
 398:         if (tp->t_canq.c_cc)
 399:             goto block;
 400:         while (uio->uio_resid && tp->t_canq.c_cc < TTYHOG - 1) {
 401:             if (cc == 0) {
 402:                 cc = MIN(uio->uio_resid, BUFSIZ);
 403:                 cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc);
 404:                 cp = locbuf;
 405:                 error = uiomove(cp, cc, uio);
 406:                 if (error)
 407:                     return (error);
 408:                 /* check again for safety */
 409:                 if ((tp->t_state&TS_ISOPEN) == 0)
 410:                     return (EIO);
 411:             }
 412:             if (cc)
 413:                 (void) b_to_q(cp, cc, &tp->t_canq);
 414:             cc = 0;
 415:         }
 416:         (void) putc(0, &tp->t_canq);
 417:         ttwakeup(tp);
 418:         wakeup((caddr_t)&tp->t_canq);
 419:         return (0);
 420:     }
 421:     while (uio->uio_resid > 0) {
 422:         if (cc == 0) {
 423:             cc = MIN(uio->uio_resid, BUFSIZ);
 424:             cp = locbuf;
 425:             error = uiomove(cp, cc, uio);
 426:             if (error)
 427:                 return (error);
 428:             /* check again for safety */
 429:             if ((tp->t_state&TS_ISOPEN) == 0)
 430:                 return (EIO);
 431:         }
 432:         while (cc > 0) {
 433:             if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
 434:                (tp->t_canq.c_cc > 0 ||
 435:                   tp->t_flags & (RAW|CBREAK))) {
 436:                 wakeup((caddr_t)&tp->t_rawq);
 437:                 goto block;
 438:             }
 439:             (*linesw[tp->t_line].l_rint)(*cp++, tp);
 440:             cnt++;
 441:             cc--;
 442:         }
 443:         cc = 0;
 444:     }
 445:     return (0);
 446: block:
 447:     /*
 448: 	 * Come here to wait for slave to open, for space
 449: 	 * in outq, or space in rawq.
 450: 	 */
 451:     if ((tp->t_state&TS_CARR_ON) == 0)
 452:         return (EIO);
 453:     if (flag & IO_NDELAY) {
 454:         /* adjust for data copied in but not written */
 455:         uio->uio_resid += cc;
 456:         if (cnt == 0)
 457:             return (EWOULDBLOCK);
 458:         return (0);
 459:     }
 460:     sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI);
 461:     goto again;
 462: }
 463: 
 464: /*ARGSUSED*/
 465: ptyioctl(dev, cmd, data, flag)
 466:     caddr_t data;
 467:     u_int cmd;
 468:     dev_t dev;
 469:     int flag;
 470: {
 471:     register struct tty *tp = &pt_tty[minor(dev)];
 472:     register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
 473:     int stop, error;
 474:     extern ttyinput();
 475: 
 476:     /*
 477: 	 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
 478: 	 * ttywflush(tp) will hang if there are characters in the outq.
 479: 	 */
 480:     if (cdevsw[major(dev)].d_open == ptcopen)
 481:         switch (cmd) {
 482: 
 483:         case TIOCPKT:
 484:             if (*(int *)data) {
 485:                 if (pti->pt_flags & PF_UCNTL)
 486:                     return (EINVAL);
 487:                 pti->pt_flags |= PF_PKT;
 488:             } else
 489:                 pti->pt_flags &= ~PF_PKT;
 490:             return (0);
 491: 
 492:         case TIOCUCNTL:
 493:             if (*(int *)data) {
 494:                 if (pti->pt_flags & PF_PKT)
 495:                     return (EINVAL);
 496:                 pti->pt_flags |= PF_UCNTL;
 497:             } else
 498:                 pti->pt_flags &= ~PF_UCNTL;
 499:             return (0);
 500: 
 501:         case TIOCREMOTE:
 502:             if (*(int *)data)
 503:                 pti->pt_flags |= PF_REMOTE;
 504:             else
 505:                 pti->pt_flags &= ~PF_REMOTE;
 506:             ttyflush(tp, FREAD|FWRITE);
 507:             return (0);
 508: 
 509:         case TIOCSETP:
 510:         case TIOCSETN:
 511:         case TIOCSETD:
 512:             while (getc(&tp->t_outq) >= 0)
 513:                 ;
 514:             break;
 515:         }
 516: /*
 517:  * Unsure if the comment below still applies or not.  For now put the
 518:  * new code in ifdef'd out.
 519: */
 520: 
 521: #ifdef  four_four_bsd
 522:     error = (*linesw[t->t_line].l_ioctl(tp, cmd, data, flag);
 523:     if (error < 0)
 524:         error = ttioctl(tp, cmd, data, flag);
 525: #else
 526:     error = ttioctl(tp, cmd, data, flag);
 527:     /*
 528: 	 * Since we use the tty queues internally,
 529: 	 * pty's can't be switched to disciplines which overwrite
 530: 	 * the queues.  We can't tell anything about the discipline
 531: 	 * from here...
 532: 	 */
 533:     if (linesw[tp->t_line].l_rint != ttyinput) {
 534:         (*linesw[tp->t_line].l_close)(tp, flag);
 535:         tp->t_line = 0;
 536:         (void)(*linesw[tp->t_line].l_open)(dev, tp);
 537:         error = ENOTTY;
 538:     }
 539: #endif
 540:     if (error < 0) {
 541:         if (pti->pt_flags & PF_UCNTL &&
 542:             (cmd & ~0xff) == UIOCCMD(0)) {
 543:             if (cmd & 0xff) {
 544:                 pti->pt_ucntl = (u_char)cmd;
 545:                 ptcwakeup(tp, FREAD);
 546:             }
 547:             return (0);
 548:         }
 549:         error = ENOTTY;
 550:     }
 551:     stop = (tp->t_flags & RAW) == 0 &&
 552:         tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q);
 553:     if (pti->pt_flags & PF_NOSTOP) {
 554:         if (stop) {
 555:             pti->pt_send &= ~TIOCPKT_NOSTOP;
 556:             pti->pt_send |= TIOCPKT_DOSTOP;
 557:             pti->pt_flags &= ~PF_NOSTOP;
 558:             ptcwakeup(tp, FREAD);
 559:         }
 560:     } else {
 561:         if (!stop) {
 562:             pti->pt_send &= ~TIOCPKT_DOSTOP;
 563:             pti->pt_send |= TIOCPKT_NOSTOP;
 564:             pti->pt_flags |= PF_NOSTOP;
 565:             ptcwakeup(tp, FREAD);
 566:         }
 567:     }
 568:     return (error);
 569: }
 570: #endif

Defined functions

ptcclose defined in line 222; never used
ptcopen defined in line 201; used 1 times
ptcread defined in line 234; never used
ptcselect defined in line 320; never used
ptcwakeup defined in line 177; used 8 times
ptcwrite defined in line 381; never used
ptsclose defined in line 88; never used
ptsopen defined in line 59; never used
ptsread defined in line 100; never used
ptsstart defined in line 163; used 1 times
ptsstop defined in line 297; never used
ptswrite defined in line 146; never used
ptyioctl defined in line 465; never used

Defined variables

npty defined in line 48; used 2 times
  • in line 66(2)
pt_ioctl defined in line 47; used 9 times
pt_tty defined in line 41; used 10 times

Defined struct's

pt_ioctl defined in line 42; used 18 times

Defined macros

BUFSIZ defined in line 35; used 5 times
NPTY defined in line 32; used 8 times
PF_NOSTOP defined in line 55; used 3 times
PF_PKT defined in line 52; used 6 times
PF_RCOLL defined in line 50; used 3 times
PF_REMOTE defined in line 54; used 5 times
PF_STOPPED defined in line 53; used 4 times
PF_UCNTL defined in line 56; used 7 times
PF_WCOLL defined in line 51; used 3 times
Last modified: 1997-05-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5006
Valid CSS Valid XHTML 1.0 Strict