1 /* 2 * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)tty_pty.c 7.25 (Berkeley) 03/14/92 8 */ 9 10 /* 11 * Pseudo-teletype Driver 12 * (Actually two drivers, requiring two entries in 'cdevsw') 13 */ 14 #include "pty.h" 15 16 #if NPTY > 0 17 #include "param.h" 18 #include "systm.h" 19 #include "ioctl.h" 20 #include "proc.h" 21 #include "tty.h" 22 #include "conf.h" 23 #include "file.h" 24 #include "uio.h" 25 #include "kernel.h" 26 #include "vnode.h" 27 28 #if NPTY == 1 29 #undef NPTY 30 #define NPTY 32 /* crude XXX */ 31 #endif 32 33 #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 34 35 /* 36 * pts == /dev/tty[pqrs]? 37 * ptc == /dev/pty[pqrs]? 38 */ 39 struct tty pt_tty[NPTY]; 40 struct pt_ioctl { 41 int pt_flags; 42 struct selinfo pt_selr, pt_selw; 43 u_char pt_send; 44 u_char pt_ucntl; 45 } pt_ioctl[NPTY]; 46 int npty = NPTY; /* for pstat -t */ 47 48 #define PF_PKT 0x08 /* packet mode */ 49 #define PF_STOPPED 0x10 /* user told stopped */ 50 #define PF_REMOTE 0x20 /* remote and flow controlled input */ 51 #define PF_NOSTOP 0x40 52 #define PF_UCNTL 0x80 /* user control mode */ 53 54 void ptsstop __P((struct tty *, int)); 55 56 /*ARGSUSED*/ 57 ptsopen(dev, flag, devtype, p) 58 dev_t dev; 59 int flag, devtype; 60 struct proc *p; 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 tp->t_state |= TS_WOPEN; 73 ttychars(tp); /* Set up default chars */ 74 tp->t_iflag = TTYDEF_IFLAG; 75 tp->t_oflag = TTYDEF_OFLAG; 76 tp->t_lflag = TTYDEF_LFLAG; 77 tp->t_cflag = TTYDEF_CFLAG; 78 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 79 ttsetwater(tp); /* would be done in xxparam() */ 80 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 81 return (EBUSY); 82 if (tp->t_oproc) /* Ctrlr still around. */ 83 tp->t_state |= TS_CARR_ON; 84 while ((tp->t_state & TS_CARR_ON) == 0) { 85 tp->t_state |= TS_WOPEN; 86 if (flag&FNONBLOCK) 87 break; 88 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 89 ttopen, 0)) 90 return (error); 91 } 92 error = (*linesw[tp->t_line].l_open)(dev, tp); 93 ptcwakeup(tp, FREAD|FWRITE); 94 return (error); 95 } 96 97 ptsclose(dev, flag, mode, p) 98 dev_t dev; 99 int flag, mode; 100 struct proc *p; 101 { 102 register struct tty *tp; 103 104 tp = &pt_tty[minor(dev)]; 105 (*linesw[tp->t_line].l_close)(tp, flag); 106 ttyclose(tp); 107 ptcwakeup(tp, FREAD|FWRITE); 108 } 109 110 ptsread(dev, uio, flag) 111 dev_t dev; 112 struct uio *uio; 113 int flag; 114 { 115 struct proc *p = curproc; 116 register struct tty *tp = &pt_tty[minor(dev)]; 117 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 118 int error = 0; 119 120 again: 121 if (pti->pt_flags & PF_REMOTE) { 122 while (isbackground(p, tp)) { 123 if ((p->p_sigignore & sigmask(SIGTTIN)) || 124 (p->p_sigmask & sigmask(SIGTTIN)) || 125 p->p_pgrp->pg_jobc == 0 || 126 p->p_flag&SPPWAIT) 127 return (EIO); 128 pgsignal(p->p_pgrp, SIGTTIN, 1); 129 if (error = ttysleep(tp, (caddr_t)&lbolt, 130 TTIPRI | PCATCH, ttybg, 0)) 131 return (error); 132 } 133 if (tp->t_canq.c_cc == 0) { 134 if (flag & IO_NDELAY) 135 return (EWOULDBLOCK); 136 if (error = ttysleep(tp, (caddr_t)&tp->t_canq, 137 TTIPRI | PCATCH, ttyin, 0)) 138 return (error); 139 goto again; 140 } 141 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 142 if (ureadc(getc(&tp->t_canq), uio) < 0) { 143 error = EFAULT; 144 break; 145 } 146 if (tp->t_canq.c_cc == 1) 147 (void) getc(&tp->t_canq); 148 if (tp->t_canq.c_cc) 149 return (error); 150 } else 151 if (tp->t_oproc) 152 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 153 ptcwakeup(tp, FWRITE); 154 return (error); 155 } 156 157 /* 158 * Write to pseudo-tty. 159 * Wakeups of controlling tty will happen 160 * indirectly, when tty driver calls ptsstart. 161 */ 162 ptswrite(dev, uio, flag) 163 dev_t dev; 164 struct uio *uio; 165 int flag; 166 { 167 register struct tty *tp; 168 169 tp = &pt_tty[minor(dev)]; 170 if (tp->t_oproc == 0) 171 return (EIO); 172 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 173 } 174 175 /* 176 * Start output on pseudo-tty. 177 * Wake up process selecting or sleeping for input from controlling tty. 178 */ 179 void 180 ptsstart(tp) 181 struct tty *tp; 182 { 183 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 184 185 if (tp->t_state & TS_TTSTOP) 186 return; 187 if (pti->pt_flags & PF_STOPPED) { 188 pti->pt_flags &= ~PF_STOPPED; 189 pti->pt_send = TIOCPKT_START; 190 } 191 ptcwakeup(tp, FREAD); 192 } 193 194 ptcwakeup(tp, flag) 195 struct tty *tp; 196 int flag; 197 { 198 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 199 200 if (flag & FREAD) { 201 selwakeup(&pti->pt_selr); 202 wakeup((caddr_t)&tp->t_outq.c_cf); 203 } 204 if (flag & FWRITE) { 205 selwakeup(&pti->pt_selw); 206 wakeup((caddr_t)&tp->t_rawq.c_cf); 207 } 208 } 209 210 /*ARGSUSED*/ 211 #ifdef __STDC__ 212 ptcopen(dev_t dev, int flag, int devtype, struct proc *p) 213 #else 214 ptcopen(dev, flag, devtype, p) 215 dev_t dev; 216 int flag, devtype; 217 struct proc *p; 218 #endif 219 { 220 register struct tty *tp; 221 struct pt_ioctl *pti; 222 223 if (minor(dev) >= NPTY) 224 return (ENXIO); 225 tp = &pt_tty[minor(dev)]; 226 if (tp->t_oproc) 227 return (EIO); 228 tp->t_oproc = ptsstart; 229 #ifdef sun4c 230 tp->t_stop = ptsstop; 231 #endif 232 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 233 tp->t_lflag &= ~EXTPROC; 234 pti = &pt_ioctl[minor(dev)]; 235 pti->pt_flags = 0; 236 pti->pt_send = 0; 237 pti->pt_ucntl = 0; 238 return (0); 239 } 240 241 ptcclose(dev) 242 dev_t dev; 243 { 244 register struct tty *tp; 245 246 tp = &pt_tty[minor(dev)]; 247 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 248 tp->t_state &= ~TS_CARR_ON; 249 tp->t_oproc = 0; /* mark closed */ 250 tp->t_session = 0; 251 } 252 253 ptcread(dev, uio, flag) 254 dev_t dev; 255 struct uio *uio; 256 int flag; 257 { 258 register struct tty *tp = &pt_tty[minor(dev)]; 259 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 260 char buf[BUFSIZ]; 261 int error = 0, cc; 262 263 /* 264 * We want to block until the slave 265 * is open, and there's something to read; 266 * but if we lost the slave or we're NBIO, 267 * then return the appropriate error instead. 268 */ 269 for (;;) { 270 if (tp->t_state&TS_ISOPEN) { 271 if (pti->pt_flags&PF_PKT && pti->pt_send) { 272 error = ureadc((int)pti->pt_send, uio); 273 if (error) 274 return (error); 275 if (pti->pt_send & TIOCPKT_IOCTL) { 276 cc = MIN(uio->uio_resid, 277 sizeof(tp->t_termios)); 278 uiomove(&tp->t_termios, cc, uio); 279 } 280 pti->pt_send = 0; 281 return (0); 282 } 283 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 284 error = ureadc((int)pti->pt_ucntl, uio); 285 if (error) 286 return (error); 287 pti->pt_ucntl = 0; 288 return (0); 289 } 290 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 291 break; 292 } 293 if ((tp->t_state&TS_CARR_ON) == 0) 294 return (0); /* EOF */ 295 if (flag & IO_NDELAY) 296 return (EWOULDBLOCK); 297 if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH, 298 ttyin, 0)) 299 return (error); 300 } 301 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 302 error = ureadc(0, uio); 303 while (uio->uio_resid > 0 && error == 0) { 304 cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 305 if (cc <= 0) 306 break; 307 error = uiomove(buf, cc, uio); 308 } 309 if (tp->t_outq.c_cc <= tp->t_lowat) { 310 if (tp->t_state&TS_ASLEEP) { 311 tp->t_state &= ~TS_ASLEEP; 312 wakeup((caddr_t)&tp->t_outq); 313 } 314 selwakeup(&tp->t_wsel); 315 } 316 return (error); 317 } 318 319 void 320 ptsstop(tp, flush) 321 register struct tty *tp; 322 int flush; 323 { 324 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 325 int flag; 326 327 /* note: FLUSHREAD and FLUSHWRITE already ok */ 328 if (flush == 0) { 329 flush = TIOCPKT_STOP; 330 pti->pt_flags |= PF_STOPPED; 331 } else 332 pti->pt_flags &= ~PF_STOPPED; 333 pti->pt_send |= flush; 334 /* change of perspective */ 335 flag = 0; 336 if (flush & FREAD) 337 flag |= FWRITE; 338 if (flush & FWRITE) 339 flag |= FREAD; 340 ptcwakeup(tp, flag); 341 } 342 343 ptcselect(dev, rw, p) 344 dev_t dev; 345 int rw; 346 struct proc *p; 347 { 348 register struct tty *tp = &pt_tty[minor(dev)]; 349 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 350 int s; 351 352 if ((tp->t_state&TS_CARR_ON) == 0) 353 return (1); 354 switch (rw) { 355 356 case FREAD: 357 /* 358 * Need to block timeouts (ttrstart). 359 */ 360 s = spltty(); 361 if ((tp->t_state&TS_ISOPEN) && 362 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 363 splx(s); 364 return (1); 365 } 366 splx(s); 367 /* FALLTHROUGH */ 368 369 case 0: /* exceptional */ 370 if ((tp->t_state&TS_ISOPEN) && 371 (pti->pt_flags&PF_PKT && pti->pt_send || 372 pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 373 return (1); 374 selrecord(p, &pti->pt_selr); 375 break; 376 377 378 case FWRITE: 379 if (tp->t_state&TS_ISOPEN) { 380 if (pti->pt_flags & PF_REMOTE) { 381 if (tp->t_canq.c_cc == 0) 382 return (1); 383 } else { 384 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 385 return (1); 386 if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON)) 387 return (1); 388 } 389 } 390 selrecord(p, &pti->pt_selw); 391 break; 392 393 } 394 return (0); 395 } 396 397 ptcwrite(dev, uio, flag) 398 dev_t dev; 399 register struct uio *uio; 400 int flag; 401 { 402 register struct tty *tp = &pt_tty[minor(dev)]; 403 register u_char *cp; 404 register int cc = 0; 405 u_char locbuf[BUFSIZ]; 406 int cnt = 0; 407 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 408 int error = 0; 409 410 again: 411 if ((tp->t_state&TS_ISOPEN) == 0) 412 goto block; 413 if (pti->pt_flags & PF_REMOTE) { 414 if (tp->t_canq.c_cc) 415 goto block; 416 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 417 if (cc == 0) { 418 cc = min(uio->uio_resid, BUFSIZ); 419 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 420 cp = locbuf; 421 error = uiomove((caddr_t)cp, cc, uio); 422 if (error) 423 return (error); 424 /* check again for safety */ 425 if ((tp->t_state&TS_ISOPEN) == 0) 426 return (EIO); 427 } 428 if (cc) 429 (void) b_to_q((char *)cp, cc, &tp->t_canq); 430 cc = 0; 431 } 432 (void) putc(0, &tp->t_canq); 433 ttwakeup(tp); 434 wakeup((caddr_t)&tp->t_canq); 435 return (0); 436 } 437 while (uio->uio_resid > 0) { 438 if (cc == 0) { 439 cc = min(uio->uio_resid, BUFSIZ); 440 cp = locbuf; 441 error = uiomove((caddr_t)cp, cc, uio); 442 if (error) 443 return (error); 444 /* check again for safety */ 445 if ((tp->t_state&TS_ISOPEN) == 0) 446 return (EIO); 447 } 448 while (cc > 0) { 449 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 450 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 451 wakeup((caddr_t)&tp->t_rawq); 452 goto block; 453 } 454 (*linesw[tp->t_line].l_rint)(*cp++, tp); 455 cnt++; 456 cc--; 457 } 458 cc = 0; 459 } 460 return (0); 461 block: 462 /* 463 * Come here to wait for slave to open, for space 464 * in outq, or space in rawq. 465 */ 466 if ((tp->t_state&TS_CARR_ON) == 0) 467 return (EIO); 468 if (flag & IO_NDELAY) { 469 /* adjust for data copied in but not written */ 470 uio->uio_resid += cc; 471 if (cnt == 0) 472 return (EWOULDBLOCK); 473 return (0); 474 } 475 if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH, 476 ttyout, 0)) { 477 /* adjust for data copied in but not written */ 478 uio->uio_resid += cc; 479 return (error); 480 } 481 goto again; 482 } 483 484 /*ARGSUSED*/ 485 ptyioctl(dev, cmd, data, flag, p) 486 dev_t dev; 487 int cmd; 488 caddr_t data; 489 int flag; 490 struct proc *p; 491 { 492 register struct tty *tp = &pt_tty[minor(dev)]; 493 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 494 register u_char *cc = tp->t_cc; 495 int stop, error; 496 497 /* 498 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 499 * ttywflush(tp) will hang if there are characters in the outq. 500 */ 501 if (cmd == TIOCEXT) { 502 /* 503 * When the EXTPROC bit is being toggled, we need 504 * to send an TIOCPKT_IOCTL if the packet driver 505 * is turned on. 506 */ 507 if (*(int *)data) { 508 if (pti->pt_flags & PF_PKT) { 509 pti->pt_send |= TIOCPKT_IOCTL; 510 ptcwakeup(tp); 511 } 512 tp->t_lflag |= EXTPROC; 513 } else { 514 if ((tp->t_state & EXTPROC) && 515 (pti->pt_flags & PF_PKT)) { 516 pti->pt_send |= TIOCPKT_IOCTL; 517 ptcwakeup(tp); 518 } 519 tp->t_lflag &= ~EXTPROC; 520 } 521 return(0); 522 } else 523 if (cdevsw[major(dev)].d_open == ptcopen) 524 switch (cmd) { 525 526 case TIOCGPGRP: 527 /* 528 * We aviod calling ttioctl on the controller since, 529 * in that case, tp must be the controlling terminal. 530 */ 531 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 532 return (0); 533 534 case TIOCPKT: 535 if (*(int *)data) { 536 if (pti->pt_flags & PF_UCNTL) 537 return (EINVAL); 538 pti->pt_flags |= PF_PKT; 539 } else 540 pti->pt_flags &= ~PF_PKT; 541 return (0); 542 543 case TIOCUCNTL: 544 if (*(int *)data) { 545 if (pti->pt_flags & PF_PKT) 546 return (EINVAL); 547 pti->pt_flags |= PF_UCNTL; 548 } else 549 pti->pt_flags &= ~PF_UCNTL; 550 return (0); 551 552 case TIOCREMOTE: 553 if (*(int *)data) 554 pti->pt_flags |= PF_REMOTE; 555 else 556 pti->pt_flags &= ~PF_REMOTE; 557 ttyflush(tp, FREAD|FWRITE); 558 return (0); 559 560 #ifdef COMPAT_43 561 case TIOCSETP: 562 case TIOCSETN: 563 #endif 564 case TIOCSETD: 565 case TIOCSETA: 566 case TIOCSETAW: 567 case TIOCSETAF: 568 ndflush(&tp->t_outq, tp->t_outq.c_cc); 569 break; 570 571 case TIOCSIG: 572 if (*(unsigned int *)data >= NSIG) 573 return(EINVAL); 574 if ((tp->t_lflag&NOFLSH) == 0) 575 ttyflush(tp, FREAD|FWRITE); 576 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 577 if ((*(unsigned int *)data == SIGINFO) && 578 ((tp->t_lflag&NOKERNINFO) == 0)) 579 ttyinfo(tp); 580 return(0); 581 } 582 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 583 if (error < 0) 584 error = ttioctl(tp, cmd, data, flag); 585 if (error < 0) { 586 if (pti->pt_flags & PF_UCNTL && 587 (cmd & ~0xff) == UIOCCMD(0)) { 588 if (cmd & 0xff) { 589 pti->pt_ucntl = (u_char)cmd; 590 ptcwakeup(tp, FREAD); 591 } 592 return (0); 593 } 594 error = ENOTTY; 595 } 596 /* 597 * If external processing and packet mode send ioctl packet. 598 */ 599 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 600 switch(cmd) { 601 case TIOCSETA: 602 case TIOCSETAW: 603 case TIOCSETAF: 604 #ifdef COMPAT_43 605 case TIOCSETP: 606 case TIOCSETN: 607 #endif 608 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 609 case TIOCSETC: 610 case TIOCSLTC: 611 case TIOCLBIS: 612 case TIOCLBIC: 613 case TIOCLSET: 614 #endif 615 pti->pt_send |= TIOCPKT_IOCTL; 616 default: 617 break; 618 } 619 } 620 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 621 && CCEQ(cc[VSTART], CTRL('q')); 622 if (pti->pt_flags & PF_NOSTOP) { 623 if (stop) { 624 pti->pt_send &= ~TIOCPKT_NOSTOP; 625 pti->pt_send |= TIOCPKT_DOSTOP; 626 pti->pt_flags &= ~PF_NOSTOP; 627 ptcwakeup(tp, FREAD); 628 } 629 } else { 630 if (!stop) { 631 pti->pt_send &= ~TIOCPKT_DOSTOP; 632 pti->pt_send |= TIOCPKT_NOSTOP; 633 pti->pt_flags |= PF_NOSTOP; 634 ptcwakeup(tp, FREAD); 635 } 636 } 637 return (error); 638 } 639 #endif 640