1 /* $OpenBSD: tty_pty.c,v 1.108 2021/02/08 09:18:30 claudio Exp $ */ 2 /* $NetBSD: tty_pty.c,v 1.33.4.1 1996/06/02 09:08:11 mrg Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 33 */ 34 35 /* 36 * Pseudo-teletype Driver 37 * (Actually two drivers, requiring two entries in 'cdevsw') 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/namei.h> 43 #include <sys/mount.h> 44 #include <sys/ioctl.h> 45 #include <sys/proc.h> 46 #include <sys/tty.h> 47 #include <sys/fcntl.h> 48 #include <sys/file.h> 49 #include <sys/filedesc.h> 50 #include <sys/uio.h> 51 #include <sys/kernel.h> 52 #include <sys/malloc.h> 53 #include <sys/vnode.h> 54 #include <sys/signalvar.h> 55 #include <sys/conf.h> 56 #include <sys/stat.h> 57 #include <sys/sysctl.h> 58 #include <sys/poll.h> 59 #include <sys/pledge.h> 60 #include <sys/rwlock.h> 61 62 #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 63 64 /* 65 * pts == /dev/tty[p-zP-T][0-9a-zA-Z] 66 * ptc == /dev/pty[p-zP-T][0-9a-zA-Z] 67 */ 68 69 /* XXX this needs to come from somewhere sane, and work with MAKEDEV */ 70 #define TTY_LETTERS "pqrstuvwxyzPQRST" 71 #define TTY_SUFFIX "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 72 73 static int pts_major; 74 75 struct pt_softc { 76 struct tty *pt_tty; 77 int pt_flags; 78 struct selinfo pt_selr, pt_selw; 79 u_char pt_send; 80 u_char pt_ucntl; 81 char pty_pn[11]; 82 char pty_sn[11]; 83 }; 84 85 #define NPTY_MIN 8 /* number of initial ptys */ 86 #define NPTY_MAX 992 /* maximum number of ptys supported */ 87 88 static struct pt_softc **pt_softc = NULL; /* pty array */ 89 static int npty = 0; /* size of pty array */ 90 static int maxptys = NPTY_MAX; /* maximum number of ptys */ 91 /* for pty array */ 92 struct rwlock pt_softc_lock = RWLOCK_INITIALIZER("ptarrlk"); 93 94 #define PF_PKT 0x08 /* packet mode */ 95 #define PF_STOPPED 0x10 /* user told stopped */ 96 #define PF_REMOTE 0x20 /* remote and flow controlled input */ 97 #define PF_NOSTOP 0x40 98 #define PF_UCNTL 0x80 /* user control mode */ 99 100 void ptyattach(int); 101 void ptcwakeup(struct tty *, int); 102 struct tty *ptytty(dev_t); 103 void ptsstart(struct tty *); 104 int sysctl_pty(int *, u_int, void *, size_t *, void *, size_t); 105 106 void filt_ptcrdetach(struct knote *); 107 int filt_ptcread(struct knote *, long); 108 void filt_ptcwdetach(struct knote *); 109 int filt_ptcwrite(struct knote *, long); 110 111 static struct pt_softc **ptyarralloc(int); 112 static int check_pty(int); 113 114 static gid_t tty_gid = TTY_GID; 115 116 void ptydevname(int, struct pt_softc *); 117 dev_t pty_getfree(void); 118 119 void ptmattach(int); 120 int ptmopen(dev_t, int, int, struct proc *); 121 int ptmclose(dev_t, int, int, struct proc *); 122 int ptmioctl(dev_t, u_long, caddr_t, int, struct proc *p); 123 static int ptm_vn_open(struct nameidata *); 124 125 void 126 ptydevname(int minor, struct pt_softc *pti) 127 { 128 char buf[11] = "/dev/XtyXX"; 129 int i, j; 130 131 i = minor / (sizeof(TTY_SUFFIX) - 1); 132 j = minor % (sizeof(TTY_SUFFIX) - 1); 133 if (i >= sizeof(TTY_LETTERS) - 1) { 134 pti->pty_pn[0] = '\0'; 135 pti->pty_sn[0] = '\0'; 136 return; 137 } 138 buf[5] = 'p'; 139 buf[8] = TTY_LETTERS[i]; 140 buf[9] = TTY_SUFFIX[j]; 141 memcpy(pti->pty_pn, buf, sizeof(buf)); 142 buf[5] = 't'; 143 memcpy(pti->pty_sn, buf, sizeof(buf)); 144 } 145 146 /* 147 * Allocate and zero array of nelem elements. 148 */ 149 struct pt_softc ** 150 ptyarralloc(int nelem) 151 { 152 struct pt_softc **pt; 153 154 pt = mallocarray(nelem, sizeof(struct pt_softc *), M_DEVBUF, 155 M_WAITOK|M_ZERO); 156 return pt; 157 } 158 159 /* 160 * Check if the minor is correct and ensure necessary structures 161 * are properly allocated. 162 */ 163 int 164 check_pty(int dev) 165 { 166 struct pt_softc *pti; 167 int minor = minor(dev); 168 169 rw_enter_write(&pt_softc_lock); 170 if (minor >= npty) { 171 struct pt_softc **newpt; 172 int newnpty; 173 174 /* check if the requested pty can be granted */ 175 if (minor >= maxptys) 176 goto limit_reached; 177 178 /* grow pty array by powers of two, up to maxptys */ 179 for (newnpty = npty; newnpty <= minor; newnpty *= 2) 180 ; 181 182 if (newnpty > maxptys) 183 newnpty = maxptys; 184 newpt = ptyarralloc(newnpty); 185 186 memcpy(newpt, pt_softc, npty * sizeof(struct pt_softc *)); 187 free(pt_softc, M_DEVBUF, npty * sizeof(struct pt_softc *)); 188 pt_softc = newpt; 189 npty = newnpty; 190 } 191 192 /* 193 * If the entry is not yet allocated, allocate one. 194 */ 195 if (!pt_softc[minor]) { 196 pti = malloc(sizeof(struct pt_softc), M_DEVBUF, 197 M_WAITOK|M_ZERO); 198 pti->pt_tty = ttymalloc(1000000); 199 pti->pt_tty->t_dev = dev; 200 ptydevname(minor, pti); 201 pt_softc[minor] = pti; 202 } 203 rw_exit_write(&pt_softc_lock); 204 return (0); 205 limit_reached: 206 rw_exit_write(&pt_softc_lock); 207 tablefull("pty"); 208 return (ENXIO); 209 } 210 211 /* 212 * Establish n (or default if n is 1) ptys in the system. 213 */ 214 void 215 ptyattach(int n) 216 { 217 /* maybe should allow 0 => none? */ 218 if (n <= 1) 219 n = NPTY_MIN; 220 pt_softc = ptyarralloc(n); 221 npty = n; 222 223 /* 224 * If we have pty, we need ptm too. 225 */ 226 ptmattach(1); 227 } 228 229 int 230 ptsopen(dev_t dev, int flag, int devtype, struct proc *p) 231 { 232 struct pt_softc *pti; 233 struct tty *tp; 234 int error; 235 236 if ((error = check_pty(dev))) 237 return (error); 238 239 pti = pt_softc[minor(dev)]; 240 tp = pti->pt_tty; 241 if ((tp->t_state & TS_ISOPEN) == 0) { 242 tp->t_state |= TS_WOPEN; 243 ttychars(tp); /* Set up default chars */ 244 tp->t_iflag = TTYDEF_IFLAG; 245 tp->t_oflag = TTYDEF_OFLAG; 246 tp->t_lflag = TTYDEF_LFLAG; 247 tp->t_cflag = TTYDEF_CFLAG; 248 tp->t_ispeed = tp->t_ospeed = B115200; 249 ttsetwater(tp); /* would be done in xxparam() */ 250 } else if (tp->t_state & TS_XCLUDE && suser(p) != 0) 251 return (EBUSY); 252 if (tp->t_oproc) /* Ctrlr still around. */ 253 tp->t_state |= TS_CARR_ON; 254 while ((tp->t_state & TS_CARR_ON) == 0) { 255 tp->t_state |= TS_WOPEN; 256 if (flag & FNONBLOCK) 257 break; 258 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen); 259 if (error) 260 return (error); 261 } 262 error = (*linesw[tp->t_line].l_open)(dev, tp, p); 263 ptcwakeup(tp, FREAD|FWRITE); 264 return (error); 265 } 266 267 int 268 ptsclose(dev_t dev, int flag, int mode, struct proc *p) 269 { 270 struct pt_softc *pti = pt_softc[minor(dev)]; 271 struct tty *tp = pti->pt_tty; 272 int error; 273 274 error = (*linesw[tp->t_line].l_close)(tp, flag, p); 275 error |= ttyclose(tp); 276 ptcwakeup(tp, FREAD|FWRITE); 277 return (error); 278 } 279 280 int 281 ptsread(dev_t dev, struct uio *uio, int flag) 282 { 283 struct proc *p = curproc; 284 struct process *pr = p->p_p; 285 struct pt_softc *pti = pt_softc[minor(dev)]; 286 struct tty *tp = pti->pt_tty; 287 int error = 0; 288 289 again: 290 if (pti->pt_flags & PF_REMOTE) { 291 while (isbackground(pr, tp)) { 292 if (sigismasked(p, SIGTTIN) || 293 pr->ps_pgrp->pg_jobc == 0 || 294 pr->ps_flags & PS_PPWAIT) 295 return (EIO); 296 pgsignal(pr->ps_pgrp, SIGTTIN, 1); 297 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg); 298 if (error) 299 return (error); 300 } 301 if (tp->t_canq.c_cc == 0) { 302 if (flag & IO_NDELAY) 303 return (EWOULDBLOCK); 304 error = ttysleep(tp, &tp->t_canq, 305 TTIPRI | PCATCH, ttyin); 306 if (error) 307 return (error); 308 goto again; 309 } 310 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 311 if (ureadc(getc(&tp->t_canq), uio) < 0) { 312 error = EFAULT; 313 break; 314 } 315 if (tp->t_canq.c_cc == 1) 316 (void) getc(&tp->t_canq); 317 if (tp->t_canq.c_cc) 318 return (error); 319 } else 320 if (tp->t_oproc) 321 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 322 ptcwakeup(tp, FWRITE); 323 return (error); 324 } 325 326 /* 327 * Write to pseudo-tty. 328 * Wakeups of controlling tty will happen 329 * indirectly, when tty driver calls ptsstart. 330 */ 331 int 332 ptswrite(dev_t dev, struct uio *uio, int flag) 333 { 334 struct pt_softc *pti = pt_softc[minor(dev)]; 335 struct tty *tp = pti->pt_tty; 336 337 if (tp->t_oproc == 0) 338 return (EIO); 339 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 340 } 341 342 /* 343 * Start output on pseudo-tty. 344 * Wake up process polling or sleeping for input from controlling tty. 345 */ 346 void 347 ptsstart(struct tty *tp) 348 { 349 struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; 350 351 if (tp->t_state & TS_TTSTOP) 352 return; 353 if (pti->pt_flags & PF_STOPPED) { 354 pti->pt_flags &= ~PF_STOPPED; 355 pti->pt_send = TIOCPKT_START; 356 } 357 ptcwakeup(tp, FREAD); 358 } 359 360 int 361 ptsstop(struct tty *tp, int flush) 362 { 363 struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; 364 int flag; 365 366 /* note: FLUSHREAD and FLUSHWRITE already ok */ 367 if (flush == 0) { 368 flush = TIOCPKT_STOP; 369 pti->pt_flags |= PF_STOPPED; 370 } else 371 pti->pt_flags &= ~PF_STOPPED; 372 pti->pt_send |= flush; 373 /* change of perspective */ 374 flag = 0; 375 if (flush & FREAD) 376 flag |= FWRITE; 377 if (flush & FWRITE) 378 flag |= FREAD; 379 ptcwakeup(tp, flag); 380 return 0; 381 } 382 383 void 384 ptcwakeup(struct tty *tp, int flag) 385 { 386 struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; 387 388 if (flag & FREAD) { 389 selwakeup(&pti->pt_selr); 390 wakeup(&tp->t_outq.c_cf); 391 } 392 if (flag & FWRITE) { 393 selwakeup(&pti->pt_selw); 394 wakeup(&tp->t_rawq.c_cf); 395 } 396 } 397 398 int ptcopen(dev_t, int, int, struct proc *); 399 400 int 401 ptcopen(dev_t dev, int flag, int devtype, struct proc *p) 402 { 403 struct pt_softc *pti; 404 struct tty *tp; 405 int error; 406 407 if ((error = check_pty(dev))) 408 return (error); 409 410 pti = pt_softc[minor(dev)]; 411 tp = pti->pt_tty; 412 if (tp->t_oproc) 413 return (EIO); 414 tp->t_oproc = ptsstart; 415 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 416 tp->t_lflag &= ~EXTPROC; 417 pti->pt_flags = 0; 418 pti->pt_send = 0; 419 pti->pt_ucntl = 0; 420 return (0); 421 } 422 423 int 424 ptcclose(dev_t dev, int flag, int devtype, struct proc *p) 425 { 426 struct pt_softc *pti = pt_softc[minor(dev)]; 427 struct tty *tp = pti->pt_tty; 428 429 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 430 tp->t_state &= ~TS_CARR_ON; 431 tp->t_oproc = 0; /* mark closed */ 432 return (0); 433 } 434 435 int 436 ptcread(dev_t dev, struct uio *uio, int flag) 437 { 438 struct pt_softc *pti = pt_softc[minor(dev)]; 439 struct tty *tp = pti->pt_tty; 440 char buf[BUFSIZ]; 441 int error = 0, cc, bufcc = 0; 442 443 /* 444 * We want to block until the slave 445 * is open, and there's something to read; 446 * but if we lost the slave or we're NBIO, 447 * then return the appropriate error instead. 448 */ 449 for (;;) { 450 if (tp->t_state & TS_ISOPEN) { 451 if (pti->pt_flags & PF_PKT && pti->pt_send) { 452 error = ureadc((int)pti->pt_send, uio); 453 if (error) 454 return (error); 455 if (pti->pt_send & TIOCPKT_IOCTL) { 456 cc = MIN(uio->uio_resid, 457 sizeof(tp->t_termios)); 458 error = uiomove(&tp->t_termios, cc, uio); 459 if (error) 460 return (error); 461 } 462 pti->pt_send = 0; 463 return (0); 464 } 465 if (pti->pt_flags & PF_UCNTL && pti->pt_ucntl) { 466 error = ureadc((int)pti->pt_ucntl, uio); 467 if (error) 468 return (error); 469 pti->pt_ucntl = 0; 470 return (0); 471 } 472 if (tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) 473 break; 474 } 475 if ((tp->t_state & TS_CARR_ON) == 0) 476 return (0); /* EOF */ 477 if (flag & IO_NDELAY) 478 return (EWOULDBLOCK); 479 error = tsleep_nsec(&tp->t_outq.c_cf, TTIPRI | PCATCH, ttyin, 480 INFSLP); 481 if (error) 482 return (error); 483 } 484 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 485 error = ureadc(0, uio); 486 while (uio->uio_resid > 0 && error == 0) { 487 cc = MIN(uio->uio_resid, BUFSIZ); 488 cc = q_to_b(&tp->t_outq, buf, cc); 489 if (cc > bufcc) 490 bufcc = cc; 491 if (cc <= 0) 492 break; 493 error = uiomove(buf, cc, uio); 494 } 495 ttwakeupwr(tp); 496 if (bufcc) 497 explicit_bzero(buf, bufcc); 498 return (error); 499 } 500 501 502 int 503 ptcwrite(dev_t dev, struct uio *uio, int flag) 504 { 505 struct pt_softc *pti = pt_softc[minor(dev)]; 506 struct tty *tp = pti->pt_tty; 507 u_char *cp = NULL; 508 int cc = 0, bufcc = 0; 509 u_char buf[BUFSIZ]; 510 size_t cnt = 0; 511 int error = 0; 512 513 again: 514 if ((tp->t_state & TS_ISOPEN) == 0) 515 goto block; 516 if (pti->pt_flags & PF_REMOTE) { 517 if (tp->t_canq.c_cc) 518 goto block; 519 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG(tp) - 1) { 520 if (cc == 0) { 521 cc = MIN(uio->uio_resid, BUFSIZ); 522 cc = min(cc, TTYHOG(tp) - 1 - tp->t_canq.c_cc); 523 if (cc > bufcc) 524 bufcc = cc; 525 cp = buf; 526 error = uiomove(cp, cc, uio); 527 if (error) 528 goto done; 529 /* check again for safety */ 530 if ((tp->t_state & TS_ISOPEN) == 0) { 531 error = EIO; 532 goto done; 533 } 534 } 535 if (cc) 536 (void) b_to_q((char *)cp, cc, &tp->t_canq); 537 cc = 0; 538 } 539 (void) putc(0, &tp->t_canq); 540 ttwakeup(tp); 541 wakeup(&tp->t_canq); 542 goto done; 543 } 544 do { 545 if (cc == 0) { 546 cc = MIN(uio->uio_resid, BUFSIZ); 547 if (cc > bufcc) 548 bufcc = cc; 549 cp = buf; 550 error = uiomove(cp, cc, uio); 551 if (error) 552 goto done; 553 /* check again for safety */ 554 if ((tp->t_state & TS_ISOPEN) == 0) { 555 error = EIO; 556 goto done; 557 } 558 } 559 bufcc = cc; 560 while (cc > 0) { 561 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG(tp) - 2 && 562 (tp->t_canq.c_cc > 0 || !ISSET(tp->t_lflag, ICANON))) { 563 wakeup(&tp->t_rawq); 564 goto block; 565 } 566 if ((*linesw[tp->t_line].l_rint)(*cp++, tp) == 1 && 567 tsleep(tp, TTIPRI | PCATCH, "ttyretype", 1) == EINTR) 568 goto interrupt; 569 cnt++; 570 cc--; 571 } 572 cc = 0; 573 } while (uio->uio_resid > 0); 574 goto done; 575 block: 576 /* 577 * Come here to wait for slave to open, for space 578 * in outq, or space in rawq. 579 */ 580 if ((tp->t_state & TS_CARR_ON) == 0) { 581 error = EIO; 582 goto done; 583 } 584 if (flag & IO_NDELAY) { 585 /* adjust for data copied in but not written */ 586 uio->uio_resid += cc; 587 if (cnt == 0) 588 error = EWOULDBLOCK; 589 goto done; 590 } 591 error = tsleep_nsec(&tp->t_rawq.c_cf, TTOPRI | PCATCH, ttyout, INFSLP); 592 if (error == 0) 593 goto again; 594 595 interrupt: 596 /* adjust for data copied in but not written */ 597 uio->uio_resid += cc; 598 done: 599 if (bufcc) 600 explicit_bzero(buf, bufcc); 601 return (error); 602 } 603 604 int 605 ptcpoll(dev_t dev, int events, struct proc *p) 606 { 607 struct pt_softc *pti = pt_softc[minor(dev)]; 608 struct tty *tp = pti->pt_tty; 609 int revents = 0, s; 610 611 if (!ISSET(tp->t_state, TS_ISOPEN) && ISSET(tp->t_state, TS_CARR_ON)) 612 goto notopen; 613 614 if (events & (POLLIN | POLLRDNORM)) { 615 /* 616 * Need to protect access to t_outq 617 */ 618 s = spltty(); 619 if ((tp->t_outq.c_cc && !ISSET(tp->t_state, TS_TTSTOP)) || 620 ((pti->pt_flags & PF_PKT) && pti->pt_send) || 621 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) 622 revents |= events & (POLLIN | POLLRDNORM); 623 splx(s); 624 } 625 /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */ 626 if (!ISSET(tp->t_state, TS_CARR_ON)) { 627 revents |= POLLHUP; 628 } else if (events & (POLLOUT | POLLWRNORM)) { 629 if ((pti->pt_flags & PF_REMOTE) ? 630 (tp->t_canq.c_cc == 0) : 631 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG(tp) - 2) || 632 (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON)))) 633 revents |= events & (POLLOUT | POLLWRNORM); 634 } 635 if (events & (POLLPRI | POLLRDBAND)) { 636 /* If in packet or user control mode, check for data. */ 637 if (((pti->pt_flags & PF_PKT) && pti->pt_send) || 638 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) 639 revents |= events & (POLLPRI | POLLRDBAND); 640 } 641 642 if (revents == 0) { 643 notopen: 644 if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) 645 selrecord(p, &pti->pt_selr); 646 if (events & (POLLOUT | POLLWRNORM)) 647 selrecord(p, &pti->pt_selw); 648 } 649 650 return (revents); 651 } 652 653 void 654 filt_ptcrdetach(struct knote *kn) 655 { 656 struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; 657 int s; 658 659 s = spltty(); 660 klist_remove_locked(&pti->pt_selr.si_note, kn); 661 splx(s); 662 } 663 664 int 665 filt_ptcread(struct knote *kn, long hint) 666 { 667 struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; 668 struct tty *tp; 669 670 tp = pti->pt_tty; 671 kn->kn_data = 0; 672 673 if (kn->kn_sfflags & NOTE_OOB) { 674 /* If in packet or user control mode, check for data. */ 675 if (((pti->pt_flags & PF_PKT) && pti->pt_send) || 676 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) { 677 kn->kn_fflags |= NOTE_OOB; 678 kn->kn_data = 1; 679 return (1); 680 } 681 return (0); 682 } 683 if (ISSET(tp->t_state, TS_ISOPEN)) { 684 if (!ISSET(tp->t_state, TS_TTSTOP)) 685 kn->kn_data = tp->t_outq.c_cc; 686 if (((pti->pt_flags & PF_PKT) && pti->pt_send) || 687 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) 688 kn->kn_data++; 689 } 690 691 if (!ISSET(tp->t_state, TS_CARR_ON)) { 692 kn->kn_flags |= EV_EOF; 693 if (kn->kn_flags & __EV_POLL) 694 kn->kn_flags |= __EV_HUP; 695 return (1); 696 } 697 698 return (kn->kn_data > 0); 699 } 700 701 void 702 filt_ptcwdetach(struct knote *kn) 703 { 704 struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; 705 int s; 706 707 s = spltty(); 708 klist_remove_locked(&pti->pt_selw.si_note, kn); 709 splx(s); 710 } 711 712 int 713 filt_ptcwrite(struct knote *kn, long hint) 714 { 715 struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; 716 struct tty *tp; 717 718 tp = pti->pt_tty; 719 kn->kn_data = 0; 720 721 if (ISSET(tp->t_state, TS_ISOPEN)) { 722 if (ISSET(pti->pt_flags, PF_REMOTE)) { 723 if (tp->t_canq.c_cc == 0) 724 kn->kn_data = tp->t_canq.c_cn; 725 } else if ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG(tp)-2) || 726 (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON))) 727 kn->kn_data = tp->t_canq.c_cn - 728 (tp->t_rawq.c_cc + tp->t_canq.c_cc); 729 } 730 731 return (kn->kn_data > 0); 732 } 733 734 const struct filterops ptcread_filtops = { 735 .f_flags = FILTEROP_ISFD, 736 .f_attach = NULL, 737 .f_detach = filt_ptcrdetach, 738 .f_event = filt_ptcread, 739 }; 740 741 const struct filterops ptcwrite_filtops = { 742 .f_flags = FILTEROP_ISFD, 743 .f_attach = NULL, 744 .f_detach = filt_ptcwdetach, 745 .f_event = filt_ptcwrite, 746 }; 747 748 const struct filterops ptcexcept_filtops = { 749 .f_flags = FILTEROP_ISFD, 750 .f_attach = NULL, 751 .f_detach = filt_ptcrdetach, 752 .f_event = filt_ptcread, 753 }; 754 755 int 756 ptckqfilter(dev_t dev, struct knote *kn) 757 { 758 struct pt_softc *pti = pt_softc[minor(dev)]; 759 struct klist *klist; 760 int s; 761 762 switch (kn->kn_filter) { 763 case EVFILT_READ: 764 klist = &pti->pt_selr.si_note; 765 kn->kn_fop = &ptcread_filtops; 766 break; 767 case EVFILT_WRITE: 768 klist = &pti->pt_selw.si_note; 769 kn->kn_fop = &ptcwrite_filtops; 770 break; 771 case EVFILT_EXCEPT: 772 klist = &pti->pt_selr.si_note; 773 kn->kn_fop = &ptcexcept_filtops; 774 break; 775 default: 776 return (EINVAL); 777 } 778 779 kn->kn_hook = (caddr_t)pti; 780 781 s = spltty(); 782 klist_insert_locked(klist, kn); 783 splx(s); 784 785 return (0); 786 } 787 788 struct tty * 789 ptytty(dev_t dev) 790 { 791 struct pt_softc *pti = pt_softc[minor(dev)]; 792 struct tty *tp = pti->pt_tty; 793 794 return (tp); 795 } 796 797 int 798 ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 799 { 800 struct pt_softc *pti = pt_softc[minor(dev)]; 801 struct tty *tp = pti->pt_tty; 802 u_char *cc = tp->t_cc; 803 int stop, error; 804 805 /* 806 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 807 * ttywflush(tp) will hang if there are characters in the outq. 808 */ 809 if (cmd == TIOCEXT) { 810 /* 811 * When the EXTPROC bit is being toggled, we need 812 * to send an TIOCPKT_IOCTL if the packet driver 813 * is turned on. 814 */ 815 if (*(int *)data) { 816 if (pti->pt_flags & PF_PKT) { 817 pti->pt_send |= TIOCPKT_IOCTL; 818 ptcwakeup(tp, FREAD); 819 } 820 tp->t_lflag |= EXTPROC; 821 } else { 822 if ((tp->t_lflag & EXTPROC) && 823 (pti->pt_flags & PF_PKT)) { 824 pti->pt_send |= TIOCPKT_IOCTL; 825 ptcwakeup(tp, FREAD); 826 } 827 tp->t_lflag &= ~EXTPROC; 828 } 829 return(0); 830 } else if (cdevsw[major(dev)].d_open == ptcopen) 831 switch (cmd) { 832 833 case TIOCGPGRP: 834 /* 835 * We avoid calling ttioctl on the controller since, 836 * in that case, tp must be the controlling terminal. 837 */ 838 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 839 return (0); 840 841 case TIOCPKT: 842 if (*(int *)data) { 843 if (pti->pt_flags & PF_UCNTL) 844 return (EINVAL); 845 pti->pt_flags |= PF_PKT; 846 } else 847 pti->pt_flags &= ~PF_PKT; 848 return (0); 849 850 case TIOCUCNTL: 851 if (*(int *)data) { 852 if (pti->pt_flags & PF_PKT) 853 return (EINVAL); 854 pti->pt_flags |= PF_UCNTL; 855 } else 856 pti->pt_flags &= ~PF_UCNTL; 857 return (0); 858 859 case TIOCREMOTE: 860 if (*(int *)data) 861 pti->pt_flags |= PF_REMOTE; 862 else 863 pti->pt_flags &= ~PF_REMOTE; 864 ttyflush(tp, FREAD|FWRITE); 865 return (0); 866 867 case TIOCSETD: 868 case TIOCSETA: 869 case TIOCSETAW: 870 case TIOCSETAF: 871 ndflush(&tp->t_outq, tp->t_outq.c_cc); 872 break; 873 874 case TIOCSIG: 875 if (*(unsigned int *)data >= NSIG || 876 *(unsigned int *)data == 0) 877 return(EINVAL); 878 if ((tp->t_lflag & NOFLSH) == 0) 879 ttyflush(tp, FREAD|FWRITE); 880 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 881 if ((*(unsigned int *)data == SIGINFO) && 882 ((tp->t_lflag & NOKERNINFO) == 0)) 883 ttyinfo(tp); 884 return (0); 885 886 case FIONREAD: 887 /* 888 * FIONREAD on the master side must return the amount 889 * in the output queue rather than the input. 890 */ 891 *(int *)data = tp->t_outq.c_cc; 892 return (0); 893 } 894 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 895 if (error < 0) 896 error = ttioctl(tp, cmd, data, flag, p); 897 if (error < 0) { 898 /* 899 * Translate TIOCSBRK/TIOCCBRK to user mode ioctls to 900 * let the master interpret BREAK conditions. 901 */ 902 switch (cmd) { 903 case TIOCSBRK: 904 cmd = UIOCCMD(TIOCUCNTL_SBRK); 905 break; 906 case TIOCCBRK: 907 cmd = UIOCCMD(TIOCUCNTL_CBRK); 908 break; 909 default: 910 break; 911 } 912 if (pti->pt_flags & PF_UCNTL && 913 (cmd & ~0xff) == UIOCCMD(0)) { 914 if (cmd & 0xff) { 915 pti->pt_ucntl = (u_char)cmd; 916 ptcwakeup(tp, FREAD); 917 } 918 return (0); 919 } 920 error = ENOTTY; 921 } 922 /* 923 * If external processing and packet mode send ioctl packet. 924 */ 925 if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) { 926 switch (cmd) { 927 case TIOCSETA: 928 case TIOCSETAW: 929 case TIOCSETAF: 930 pti->pt_send |= TIOCPKT_IOCTL; 931 ptcwakeup(tp, FREAD); 932 default: 933 break; 934 } 935 } 936 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) && 937 CCEQ(cc[VSTART], CTRL('q')); 938 if (pti->pt_flags & PF_NOSTOP) { 939 if (stop) { 940 pti->pt_send &= ~TIOCPKT_NOSTOP; 941 pti->pt_send |= TIOCPKT_DOSTOP; 942 pti->pt_flags &= ~PF_NOSTOP; 943 ptcwakeup(tp, FREAD); 944 } 945 } else { 946 if (!stop) { 947 pti->pt_send &= ~TIOCPKT_DOSTOP; 948 pti->pt_send |= TIOCPKT_NOSTOP; 949 pti->pt_flags |= PF_NOSTOP; 950 ptcwakeup(tp, FREAD); 951 } 952 } 953 return (error); 954 } 955 956 /* 957 * Return pty-related information. 958 */ 959 int 960 sysctl_pty(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 961 size_t newlen) 962 { 963 if (namelen != 1) 964 return (ENOTDIR); 965 966 switch (name[0]) { 967 default: 968 return (EOPNOTSUPP); 969 } 970 /* NOTREACHED */ 971 } 972 973 /* 974 * Check if a pty is free to use. 975 */ 976 static int 977 pty_isfree_locked(int minor) 978 { 979 struct pt_softc *pt = pt_softc[minor]; 980 981 return (pt == NULL || pt->pt_tty == NULL || 982 pt->pt_tty->t_oproc == NULL); 983 } 984 985 static int 986 pty_isfree(int minor) 987 { 988 int isfree; 989 990 rw_enter_read(&pt_softc_lock); 991 isfree = pty_isfree_locked(minor); 992 rw_exit_read(&pt_softc_lock); 993 return(isfree); 994 } 995 996 dev_t 997 pty_getfree(void) 998 { 999 int i; 1000 1001 rw_enter_read(&pt_softc_lock); 1002 for (i = 0; i < npty; i++) { 1003 if (pty_isfree_locked(i)) 1004 break; 1005 } 1006 rw_exit_read(&pt_softc_lock); 1007 return (makedev(pts_major, i)); 1008 } 1009 1010 /* 1011 * Hacked up version of vn_open. We _only_ handle ptys and only open 1012 * them with FREAD|FWRITE and never deal with creat or stuff like that. 1013 * 1014 * We need it because we have to fake up root credentials to open the pty. 1015 */ 1016 static int 1017 ptm_vn_open(struct nameidata *ndp) 1018 { 1019 struct proc *p = ndp->ni_cnd.cn_proc; 1020 struct ucred *cred; 1021 struct vattr vattr; 1022 struct vnode *vp; 1023 int error; 1024 1025 if ((error = namei(ndp)) != 0) 1026 return (error); 1027 vp = ndp->ni_vp; 1028 if (vp->v_type != VCHR) { 1029 error = EINVAL; 1030 goto bad; 1031 } 1032 1033 /* 1034 * Get us a fresh cred with root privileges. 1035 */ 1036 cred = crget(); 1037 error = VOP_OPEN(vp, FREAD|FWRITE, cred, p); 1038 if (!error) { 1039 /* update atime/mtime */ 1040 VATTR_NULL(&vattr); 1041 getnanotime(&vattr.va_atime); 1042 vattr.va_mtime = vattr.va_atime; 1043 vattr.va_vaflags |= VA_UTIMES_NULL; 1044 (void)VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1045 } 1046 crfree(cred); 1047 1048 if (error) 1049 goto bad; 1050 1051 vp->v_writecount++; 1052 1053 return (0); 1054 bad: 1055 vput(vp); 1056 return (error); 1057 } 1058 1059 void 1060 ptmattach(int n) 1061 { 1062 /* find the major and minor of the pty devices */ 1063 int i; 1064 1065 for (i = 0; i < nchrdev; i++) 1066 if (cdevsw[i].d_open == ptsopen) 1067 break; 1068 1069 if (i == nchrdev) 1070 panic("ptmattach: Can't find pty slave in cdevsw"); 1071 1072 pts_major = i; 1073 } 1074 1075 int 1076 ptmopen(dev_t dev, int flag, int mode, struct proc *p) 1077 { 1078 return(0); 1079 } 1080 1081 1082 int 1083 ptmclose(dev_t dev, int flag, int mode, struct proc *p) 1084 { 1085 return (0); 1086 } 1087 1088 int 1089 ptmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 1090 { 1091 dev_t newdev; 1092 struct pt_softc * pti; 1093 struct nameidata cnd, snd; 1094 struct filedesc *fdp = p->p_fd; 1095 struct file *cfp = NULL, *sfp = NULL; 1096 int cindx, sindx, error; 1097 uid_t uid; 1098 gid_t gid; 1099 struct vattr vattr; 1100 struct ucred *cred; 1101 struct ptmget *ptm = (struct ptmget *)data; 1102 1103 switch (cmd) { 1104 case PTMGET: 1105 fdplock(fdp); 1106 /* Grab two filedescriptors. */ 1107 if ((error = falloc(p, &cfp, &cindx)) != 0) { 1108 fdpunlock(fdp); 1109 break; 1110 } 1111 if ((error = falloc(p, &sfp, &sindx)) != 0) { 1112 fdremove(fdp, cindx); 1113 fdpunlock(fdp); 1114 closef(cfp, p); 1115 break; 1116 } 1117 fdpunlock(fdp); 1118 1119 retry: 1120 /* Find and open a free master pty. */ 1121 newdev = pty_getfree(); 1122 if ((error = check_pty(newdev))) 1123 goto bad; 1124 pti = pt_softc[minor(newdev)]; 1125 NDINIT(&cnd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, 1126 pti->pty_pn, p); 1127 cnd.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH; 1128 if ((error = ptm_vn_open(&cnd)) != 0) { 1129 /* 1130 * Check if the master open failed because we lost 1131 * the race to grab it. 1132 */ 1133 if (error == EIO && !pty_isfree(minor(newdev))) 1134 goto retry; 1135 goto bad; 1136 } 1137 cfp->f_flag = FREAD|FWRITE; 1138 cfp->f_type = DTYPE_VNODE; 1139 cfp->f_ops = &vnops; 1140 cfp->f_data = (caddr_t) cnd.ni_vp; 1141 VOP_UNLOCK(cnd.ni_vp); 1142 1143 /* 1144 * Open the slave. 1145 * namei -> setattr -> unlock -> revoke -> vrele -> 1146 * namei -> open -> unlock 1147 * Three stage rocket: 1148 * 1. Change the owner and permissions on the slave. 1149 * 2. Revoke all the users of the slave. 1150 * 3. open the slave. 1151 */ 1152 NDINIT(&snd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, 1153 pti->pty_sn, p); 1154 snd.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH; 1155 snd.ni_unveil = UNVEIL_READ | UNVEIL_WRITE; 1156 if ((error = namei(&snd)) != 0) 1157 goto bad; 1158 if ((snd.ni_vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 1159 gid = tty_gid; 1160 /* get real uid */ 1161 uid = p->p_ucred->cr_ruid; 1162 1163 VATTR_NULL(&vattr); 1164 vattr.va_uid = uid; 1165 vattr.va_gid = gid; 1166 vattr.va_mode = (S_IRUSR|S_IWUSR|S_IWGRP) & ALLPERMS; 1167 /* Get a fake cred to pretend we're root. */ 1168 cred = crget(); 1169 error = VOP_SETATTR(snd.ni_vp, &vattr, cred, p); 1170 crfree(cred); 1171 if (error) { 1172 vput(snd.ni_vp); 1173 goto bad; 1174 } 1175 } 1176 VOP_UNLOCK(snd.ni_vp); 1177 if (snd.ni_vp->v_usecount > 1 || 1178 (snd.ni_vp->v_flag & (VALIASED))) 1179 VOP_REVOKE(snd.ni_vp, REVOKEALL); 1180 1181 /* 1182 * The vnode is useless after the revoke, we need to 1183 * namei again. 1184 */ 1185 vrele(snd.ni_vp); 1186 1187 NDINIT(&snd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, 1188 pti->pty_sn, p); 1189 snd.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH; 1190 snd.ni_unveil= UNVEIL_READ | UNVEIL_WRITE; 1191 /* now open it */ 1192 if ((error = ptm_vn_open(&snd)) != 0) 1193 goto bad; 1194 sfp->f_flag = FREAD|FWRITE; 1195 sfp->f_type = DTYPE_VNODE; 1196 sfp->f_ops = &vnops; 1197 sfp->f_data = (caddr_t) snd.ni_vp; 1198 VOP_UNLOCK(snd.ni_vp); 1199 1200 /* now, put the indexen and names into struct ptmget */ 1201 ptm->cfd = cindx; 1202 ptm->sfd = sindx; 1203 memcpy(ptm->cn, pti->pty_pn, sizeof(pti->pty_pn)); 1204 memcpy(ptm->sn, pti->pty_sn, sizeof(pti->pty_sn)); 1205 1206 /* insert files now that we've passed all errors */ 1207 fdplock(fdp); 1208 fdinsert(fdp, cindx, 0, cfp); 1209 fdinsert(fdp, sindx, 0, sfp); 1210 fdpunlock(fdp); 1211 FRELE(cfp, p); 1212 FRELE(sfp, p); 1213 break; 1214 default: 1215 error = EINVAL; 1216 break; 1217 } 1218 return (error); 1219 bad: 1220 fdplock(fdp); 1221 fdremove(fdp, cindx); 1222 fdremove(fdp, sindx); 1223 fdpunlock(fdp); 1224 closef(cfp, p); 1225 closef(sfp, p); 1226 return (error); 1227 } 1228