1 /* $OpenBSD: tty_pty.c,v 1.115 2024/11/05 06:03:19 jsg 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/pledge.h> 59 #include <sys/rwlock.h> 60 61 #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 62 63 /* 64 * pts == /dev/tty[p-zP-T][0-9a-zA-Z] 65 * ptc == /dev/pty[p-zP-T][0-9a-zA-Z] 66 */ 67 68 /* XXX this needs to come from somewhere sane, and work with MAKEDEV */ 69 #define TTY_LETTERS "pqrstuvwxyzPQRST" 70 #define TTY_SUFFIX "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 71 72 static int pts_major; 73 74 struct pt_softc { 75 struct tty *pt_tty; 76 int pt_flags; 77 struct selinfo pt_selr, pt_selw; 78 u_char pt_send; 79 u_char pt_ucntl; 80 char pty_pn[11]; 81 char pty_sn[11]; 82 }; 83 84 #define NPTY_MIN 8 /* number of initial ptys */ 85 #define NPTY_MAX 992 /* maximum number of ptys supported */ 86 87 static struct pt_softc **pt_softc = NULL; /* pty array */ 88 static int npty = 0; /* size of pty array */ 89 static int maxptys = NPTY_MAX; /* maximum number of ptys */ 90 /* for pty array */ 91 struct rwlock pt_softc_lock = RWLOCK_INITIALIZER("ptarrlk"); 92 93 #define PF_PKT 0x08 /* packet mode */ 94 #define PF_STOPPED 0x10 /* user told stopped */ 95 #define PF_REMOTE 0x20 /* remote and flow controlled input */ 96 #define PF_NOSTOP 0x40 97 #define PF_UCNTL 0x80 /* user control mode */ 98 99 void ptyattach(int); 100 void ptcwakeup(struct tty *, int); 101 struct tty *ptytty(dev_t); 102 void ptsstart(struct tty *); 103 int sysctl_pty(int *, u_int, void *, size_t *, void *, size_t); 104 105 void filt_ptcrdetach(struct knote *); 106 int filt_ptcread(struct knote *, long); 107 void filt_ptcwdetach(struct knote *); 108 int filt_ptcwrite(struct knote *, long); 109 int filt_ptcexcept(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 == NULL) 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 = NULL; /* 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 void 605 filt_ptcrdetach(struct knote *kn) 606 { 607 struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; 608 int s; 609 610 s = spltty(); 611 klist_remove_locked(&pti->pt_selr.si_note, kn); 612 splx(s); 613 } 614 615 int 616 filt_ptcread(struct knote *kn, long hint) 617 { 618 struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; 619 struct tty *tp; 620 int active; 621 622 tp = pti->pt_tty; 623 kn->kn_data = 0; 624 625 if (ISSET(tp->t_state, TS_ISOPEN)) { 626 if (!ISSET(tp->t_state, TS_TTSTOP)) 627 kn->kn_data = tp->t_outq.c_cc; 628 if (((pti->pt_flags & PF_PKT) && pti->pt_send) || 629 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) 630 kn->kn_data++; 631 } 632 active = (kn->kn_data > 0); 633 634 if (!ISSET(tp->t_state, TS_CARR_ON)) { 635 kn->kn_flags |= EV_EOF; 636 if (kn->kn_flags & __EV_POLL) 637 kn->kn_flags |= __EV_HUP; 638 active = 1; 639 } else { 640 kn->kn_flags &= ~(EV_EOF | __EV_HUP); 641 } 642 643 return (active); 644 } 645 646 void 647 filt_ptcwdetach(struct knote *kn) 648 { 649 struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; 650 int s; 651 652 s = spltty(); 653 klist_remove_locked(&pti->pt_selw.si_note, kn); 654 splx(s); 655 } 656 657 int 658 filt_ptcwrite(struct knote *kn, long hint) 659 { 660 struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; 661 struct tty *tp; 662 int active; 663 664 tp = pti->pt_tty; 665 kn->kn_data = 0; 666 667 if (ISSET(tp->t_state, TS_ISOPEN)) { 668 if (ISSET(pti->pt_flags, PF_REMOTE)) { 669 if (tp->t_canq.c_cc == 0) 670 kn->kn_data = tp->t_canq.c_cn; 671 } else if ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG(tp)-2) || 672 (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON))) 673 kn->kn_data = tp->t_canq.c_cn - 674 (tp->t_rawq.c_cc + tp->t_canq.c_cc); 675 } 676 active = (kn->kn_data > 0); 677 678 /* Write-side HUP condition is only for poll(2) and select(2). */ 679 if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) { 680 if (!ISSET(tp->t_state, TS_CARR_ON)) { 681 kn->kn_flags |= __EV_HUP; 682 active = 1; 683 } else { 684 kn->kn_flags &= ~__EV_HUP; 685 } 686 } 687 688 return (active); 689 } 690 691 int 692 filt_ptcexcept(struct knote *kn, long hint) 693 { 694 struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; 695 struct tty *tp; 696 int active = 0; 697 698 tp = pti->pt_tty; 699 700 if (kn->kn_sfflags & NOTE_OOB) { 701 /* If in packet or user control mode, check for data. */ 702 if (((pti->pt_flags & PF_PKT) && pti->pt_send) || 703 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) { 704 kn->kn_fflags |= NOTE_OOB; 705 kn->kn_data = 1; 706 active = 1; 707 } 708 } 709 710 if (kn->kn_flags & __EV_POLL) { 711 if (!ISSET(tp->t_state, TS_CARR_ON)) { 712 kn->kn_flags |= __EV_HUP; 713 active = 1; 714 } else { 715 kn->kn_flags &= ~__EV_HUP; 716 } 717 } 718 719 return (active); 720 } 721 722 const struct filterops ptcread_filtops = { 723 .f_flags = FILTEROP_ISFD, 724 .f_attach = NULL, 725 .f_detach = filt_ptcrdetach, 726 .f_event = filt_ptcread, 727 }; 728 729 const struct filterops ptcwrite_filtops = { 730 .f_flags = FILTEROP_ISFD, 731 .f_attach = NULL, 732 .f_detach = filt_ptcwdetach, 733 .f_event = filt_ptcwrite, 734 }; 735 736 const struct filterops ptcexcept_filtops = { 737 .f_flags = FILTEROP_ISFD, 738 .f_attach = NULL, 739 .f_detach = filt_ptcrdetach, 740 .f_event = filt_ptcexcept, 741 }; 742 743 int 744 ptckqfilter(dev_t dev, struct knote *kn) 745 { 746 struct pt_softc *pti = pt_softc[minor(dev)]; 747 struct klist *klist; 748 int s; 749 750 switch (kn->kn_filter) { 751 case EVFILT_READ: 752 klist = &pti->pt_selr.si_note; 753 kn->kn_fop = &ptcread_filtops; 754 break; 755 case EVFILT_WRITE: 756 klist = &pti->pt_selw.si_note; 757 kn->kn_fop = &ptcwrite_filtops; 758 break; 759 case EVFILT_EXCEPT: 760 klist = &pti->pt_selr.si_note; 761 kn->kn_fop = &ptcexcept_filtops; 762 break; 763 default: 764 return (EINVAL); 765 } 766 767 kn->kn_hook = (caddr_t)pti; 768 769 s = spltty(); 770 klist_insert_locked(klist, kn); 771 splx(s); 772 773 return (0); 774 } 775 776 struct tty * 777 ptytty(dev_t dev) 778 { 779 struct pt_softc *pti = pt_softc[minor(dev)]; 780 struct tty *tp = pti->pt_tty; 781 782 return (tp); 783 } 784 785 int 786 ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 787 { 788 struct pt_softc *pti = pt_softc[minor(dev)]; 789 struct tty *tp = pti->pt_tty; 790 u_char *cc = tp->t_cc; 791 int stop, error; 792 793 /* 794 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 795 * ttywflush(tp) will hang if there are characters in the outq. 796 */ 797 if (cmd == TIOCEXT) { 798 /* 799 * When the EXTPROC bit is being toggled, we need 800 * to send an TIOCPKT_IOCTL if the packet driver 801 * is turned on. 802 */ 803 if (*(int *)data) { 804 if (pti->pt_flags & PF_PKT) { 805 pti->pt_send |= TIOCPKT_IOCTL; 806 ptcwakeup(tp, FREAD); 807 } 808 tp->t_lflag |= EXTPROC; 809 } else { 810 if ((tp->t_lflag & EXTPROC) && 811 (pti->pt_flags & PF_PKT)) { 812 pti->pt_send |= TIOCPKT_IOCTL; 813 ptcwakeup(tp, FREAD); 814 } 815 tp->t_lflag &= ~EXTPROC; 816 } 817 return(0); 818 } else if (cdevsw[major(dev)].d_open == ptcopen) 819 switch (cmd) { 820 821 case TIOCGPGRP: 822 /* 823 * We avoid calling ttioctl on the controller since, 824 * in that case, tp must be the controlling terminal. 825 */ 826 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 827 return (0); 828 829 case TIOCPKT: 830 if (*(int *)data) { 831 if (pti->pt_flags & PF_UCNTL) 832 return (EINVAL); 833 pti->pt_flags |= PF_PKT; 834 } else 835 pti->pt_flags &= ~PF_PKT; 836 return (0); 837 838 case TIOCUCNTL: 839 if (*(int *)data) { 840 if (pti->pt_flags & PF_PKT) 841 return (EINVAL); 842 pti->pt_flags |= PF_UCNTL; 843 } else 844 pti->pt_flags &= ~PF_UCNTL; 845 return (0); 846 847 case TIOCREMOTE: 848 if (*(int *)data) 849 pti->pt_flags |= PF_REMOTE; 850 else 851 pti->pt_flags &= ~PF_REMOTE; 852 ttyflush(tp, FREAD|FWRITE); 853 return (0); 854 855 case TIOCSETD: 856 case TIOCSETA: 857 case TIOCSETAW: 858 case TIOCSETAF: 859 ndflush(&tp->t_outq, tp->t_outq.c_cc); 860 break; 861 862 case TIOCSIG: 863 if (*(unsigned int *)data >= NSIG || 864 *(unsigned int *)data == 0) 865 return(EINVAL); 866 if ((tp->t_lflag & NOFLSH) == 0) 867 ttyflush(tp, FREAD|FWRITE); 868 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 869 if ((*(unsigned int *)data == SIGINFO) && 870 ((tp->t_lflag & NOKERNINFO) == 0)) 871 ttyinfo(tp); 872 return (0); 873 874 case FIONREAD: 875 /* 876 * FIONREAD on the master side must return the amount 877 * in the output queue rather than the input. 878 */ 879 *(int *)data = tp->t_outq.c_cc; 880 return (0); 881 } 882 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 883 if (error < 0) 884 error = ttioctl(tp, cmd, data, flag, p); 885 if (error < 0) { 886 /* 887 * Translate TIOCSBRK/TIOCCBRK to user mode ioctls to 888 * let the master interpret BREAK conditions. 889 */ 890 switch (cmd) { 891 case TIOCSBRK: 892 cmd = UIOCCMD(TIOCUCNTL_SBRK); 893 break; 894 case TIOCCBRK: 895 cmd = UIOCCMD(TIOCUCNTL_CBRK); 896 break; 897 default: 898 break; 899 } 900 if (pti->pt_flags & PF_UCNTL && 901 (cmd & ~0xff) == UIOCCMD(0)) { 902 if (cmd & 0xff) { 903 pti->pt_ucntl = (u_char)cmd; 904 ptcwakeup(tp, FREAD); 905 } 906 return (0); 907 } 908 error = ENOTTY; 909 } 910 /* 911 * If external processing and packet mode send ioctl packet. 912 */ 913 if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) { 914 switch (cmd) { 915 case TIOCSETA: 916 case TIOCSETAW: 917 case TIOCSETAF: 918 pti->pt_send |= TIOCPKT_IOCTL; 919 ptcwakeup(tp, FREAD); 920 default: 921 break; 922 } 923 } 924 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) && 925 CCEQ(cc[VSTART], CTRL('q')); 926 if (pti->pt_flags & PF_NOSTOP) { 927 if (stop) { 928 pti->pt_send &= ~TIOCPKT_NOSTOP; 929 pti->pt_send |= TIOCPKT_DOSTOP; 930 pti->pt_flags &= ~PF_NOSTOP; 931 ptcwakeup(tp, FREAD); 932 } 933 } else { 934 if (!stop) { 935 pti->pt_send &= ~TIOCPKT_DOSTOP; 936 pti->pt_send |= TIOCPKT_NOSTOP; 937 pti->pt_flags |= PF_NOSTOP; 938 ptcwakeup(tp, FREAD); 939 } 940 } 941 return (error); 942 } 943 944 /* 945 * Return pty-related information. 946 */ 947 int 948 sysctl_pty(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 949 size_t newlen) 950 { 951 if (namelen != 1) 952 return (ENOTDIR); 953 954 switch (name[0]) { 955 default: 956 return (EOPNOTSUPP); 957 } 958 /* NOTREACHED */ 959 } 960 961 /* 962 * Check if a pty is free to use. 963 */ 964 static int 965 pty_isfree_locked(int minor) 966 { 967 struct pt_softc *pt = pt_softc[minor]; 968 969 return (pt == NULL || pt->pt_tty == NULL || 970 pt->pt_tty->t_oproc == NULL); 971 } 972 973 static int 974 pty_isfree(int minor) 975 { 976 int isfree; 977 978 rw_enter_read(&pt_softc_lock); 979 isfree = pty_isfree_locked(minor); 980 rw_exit_read(&pt_softc_lock); 981 return(isfree); 982 } 983 984 dev_t 985 pty_getfree(void) 986 { 987 int i; 988 989 rw_enter_read(&pt_softc_lock); 990 for (i = 0; i < npty; i++) { 991 if (pty_isfree_locked(i)) 992 break; 993 } 994 rw_exit_read(&pt_softc_lock); 995 return (makedev(pts_major, i)); 996 } 997 998 /* 999 * Hacked up version of vn_open. We _only_ handle ptys and only open 1000 * them with FREAD|FWRITE and never deal with creat or stuff like that. 1001 * 1002 * We need it because we have to fake up root credentials to open the pty. 1003 */ 1004 static int 1005 ptm_vn_open(struct nameidata *ndp) 1006 { 1007 struct proc *p = ndp->ni_cnd.cn_proc; 1008 struct ucred *cred; 1009 struct vattr vattr; 1010 struct vnode *vp; 1011 int error; 1012 1013 if ((error = namei(ndp)) != 0) 1014 return (error); 1015 vp = ndp->ni_vp; 1016 if (vp->v_type != VCHR) { 1017 error = EINVAL; 1018 goto bad; 1019 } 1020 1021 /* 1022 * Get us a fresh cred with root privileges. 1023 */ 1024 cred = crget(); 1025 error = VOP_OPEN(vp, FREAD|FWRITE, cred, p); 1026 if (!error) { 1027 /* update atime/mtime */ 1028 vattr_null(&vattr); 1029 getnanotime(&vattr.va_atime); 1030 vattr.va_mtime = vattr.va_atime; 1031 vattr.va_vaflags |= VA_UTIMES_NULL; 1032 (void)VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1033 } 1034 crfree(cred); 1035 1036 if (error) 1037 goto bad; 1038 1039 vp->v_writecount++; 1040 1041 return (0); 1042 bad: 1043 vput(vp); 1044 return (error); 1045 } 1046 1047 void 1048 ptmattach(int n) 1049 { 1050 /* find the major and minor of the pty devices */ 1051 int i; 1052 1053 for (i = 0; i < nchrdev; i++) 1054 if (cdevsw[i].d_open == ptsopen) 1055 break; 1056 1057 if (i == nchrdev) 1058 panic("ptmattach: Can't find pty slave in cdevsw"); 1059 1060 pts_major = i; 1061 } 1062 1063 int 1064 ptmopen(dev_t dev, int flag, int mode, struct proc *p) 1065 { 1066 return(0); 1067 } 1068 1069 1070 int 1071 ptmclose(dev_t dev, int flag, int mode, struct proc *p) 1072 { 1073 return (0); 1074 } 1075 1076 int 1077 ptmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 1078 { 1079 dev_t newdev; 1080 struct pt_softc * pti; 1081 struct nameidata cnd, snd; 1082 struct filedesc *fdp = p->p_fd; 1083 struct file *cfp = NULL, *sfp = NULL; 1084 int cindx, sindx, error; 1085 uid_t uid; 1086 gid_t gid; 1087 struct vattr vattr; 1088 struct ucred *cred; 1089 struct ptmget *ptm = (struct ptmget *)data; 1090 1091 switch (cmd) { 1092 case PTMGET: 1093 fdplock(fdp); 1094 /* Grab two filedescriptors. */ 1095 if ((error = falloc(p, &cfp, &cindx)) != 0) { 1096 fdpunlock(fdp); 1097 break; 1098 } 1099 if ((error = falloc(p, &sfp, &sindx)) != 0) { 1100 fdremove(fdp, cindx); 1101 fdpunlock(fdp); 1102 closef(cfp, p); 1103 break; 1104 } 1105 fdpunlock(fdp); 1106 1107 retry: 1108 /* Find and open a free master pty. */ 1109 newdev = pty_getfree(); 1110 if ((error = check_pty(newdev))) 1111 goto bad; 1112 pti = pt_softc[minor(newdev)]; 1113 NDINIT(&cnd, LOOKUP, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, 1114 pti->pty_pn, p); 1115 cnd.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH; 1116 if ((error = ptm_vn_open(&cnd)) != 0) { 1117 /* 1118 * Check if the master open failed because we lost 1119 * the race to grab it. 1120 */ 1121 if (error == EIO && !pty_isfree(minor(newdev))) 1122 goto retry; 1123 goto bad; 1124 } 1125 cfp->f_flag = FREAD|FWRITE; 1126 cfp->f_type = DTYPE_VNODE; 1127 cfp->f_ops = &vnops; 1128 cfp->f_data = (caddr_t) cnd.ni_vp; 1129 VOP_UNLOCK(cnd.ni_vp); 1130 1131 /* 1132 * Open the slave. 1133 * namei -> setattr -> unlock -> revoke -> vrele -> 1134 * namei -> open -> unlock 1135 * Three stage rocket: 1136 * 1. Change the owner and permissions on the slave. 1137 * 2. Revoke all the users of the slave. 1138 * 3. open the slave. 1139 */ 1140 NDINIT(&snd, LOOKUP, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, 1141 pti->pty_sn, p); 1142 snd.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH; 1143 if ((error = namei(&snd)) != 0) 1144 goto bad; 1145 if ((snd.ni_vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 1146 gid = tty_gid; 1147 /* get real uid */ 1148 uid = p->p_ucred->cr_ruid; 1149 1150 vattr_null(&vattr); 1151 vattr.va_uid = uid; 1152 vattr.va_gid = gid; 1153 vattr.va_mode = (S_IRUSR|S_IWUSR|S_IWGRP) & ALLPERMS; 1154 /* Get a fake cred to pretend we're root. */ 1155 cred = crget(); 1156 error = VOP_SETATTR(snd.ni_vp, &vattr, cred, p); 1157 crfree(cred); 1158 if (error) { 1159 vput(snd.ni_vp); 1160 goto bad; 1161 } 1162 } 1163 VOP_UNLOCK(snd.ni_vp); 1164 if (snd.ni_vp->v_usecount > 1 || 1165 (snd.ni_vp->v_flag & (VALIASED))) 1166 VOP_REVOKE(snd.ni_vp, REVOKEALL); 1167 1168 /* 1169 * The vnode is useless after the revoke, we need to 1170 * namei again. 1171 */ 1172 vrele(snd.ni_vp); 1173 1174 NDINIT(&snd, LOOKUP, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, 1175 pti->pty_sn, p); 1176 snd.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH; 1177 /* now open it */ 1178 if ((error = ptm_vn_open(&snd)) != 0) 1179 goto bad; 1180 sfp->f_flag = FREAD|FWRITE; 1181 sfp->f_type = DTYPE_VNODE; 1182 sfp->f_ops = &vnops; 1183 sfp->f_data = (caddr_t) snd.ni_vp; 1184 VOP_UNLOCK(snd.ni_vp); 1185 1186 /* now, put the indexen and names into struct ptmget */ 1187 ptm->cfd = cindx; 1188 ptm->sfd = sindx; 1189 memcpy(ptm->cn, pti->pty_pn, sizeof(pti->pty_pn)); 1190 memcpy(ptm->sn, pti->pty_sn, sizeof(pti->pty_sn)); 1191 1192 /* insert files now that we've passed all errors */ 1193 fdplock(fdp); 1194 fdinsert(fdp, cindx, 0, cfp); 1195 fdinsert(fdp, sindx, 0, sfp); 1196 fdpunlock(fdp); 1197 FRELE(cfp, p); 1198 FRELE(sfp, p); 1199 break; 1200 default: 1201 error = EINVAL; 1202 break; 1203 } 1204 return (error); 1205 bad: 1206 fdplock(fdp); 1207 fdremove(fdp, cindx); 1208 fdremove(fdp, sindx); 1209 fdpunlock(fdp); 1210 closef(cfp, p); 1211 closef(sfp, p); 1212 return (error); 1213 } 1214