1 /* $NetBSD: tty_pty.c,v 1.79 2004/06/05 11:23:15 lha Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 32 */ 33 34 /* 35 * Pseudo-teletype Driver 36 * (Actually two drivers, requiring two entries in 'cdevsw') 37 * Additional multiplexor driver /dev/ptm{,x} 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: tty_pty.c,v 1.79 2004/06/05 11:23:15 lha Exp $"); 42 43 #include "opt_compat_sunos.h" 44 #include "pty.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/ioctl.h> 49 #include <sys/proc.h> 50 #include <sys/tty.h> 51 #include <sys/stat.h> 52 #include <sys/file.h> 53 #include <sys/uio.h> 54 #include <sys/kernel.h> 55 #include <sys/vnode.h> 56 #include <sys/namei.h> 57 #include <sys/signalvar.h> 58 #include <sys/uio.h> 59 #include <sys/filedesc.h> 60 #include <sys/conf.h> 61 #include <sys/poll.h> 62 #include <sys/malloc.h> 63 64 #define DEFAULT_NPTYS 16 /* default number of initial ptys */ 65 #define DEFAULT_MAXPTYS 992 /* default maximum number of ptys */ 66 67 #ifdef DEBUG_PTM 68 #define DPRINTF(a) uprintf a 69 #else 70 #define DPRINTF(a) 71 #endif 72 73 /* Macros to clear/set/test flags. */ 74 #define SET(t, f) (t) |= (f) 75 #define CLR(t, f) (t) &= ~((unsigned)(f)) 76 #define ISSET(t, f) ((t) & (f)) 77 78 #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 79 80 /* 81 * pts == /dev/tty[pqrs]? 82 * ptc == /dev/pty[pqrs]? 83 */ 84 85 #define TTY_TEMPLATE "/dev/XtyXX" 86 #define TTY_NAMESIZE sizeof(TTY_TEMPLATE) 87 /* XXX this needs to come from somewhere sane, and work with MAKEDEV */ 88 #define TTY_LETTERS "pqrstuvwxyzPQRST" 89 #define TTY_OLD_SUFFIX "0123456789abcdef" 90 #define TTY_NEW_SUFFIX "ghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 91 92 struct pt_softc { 93 struct tty *pt_tty; 94 int pt_flags; 95 struct selinfo pt_selr, pt_selw; 96 u_char pt_send; 97 u_char pt_ucntl; 98 }; 99 100 static struct pt_softc **pt_softc = NULL; /* pty array */ 101 static int npty = 0; /* for pstat -t */ 102 static int maxptys = DEFAULT_MAXPTYS; /* maximum number of ptys (sysctable) */ 103 static struct simplelock pt_softc_mutex = SIMPLELOCK_INITIALIZER; 104 105 #define PF_PKT 0x08 /* packet mode */ 106 #define PF_STOPPED 0x10 /* user told stopped */ 107 #define PF_REMOTE 0x20 /* remote and flow controlled input */ 108 #define PF_NOSTOP 0x40 109 #define PF_UCNTL 0x80 /* user control mode */ 110 111 void ptyattach(int); 112 void ptcwakeup(struct tty *, int); 113 void ptsstart(struct tty *); 114 int pty_maxptys(int, int); 115 116 static struct pt_softc **ptyarralloc(int); 117 static int check_pty(int); 118 119 #ifdef NPTM 120 121 static int pts_major; 122 123 static dev_t pty_getfree(void); 124 static char *pty_makename(char *, dev_t, char); 125 static int pty_grant_slave(struct proc *, dev_t); 126 static int pty_alloc_master(struct proc *, int *, dev_t *); 127 static int pty_alloc_slave(struct proc *, int *, dev_t); 128 static void pty_fill_ptmget(dev_t, int, int, void *); 129 130 void ptmattach(int); 131 132 dev_type_open(ptmopen); 133 dev_type_close(ptmclose); 134 dev_type_ioctl(ptmioctl); 135 136 const struct cdevsw ptm_cdevsw = { 137 ptmopen, ptmclose, noread, nowrite, ptmioctl, 138 nullstop, notty, nopoll, nommap, nokqfilter, D_TTY 139 }; 140 #endif 141 142 dev_type_open(ptcopen); 143 dev_type_close(ptcclose); 144 dev_type_read(ptcread); 145 dev_type_write(ptcwrite); 146 dev_type_poll(ptcpoll); 147 dev_type_kqfilter(ptckqfilter); 148 149 dev_type_open(ptsopen); 150 dev_type_close(ptsclose); 151 dev_type_read(ptsread); 152 dev_type_write(ptswrite); 153 dev_type_stop(ptsstop); 154 dev_type_poll(ptspoll); 155 156 dev_type_ioctl(ptyioctl); 157 dev_type_tty(ptytty); 158 159 const struct cdevsw ptc_cdevsw = { 160 ptcopen, ptcclose, ptcread, ptcwrite, ptyioctl, 161 nullstop, ptytty, ptcpoll, nommap, ptckqfilter, D_TTY 162 }; 163 164 const struct cdevsw pts_cdevsw = { 165 ptsopen, ptsclose, ptsread, ptswrite, ptyioctl, 166 ptsstop, ptytty, ptspoll, nommap, ttykqfilter, D_TTY 167 }; 168 169 #if defined(pmax) 170 const struct cdevsw ptc_ultrix_cdevsw = { 171 ptcopen, ptcclose, ptcread, ptcwrite, ptyioctl, 172 nullstop, ptytty, ptcpoll, nommap, ptckqfilter, D_TTY 173 }; 174 175 const struct cdevsw pts_ultrix_cdevsw = { 176 ptsopen, ptsclose, ptsread, ptswrite, ptyioctl, 177 ptsstop, ptytty, ptspoll, nommap, ttykqfilter, D_TTY 178 }; 179 #endif /* defined(pmax) */ 180 181 /* 182 * Allocate and zero array of nelem elements. 183 */ 184 static struct pt_softc ** 185 ptyarralloc(nelem) 186 int nelem; 187 { 188 struct pt_softc **pt; 189 nelem += 10; 190 pt = malloc(nelem * sizeof *pt, M_DEVBUF, M_WAITOK | M_ZERO); 191 return pt; 192 } 193 194 /* 195 * Check if the minor is correct and ensure necessary structures 196 * are properly allocated. 197 */ 198 static int 199 check_pty(int ptn) 200 { 201 struct pt_softc *pti; 202 203 if (ptn >= npty) { 204 struct pt_softc **newpt, **oldpt; 205 int newnpty; 206 207 /* check if the requested pty can be granted */ 208 if (ptn >= maxptys) { 209 limit_reached: 210 tablefull("pty", "increase kern.maxptys"); 211 return (ENXIO); 212 } 213 214 /* Allocate a larger pty array */ 215 for (newnpty = npty; newnpty <= ptn;) 216 newnpty *= 2; 217 if (newnpty > maxptys) 218 newnpty = maxptys; 219 newpt = ptyarralloc(newnpty); 220 221 /* 222 * Now grab the pty array mutex - we need to ensure 223 * that the pty array is consistent while copying it's 224 * content to newly allocated, larger space; we also 225 * need to be safe against pty_maxptys(). 226 */ 227 simple_lock(&pt_softc_mutex); 228 229 if (newnpty >= maxptys) { 230 /* limit cut away beneath us... */ 231 newnpty = maxptys; 232 if (ptn >= newnpty) { 233 simple_unlock(&pt_softc_mutex); 234 free(newpt, M_DEVBUF); 235 goto limit_reached; 236 } 237 } 238 239 /* 240 * If the pty array was not enlarged while we were waiting 241 * for mutex, copy current contents of pt_softc[] to newly 242 * allocated array and start using the new bigger array. 243 */ 244 if (newnpty > npty) { 245 memcpy(newpt, pt_softc, npty*sizeof(struct pt_softc *)); 246 oldpt = pt_softc; 247 pt_softc = newpt; 248 npty = newnpty; 249 } else { 250 /* was enlarged when waited for lock, free new space */ 251 oldpt = newpt; 252 } 253 254 simple_unlock(&pt_softc_mutex); 255 free(oldpt, M_DEVBUF); 256 } 257 258 /* 259 * If the entry is not yet allocated, allocate one. The mutex is 260 * needed so that the state of pt_softc[] array is consistant 261 * in case it has been lengthened above. 262 */ 263 if (!pt_softc[ptn]) { 264 MALLOC(pti, struct pt_softc *, sizeof(struct pt_softc), 265 M_DEVBUF, M_WAITOK); 266 memset(pti, 0, sizeof(struct pt_softc)); 267 268 pti->pt_tty = ttymalloc(); 269 270 simple_lock(&pt_softc_mutex); 271 272 /* 273 * Check the entry again - it might have been 274 * added while we were waiting for mutex. 275 */ 276 if (!pt_softc[ptn]) { 277 tty_attach(pti->pt_tty); 278 pt_softc[ptn] = pti; 279 } else { 280 ttyfree(pti->pt_tty); 281 free(pti, M_DEVBUF); 282 } 283 284 simple_unlock(&pt_softc_mutex); 285 } 286 287 return (0); 288 } 289 290 /* 291 * Set maxpty in thread-safe way. Returns 0 in case of error, otherwise 292 * new value of maxptys. 293 */ 294 int 295 pty_maxptys(newmax, set) 296 int newmax, set; 297 { 298 if (!set) 299 return (maxptys); 300 301 /* 302 * We have to grab the pt_softc lock, so that we would pick correct 303 * value of npty (might be modified in check_pty()). 304 */ 305 simple_lock(&pt_softc_mutex); 306 307 /* 308 * The value cannot be set to value lower than the highest pty 309 * number ever allocated. 310 */ 311 if (newmax >= npty) 312 maxptys = newmax; 313 else 314 newmax = 0; 315 316 simple_unlock(&pt_softc_mutex); 317 318 return newmax; 319 } 320 321 /* 322 * Establish n (or default if n is 1) ptys in the system. 323 */ 324 void 325 ptyattach(n) 326 int n; 327 { 328 /* maybe should allow 0 => none? */ 329 if (n <= 1) 330 n = DEFAULT_NPTYS; 331 pt_softc = ptyarralloc(n); 332 npty = n; 333 } 334 335 /*ARGSUSED*/ 336 int 337 ptsopen(dev, flag, devtype, p) 338 dev_t dev; 339 int flag, devtype; 340 struct proc *p; 341 { 342 struct pt_softc *pti; 343 struct tty *tp; 344 int error; 345 int ptn = minor(dev); 346 int s; 347 348 if ((error = check_pty(ptn))) 349 return (error); 350 351 pti = pt_softc[ptn]; 352 tp = pti->pt_tty; 353 354 if (!ISSET(tp->t_state, TS_ISOPEN)) { 355 ttychars(tp); /* Set up default chars */ 356 tp->t_iflag = TTYDEF_IFLAG; 357 tp->t_oflag = TTYDEF_OFLAG; 358 tp->t_lflag = TTYDEF_LFLAG; 359 tp->t_cflag = TTYDEF_CFLAG; 360 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 361 ttsetwater(tp); /* would be done in xxparam() */ 362 } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) 363 return (EBUSY); 364 if (tp->t_oproc) /* Ctrlr still around. */ 365 SET(tp->t_state, TS_CARR_ON); 366 367 if (!ISSET(flag, O_NONBLOCK)) { 368 s = spltty(); 369 TTY_LOCK(tp); 370 while (!ISSET(tp->t_state, TS_CARR_ON)) { 371 tp->t_wopen++; 372 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 373 ttopen, 0); 374 tp->t_wopen--; 375 if (error) { 376 TTY_UNLOCK(tp); 377 splx(s); 378 return (error); 379 } 380 } 381 TTY_UNLOCK(tp); 382 splx(s); 383 } 384 error = (*tp->t_linesw->l_open)(dev, tp); 385 ptcwakeup(tp, FREAD|FWRITE); 386 return (error); 387 } 388 389 int 390 ptsclose(dev, flag, mode, p) 391 dev_t dev; 392 int flag, mode; 393 struct proc *p; 394 { 395 struct pt_softc *pti = pt_softc[minor(dev)]; 396 struct tty *tp = pti->pt_tty; 397 int error; 398 399 error = (*tp->t_linesw->l_close)(tp, flag); 400 error |= ttyclose(tp); 401 ptcwakeup(tp, FREAD|FWRITE); 402 return (error); 403 } 404 405 int 406 ptsread(dev, uio, flag) 407 dev_t dev; 408 struct uio *uio; 409 int flag; 410 { 411 struct proc *p = curproc; 412 struct pt_softc *pti = pt_softc[minor(dev)]; 413 struct tty *tp = pti->pt_tty; 414 int error = 0; 415 int cc; 416 int s; 417 418 again: 419 if (pti->pt_flags & PF_REMOTE) { 420 while (isbackground(p, tp)) { 421 if (sigismasked(p, SIGTTIN) || 422 p->p_pgrp->pg_jobc == 0 || 423 p->p_flag & P_PPWAIT) 424 return (EIO); 425 pgsignal(p->p_pgrp, SIGTTIN, 1); 426 s = spltty(); 427 TTY_LOCK(tp); 428 error = ttysleep(tp, (caddr_t)&lbolt, 429 TTIPRI | PCATCH | PNORELOCK, ttybg, 0); 430 splx(s); 431 if (error) 432 return (error); 433 } 434 s = spltty(); 435 TTY_LOCK(tp); 436 if (tp->t_canq.c_cc == 0) { 437 if (flag & IO_NDELAY) { 438 TTY_UNLOCK(tp); 439 splx(s); 440 return (EWOULDBLOCK); 441 } 442 error = ttysleep(tp, (caddr_t)&tp->t_canq, 443 TTIPRI | PCATCH | PNORELOCK, ttyin, 0); 444 if (error) 445 return (error); 446 goto again; 447 } 448 while(error == 0 && tp->t_canq.c_cc > 1 && uio->uio_resid > 0) { 449 TTY_UNLOCK(tp); 450 splx(s); 451 error = ureadc(getc(&tp->t_canq), uio); 452 s = spltty(); 453 TTY_LOCK(tp); 454 /* Re-check terminal state here? */ 455 } 456 if (tp->t_canq.c_cc == 1) 457 (void) getc(&tp->t_canq); 458 cc = tp->t_canq.c_cc; 459 TTY_UNLOCK(tp); 460 splx(s); 461 if (cc) 462 return (error); 463 } else 464 if (tp->t_oproc) 465 error = (*tp->t_linesw->l_read)(tp, uio, flag); 466 ptcwakeup(tp, FWRITE); 467 return (error); 468 } 469 470 /* 471 * Write to pseudo-tty. 472 * Wakeups of controlling tty will happen 473 * indirectly, when tty driver calls ptsstart. 474 */ 475 int 476 ptswrite(dev, uio, flag) 477 dev_t dev; 478 struct uio *uio; 479 int flag; 480 { 481 struct pt_softc *pti = pt_softc[minor(dev)]; 482 struct tty *tp = pti->pt_tty; 483 484 if (tp->t_oproc == 0) 485 return (EIO); 486 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 487 } 488 489 /* 490 * Poll pseudo-tty. 491 */ 492 int 493 ptspoll(dev, events, p) 494 dev_t dev; 495 int events; 496 struct proc *p; 497 { 498 struct pt_softc *pti = pt_softc[minor(dev)]; 499 struct tty *tp = pti->pt_tty; 500 501 if (tp->t_oproc == 0) 502 return (EIO); 503 504 return ((*tp->t_linesw->l_poll)(tp, events, p)); 505 } 506 507 /* 508 * Start output on pseudo-tty. 509 * Wake up process polling or sleeping for input from controlling tty. 510 * Called with tty slock held. 511 */ 512 void 513 ptsstart(tp) 514 struct tty *tp; 515 { 516 struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; 517 518 if (ISSET(tp->t_state, TS_TTSTOP)) 519 return; 520 if (pti->pt_flags & PF_STOPPED) { 521 pti->pt_flags &= ~PF_STOPPED; 522 pti->pt_send = TIOCPKT_START; 523 } 524 525 selnotify(&pti->pt_selr, NOTE_SUBMIT); 526 wakeup((caddr_t)&tp->t_outq.c_cf); 527 } 528 529 /* 530 * Stop output. 531 * Called with tty slock held. 532 */ 533 void 534 ptsstop(tp, flush) 535 struct tty *tp; 536 int flush; 537 { 538 struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; 539 540 /* note: FLUSHREAD and FLUSHWRITE already ok */ 541 if (flush == 0) { 542 flush = TIOCPKT_STOP; 543 pti->pt_flags |= PF_STOPPED; 544 } else 545 pti->pt_flags &= ~PF_STOPPED; 546 pti->pt_send |= flush; 547 548 /* change of perspective */ 549 if (flush & FREAD) { 550 selnotify(&pti->pt_selw, NOTE_SUBMIT); 551 wakeup((caddr_t)&tp->t_rawq.c_cf); 552 } 553 if (flush & FWRITE) { 554 selnotify(&pti->pt_selr, NOTE_SUBMIT); 555 wakeup((caddr_t)&tp->t_outq.c_cf); 556 } 557 } 558 559 void 560 ptcwakeup(tp, flag) 561 struct tty *tp; 562 int flag; 563 { 564 struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; 565 int s; 566 567 s = spltty(); 568 TTY_LOCK(tp); 569 if (flag & FREAD) { 570 selnotify(&pti->pt_selr, NOTE_SUBMIT); 571 wakeup((caddr_t)&tp->t_outq.c_cf); 572 } 573 if (flag & FWRITE) { 574 selnotify(&pti->pt_selw, NOTE_SUBMIT); 575 wakeup((caddr_t)&tp->t_rawq.c_cf); 576 } 577 TTY_UNLOCK(tp); 578 splx(s); 579 } 580 581 /*ARGSUSED*/ 582 int 583 ptcopen(dev, flag, devtype, p) 584 dev_t dev; 585 int flag, devtype; 586 struct proc *p; 587 { 588 struct pt_softc *pti; 589 struct tty *tp; 590 int error; 591 int ptn = minor(dev); 592 int s; 593 594 if ((error = check_pty(ptn))) 595 return (error); 596 597 pti = pt_softc[ptn]; 598 tp = pti->pt_tty; 599 600 s = spltty(); 601 TTY_LOCK(tp); 602 if (tp->t_oproc) { 603 TTY_UNLOCK(tp); 604 splx(s); 605 return (EIO); 606 } 607 tp->t_oproc = ptsstart; 608 TTY_UNLOCK(tp); 609 splx(s); 610 (void)(*tp->t_linesw->l_modem)(tp, 1); 611 CLR(tp->t_lflag, EXTPROC); 612 pti->pt_flags = 0; 613 pti->pt_send = 0; 614 pti->pt_ucntl = 0; 615 return (0); 616 } 617 618 /*ARGSUSED*/ 619 int 620 ptcclose(dev, flag, devtype, p) 621 dev_t dev; 622 int flag, devtype; 623 struct proc *p; 624 { 625 struct pt_softc *pti = pt_softc[minor(dev)]; 626 struct tty *tp = pti->pt_tty; 627 int s; 628 629 (void)(*tp->t_linesw->l_modem)(tp, 0); 630 CLR(tp->t_state, TS_CARR_ON); 631 s = spltty(); 632 TTY_LOCK(tp); 633 tp->t_oproc = 0; /* mark closed */ 634 TTY_UNLOCK(tp); 635 splx(s); 636 return (0); 637 } 638 639 int 640 ptcread(dev, uio, flag) 641 dev_t dev; 642 struct uio *uio; 643 int flag; 644 { 645 struct pt_softc *pti = pt_softc[minor(dev)]; 646 struct tty *tp = pti->pt_tty; 647 u_char buf[BUFSIZ]; 648 int error = 0, cc; 649 int s; 650 651 /* 652 * We want to block until the slave 653 * is open, and there's something to read; 654 * but if we lost the slave or we're NBIO, 655 * then return the appropriate error instead. 656 */ 657 s = spltty(); 658 TTY_LOCK(tp); 659 for (;;) { 660 if (ISSET(tp->t_state, TS_ISOPEN)) { 661 if (pti->pt_flags & PF_PKT && pti->pt_send) { 662 TTY_UNLOCK(tp); 663 splx(s); 664 error = ureadc((int)pti->pt_send, uio); 665 if (error) 666 return (error); 667 /* 668 * Since we don't have the tty locked, there's 669 * a risk of messing up `t_termios'. This is 670 * relevant only if the tty got closed and then 671 * opened again while we were out uiomoving. 672 */ 673 if (pti->pt_send & TIOCPKT_IOCTL) { 674 cc = min(uio->uio_resid, 675 sizeof(tp->t_termios)); 676 uiomove((caddr_t) &tp->t_termios, 677 cc, uio); 678 } 679 pti->pt_send = 0; 680 return (0); 681 } 682 if (pti->pt_flags & PF_UCNTL && pti->pt_ucntl) { 683 TTY_UNLOCK(tp); 684 splx(s); 685 error = ureadc((int)pti->pt_ucntl, uio); 686 if (error) 687 return (error); 688 pti->pt_ucntl = 0; 689 return (0); 690 } 691 if (tp->t_outq.c_cc && !ISSET(tp->t_state, TS_TTSTOP)) 692 break; 693 } 694 if (!ISSET(tp->t_state, TS_CARR_ON)) { 695 error = 0; /* EOF */ 696 goto out; 697 } 698 if (flag & IO_NDELAY) { 699 error = EWOULDBLOCK; 700 goto out; 701 } 702 error = ltsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH, 703 ttyin, 0, &tp->t_slock); 704 if (error) 705 goto out; 706 } 707 708 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) { 709 TTY_UNLOCK(tp); 710 splx(s); 711 error = ureadc(0, uio); 712 s = spltty(); 713 TTY_LOCK(tp); 714 if (error == 0 && !ISSET(tp->t_state, TS_ISOPEN)) 715 error = EIO; 716 } 717 while (uio->uio_resid > 0 && error == 0) { 718 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ)); 719 if (cc <= 0) 720 break; 721 TTY_UNLOCK(tp); 722 splx(s); 723 error = uiomove(buf, cc, uio); 724 s = spltty(); 725 TTY_LOCK(tp); 726 if (error == 0 && !ISSET(tp->t_state, TS_ISOPEN)) 727 error = EIO; 728 } 729 730 if (tp->t_outq.c_cc <= tp->t_lowat) { 731 if (ISSET(tp->t_state, TS_ASLEEP)) { 732 CLR(tp->t_state, TS_ASLEEP); 733 wakeup((caddr_t)&tp->t_outq); 734 } 735 selnotify(&tp->t_wsel, NOTE_SUBMIT); 736 } 737 out: 738 TTY_UNLOCK(tp); 739 splx(s); 740 return (error); 741 } 742 743 744 int 745 ptcwrite(dev, uio, flag) 746 dev_t dev; 747 struct uio *uio; 748 int flag; 749 { 750 struct pt_softc *pti = pt_softc[minor(dev)]; 751 struct tty *tp = pti->pt_tty; 752 u_char *cp = NULL; 753 int cc = 0; 754 u_char locbuf[BUFSIZ]; 755 int cnt = 0; 756 int error = 0; 757 int s; 758 759 again: 760 s = spltty(); 761 TTY_LOCK(tp); 762 if (!ISSET(tp->t_state, TS_ISOPEN)) 763 goto block; 764 if (pti->pt_flags & PF_REMOTE) { 765 if (tp->t_canq.c_cc) 766 goto block; 767 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 768 if (cc == 0) { 769 cc = min(uio->uio_resid, BUFSIZ); 770 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 771 cp = locbuf; 772 TTY_UNLOCK(tp); 773 splx(s); 774 error = uiomove((caddr_t)cp, cc, uio); 775 if (error) 776 return (error); 777 s = spltty(); 778 TTY_LOCK(tp); 779 /* check again for safety */ 780 if (!ISSET(tp->t_state, TS_ISOPEN)) { 781 error = EIO; 782 goto out; 783 } 784 } 785 if (cc) 786 (void) b_to_q(cp, cc, &tp->t_canq); 787 cc = 0; 788 } 789 (void) putc(0, &tp->t_canq); 790 ttwakeup(tp); 791 wakeup((caddr_t)&tp->t_canq); 792 error = 0; 793 goto out; 794 } 795 while (uio->uio_resid > 0) { 796 if (cc == 0) { 797 cc = min(uio->uio_resid, BUFSIZ); 798 cp = locbuf; 799 TTY_UNLOCK(tp); 800 splx(s); 801 error = uiomove((caddr_t)cp, cc, uio); 802 if (error) 803 return (error); 804 s = spltty(); 805 TTY_LOCK(tp); 806 /* check again for safety */ 807 if (!ISSET(tp->t_state, TS_ISOPEN)) { 808 error = EIO; 809 goto out; 810 } 811 } 812 while (cc > 0) { 813 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 814 (tp->t_canq.c_cc > 0 || !ISSET(tp->t_lflag, ICANON))) { 815 wakeup((caddr_t)&tp->t_rawq); 816 goto block; 817 } 818 /* XXX - should change l_rint to be called with lock 819 * see also tty.c:ttyinput_wlock() 820 */ 821 TTY_UNLOCK(tp); 822 splx(s); 823 (*tp->t_linesw->l_rint)(*cp++, tp); 824 s = spltty(); 825 TTY_LOCK(tp); 826 cnt++; 827 cc--; 828 } 829 cc = 0; 830 } 831 error = 0; 832 goto out; 833 834 block: 835 /* 836 * Come here to wait for slave to open, for space 837 * in outq, or space in rawq. 838 */ 839 if (!ISSET(tp->t_state, TS_CARR_ON)) { 840 error = EIO; 841 goto out; 842 } 843 if (flag & IO_NDELAY) { 844 /* adjust for data copied in but not written */ 845 uio->uio_resid += cc; 846 error = cnt == 0 ? EWOULDBLOCK : 0; 847 goto out; 848 } 849 error = ltsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH | PNORELOCK, 850 ttyout, 0, &tp->t_slock); 851 splx(s); 852 if (error) { 853 /* adjust for data copied in but not written */ 854 uio->uio_resid += cc; 855 return (error); 856 } 857 goto again; 858 859 out: 860 TTY_UNLOCK(tp); 861 splx(s); 862 return (error); 863 } 864 865 int 866 ptcpoll(dev, events, p) 867 dev_t dev; 868 int events; 869 struct proc *p; 870 { 871 struct pt_softc *pti = pt_softc[minor(dev)]; 872 struct tty *tp = pti->pt_tty; 873 int revents = 0; 874 int s = splsoftclock(); 875 876 if (events & (POLLIN | POLLRDNORM)) 877 if (ISSET(tp->t_state, TS_ISOPEN) && 878 ((tp->t_outq.c_cc > 0 && !ISSET(tp->t_state, TS_TTSTOP)) || 879 ((pti->pt_flags & PF_PKT) && pti->pt_send) || 880 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) 881 revents |= events & (POLLIN | POLLRDNORM); 882 883 if (events & (POLLOUT | POLLWRNORM)) 884 if (ISSET(tp->t_state, TS_ISOPEN) && 885 ((pti->pt_flags & PF_REMOTE) ? 886 (tp->t_canq.c_cc == 0) : 887 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) || 888 (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON))))) 889 revents |= events & (POLLOUT | POLLWRNORM); 890 891 if (events & POLLHUP) 892 if (!ISSET(tp->t_state, TS_CARR_ON)) 893 revents |= POLLHUP; 894 895 if (revents == 0) { 896 if (events & (POLLIN | POLLHUP | POLLRDNORM)) 897 selrecord(p, &pti->pt_selr); 898 899 if (events & (POLLOUT | POLLWRNORM)) 900 selrecord(p, &pti->pt_selw); 901 } 902 903 splx(s); 904 return (revents); 905 } 906 907 static void 908 filt_ptcrdetach(struct knote *kn) 909 { 910 struct pt_softc *pti; 911 int s; 912 913 pti = kn->kn_hook; 914 s = spltty(); 915 SLIST_REMOVE(&pti->pt_selr.sel_klist, kn, knote, kn_selnext); 916 splx(s); 917 } 918 919 static int 920 filt_ptcread(struct knote *kn, long hint) 921 { 922 struct pt_softc *pti; 923 struct tty *tp; 924 int canread; 925 926 pti = kn->kn_hook; 927 tp = pti->pt_tty; 928 929 canread = (ISSET(tp->t_state, TS_ISOPEN) && 930 ((tp->t_outq.c_cc > 0 && !ISSET(tp->t_state, TS_TTSTOP)) || 931 ((pti->pt_flags & PF_PKT) && pti->pt_send) || 932 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))); 933 934 if (canread) { 935 /* 936 * c_cc is number of characters after output post-processing; 937 * the amount of data actually read(2) depends on 938 * setting of input flags for the terminal. 939 */ 940 kn->kn_data = tp->t_outq.c_cc; 941 if (((pti->pt_flags & PF_PKT) && pti->pt_send) || 942 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) 943 kn->kn_data++; 944 } 945 946 return (canread); 947 } 948 949 static void 950 filt_ptcwdetach(struct knote *kn) 951 { 952 struct pt_softc *pti; 953 int s; 954 955 pti = kn->kn_hook; 956 s = spltty(); 957 SLIST_REMOVE(&pti->pt_selw.sel_klist, kn, knote, kn_selnext); 958 splx(s); 959 } 960 961 static int 962 filt_ptcwrite(struct knote *kn, long hint) 963 { 964 struct pt_softc *pti; 965 struct tty *tp; 966 int canwrite; 967 int nwrite; 968 969 pti = kn->kn_hook; 970 tp = pti->pt_tty; 971 972 canwrite = (ISSET(tp->t_state, TS_ISOPEN) && 973 ((pti->pt_flags & PF_REMOTE) ? 974 (tp->t_canq.c_cc == 0) : 975 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) || 976 (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON))))); 977 978 if (canwrite) { 979 if (pti->pt_flags & PF_REMOTE) 980 nwrite = tp->t_canq.c_cn; 981 else { 982 /* this is guaranteed to be > 0 due to above check */ 983 nwrite = tp->t_canq.c_cn 984 - (tp->t_rawq.c_cc + tp->t_canq.c_cc); 985 } 986 kn->kn_data = nwrite; 987 } 988 989 return (canwrite); 990 } 991 992 static const struct filterops ptcread_filtops = 993 { 1, NULL, filt_ptcrdetach, filt_ptcread }; 994 static const struct filterops ptcwrite_filtops = 995 { 1, NULL, filt_ptcwdetach, filt_ptcwrite }; 996 997 int 998 ptckqfilter(dev_t dev, struct knote *kn) 999 { 1000 struct pt_softc *pti = pt_softc[minor(dev)]; 1001 struct klist *klist; 1002 int s; 1003 1004 switch (kn->kn_filter) { 1005 case EVFILT_READ: 1006 klist = &pti->pt_selr.sel_klist; 1007 kn->kn_fop = &ptcread_filtops; 1008 break; 1009 case EVFILT_WRITE: 1010 klist = &pti->pt_selw.sel_klist; 1011 kn->kn_fop = &ptcwrite_filtops; 1012 break; 1013 default: 1014 return (1); 1015 } 1016 1017 kn->kn_hook = pti; 1018 1019 s = spltty(); 1020 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 1021 splx(s); 1022 1023 return (0); 1024 } 1025 1026 struct tty * 1027 ptytty(dev) 1028 dev_t dev; 1029 { 1030 struct pt_softc *pti = pt_softc[minor(dev)]; 1031 struct tty *tp = pti->pt_tty; 1032 1033 return (tp); 1034 } 1035 1036 /*ARGSUSED*/ 1037 int 1038 ptyioctl(dev, cmd, data, flag, p) 1039 dev_t dev; 1040 u_long cmd; 1041 caddr_t data; 1042 int flag; 1043 struct proc *p; 1044 { 1045 struct pt_softc *pti = pt_softc[minor(dev)]; 1046 struct tty *tp = pti->pt_tty; 1047 const struct cdevsw *cdev; 1048 u_char *cc = tp->t_cc; 1049 int stop, error, sig; 1050 int s; 1051 1052 cdev = cdevsw_lookup(dev); 1053 /* 1054 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 1055 * ttywflush(tp) will hang if there are characters in the outq. 1056 */ 1057 if (cmd == TIOCEXT) { 1058 /* 1059 * When the EXTPROC bit is being toggled, we need 1060 * to send an TIOCPKT_IOCTL if the packet driver 1061 * is turned on. 1062 */ 1063 if (*(int *)data) { 1064 if (pti->pt_flags & PF_PKT) { 1065 pti->pt_send |= TIOCPKT_IOCTL; 1066 ptcwakeup(tp, FREAD); 1067 } 1068 SET(tp->t_lflag, EXTPROC); 1069 } else { 1070 if (ISSET(tp->t_lflag, EXTPROC) && 1071 (pti->pt_flags & PF_PKT)) { 1072 pti->pt_send |= TIOCPKT_IOCTL; 1073 ptcwakeup(tp, FREAD); 1074 } 1075 CLR(tp->t_lflag, EXTPROC); 1076 } 1077 return(0); 1078 } 1079 1080 if (cdev != NULL && cdev->d_open == ptcopen) 1081 switch (cmd) { 1082 #ifdef NPTM 1083 case TIOCGRANTPT: 1084 return pty_grant_slave(p, dev); 1085 1086 case TIOCPTSNAME: 1087 pty_fill_ptmget(dev, -1, -1, data); 1088 return 0; 1089 #endif 1090 1091 case TIOCGPGRP: 1092 /* 1093 * We avoid calling ttioctl on the controller since, 1094 * in that case, tp must be the controlling terminal. 1095 */ 1096 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 1097 return (0); 1098 1099 case TIOCPKT: 1100 if (*(int *)data) { 1101 if (pti->pt_flags & PF_UCNTL) 1102 return (EINVAL); 1103 pti->pt_flags |= PF_PKT; 1104 } else 1105 pti->pt_flags &= ~PF_PKT; 1106 return (0); 1107 1108 case TIOCUCNTL: 1109 if (*(int *)data) { 1110 if (pti->pt_flags & PF_PKT) 1111 return (EINVAL); 1112 pti->pt_flags |= PF_UCNTL; 1113 } else 1114 pti->pt_flags &= ~PF_UCNTL; 1115 return (0); 1116 1117 case TIOCREMOTE: 1118 if (*(int *)data) 1119 pti->pt_flags |= PF_REMOTE; 1120 else 1121 pti->pt_flags &= ~PF_REMOTE; 1122 s = spltty(); 1123 TTY_LOCK(tp); 1124 ttyflush(tp, FREAD|FWRITE); 1125 TTY_UNLOCK(tp); 1126 splx(s); 1127 return (0); 1128 1129 #ifdef COMPAT_OLDTTY 1130 case TIOCSETP: 1131 case TIOCSETN: 1132 #endif 1133 case TIOCSETD: 1134 case TIOCSETA: 1135 case TIOCSETAW: 1136 case TIOCSETAF: 1137 TTY_LOCK(tp); 1138 ndflush(&tp->t_outq, tp->t_outq.c_cc); 1139 TTY_UNLOCK(tp); 1140 break; 1141 1142 case TIOCSIG: 1143 sig = (int)(long)*(caddr_t *)data; 1144 if (sig <= 0 || sig >= NSIG) 1145 return (EINVAL); 1146 TTY_LOCK(tp); 1147 if (!ISSET(tp->t_lflag, NOFLSH)) 1148 ttyflush(tp, FREAD|FWRITE); 1149 if ((sig == SIGINFO) && 1150 (!ISSET(tp->t_lflag, NOKERNINFO))) 1151 ttyinfo(tp); 1152 TTY_UNLOCK(tp); 1153 pgsignal(tp->t_pgrp, sig, 1); 1154 return(0); 1155 } 1156 1157 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 1158 if (error == EPASSTHROUGH) 1159 error = ttioctl(tp, cmd, data, flag, p); 1160 if (error == EPASSTHROUGH) { 1161 if (pti->pt_flags & PF_UCNTL && 1162 (cmd & ~0xff) == UIOCCMD(0)) { 1163 if (cmd & 0xff) { 1164 pti->pt_ucntl = (u_char)cmd; 1165 ptcwakeup(tp, FREAD); 1166 } 1167 return (0); 1168 } 1169 } 1170 /* 1171 * If external processing and packet mode send ioctl packet. 1172 */ 1173 if (ISSET(tp->t_lflag, EXTPROC) && (pti->pt_flags & PF_PKT)) { 1174 switch(cmd) { 1175 case TIOCSETA: 1176 case TIOCSETAW: 1177 case TIOCSETAF: 1178 #ifdef COMPAT_OLDTTY 1179 case TIOCSETP: 1180 case TIOCSETN: 1181 case TIOCSETC: 1182 case TIOCSLTC: 1183 case TIOCLBIS: 1184 case TIOCLBIC: 1185 case TIOCLSET: 1186 #endif 1187 pti->pt_send |= TIOCPKT_IOCTL; 1188 ptcwakeup(tp, FREAD); 1189 default: 1190 break; 1191 } 1192 } 1193 stop = ISSET(tp->t_iflag, IXON) && CCEQ(cc[VSTOP], CTRL('s')) 1194 && CCEQ(cc[VSTART], CTRL('q')); 1195 if (pti->pt_flags & PF_NOSTOP) { 1196 if (stop) { 1197 pti->pt_send &= ~TIOCPKT_NOSTOP; 1198 pti->pt_send |= TIOCPKT_DOSTOP; 1199 pti->pt_flags &= ~PF_NOSTOP; 1200 ptcwakeup(tp, FREAD); 1201 } 1202 } else { 1203 if (!stop) { 1204 pti->pt_send &= ~TIOCPKT_DOSTOP; 1205 pti->pt_send |= TIOCPKT_NOSTOP; 1206 pti->pt_flags |= PF_NOSTOP; 1207 ptcwakeup(tp, FREAD); 1208 } 1209 } 1210 return (error); 1211 } 1212 1213 #ifdef NPTM 1214 /* 1215 * Check if a pty is free to use. 1216 */ 1217 static __inline int 1218 pty_isfree_locked(int minor) 1219 { 1220 struct pt_softc *pt = pt_softc[minor]; 1221 return (pt == NULL || pt->pt_tty == NULL || 1222 pt->pt_tty->t_oproc == NULL); 1223 } 1224 1225 static int 1226 pty_isfree(int minor) 1227 { 1228 int isfree; 1229 1230 simple_lock(&pt_softc_mutex); 1231 isfree = pty_isfree_locked(minor); 1232 simple_unlock(&pt_softc_mutex); 1233 return(isfree); 1234 } 1235 1236 static char * 1237 pty_makename(char *buf, dev_t dev, char c) 1238 { 1239 size_t nt; 1240 dev_t minor = minor(dev); 1241 1242 (void)memcpy(buf, TTY_TEMPLATE, TTY_NAMESIZE); 1243 1244 buf[5] = c; 1245 1246 if (minor < 256) { 1247 nt = sizeof(TTY_OLD_SUFFIX) - 1; 1248 buf[8] = TTY_LETTERS[minor / nt]; 1249 buf[9] = TTY_OLD_SUFFIX[minor % nt]; 1250 } else { 1251 minor -= 256; 1252 nt = sizeof(TTY_NEW_SUFFIX) - sizeof(TTY_OLD_SUFFIX); 1253 buf[8] = TTY_LETTERS[minor / nt]; 1254 buf[9] = TTY_NEW_SUFFIX[minor % nt]; 1255 } 1256 return buf; 1257 } 1258 1259 static dev_t 1260 pty_getfree(void) 1261 { 1262 int i; 1263 1264 simple_lock(&pt_softc_mutex); 1265 for (i = 0; i < npty; i++) { 1266 if (pty_isfree_locked(i)) 1267 break; 1268 } 1269 simple_unlock(&pt_softc_mutex); 1270 return (makedev(pts_major, i)); 1271 } 1272 1273 /* 1274 * Hacked up version of vn_open. We _only_ handle ptys and only open 1275 * them with FREAD|FWRITE and never deal with creat or stuff like that. 1276 * 1277 * We need it because we have to fake up root credentials to open the pty. 1278 */ 1279 static int 1280 ptm_vn_open(struct nameidata *ndp) 1281 { 1282 struct vnode *vp; 1283 struct proc *p = ndp->ni_cnd.cn_proc; 1284 struct ucred *cred; 1285 int error; 1286 1287 if ((error = namei(ndp)) != 0) 1288 return (error); 1289 vp = ndp->ni_vp; 1290 if (vp->v_type != VCHR) { 1291 error = EINVAL; 1292 goto bad; 1293 } 1294 1295 /* 1296 * Get us a fresh cred with root privileges. 1297 */ 1298 cred = crget(); 1299 error = VOP_OPEN(vp, FREAD|FWRITE, cred, p); 1300 crfree(cred); 1301 1302 if (error) 1303 goto bad; 1304 1305 vp->v_writecount++; 1306 1307 return (0); 1308 bad: 1309 vput(vp); 1310 return (error); 1311 } 1312 1313 static int 1314 pty_alloc_master(struct proc *p, int *fd, dev_t *dev) 1315 { 1316 int error; 1317 struct nameidata nd; 1318 struct pt_softc *pti; 1319 struct file *fp; 1320 int md; 1321 char name[TTY_NAMESIZE]; 1322 1323 if ((error = falloc(p, &fp, fd)) != 0) { 1324 DPRINTF(("falloc %d\n", error)); 1325 return error; 1326 } 1327 retry: 1328 /* Find and open a free master pty. */ 1329 *dev = pty_getfree(); 1330 md = minor(*dev); 1331 if ((error = check_pty(md)) != 0) { 1332 DPRINTF(("ckeck_pty %d\n", error)); 1333 goto bad; 1334 } 1335 pti = pt_softc[md]; 1336 NDINIT(&nd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, 1337 pty_makename(name, *dev, 'p'), p); 1338 if ((error = ptm_vn_open(&nd)) != 0) { 1339 /* 1340 * Check if the master open failed because we lost 1341 * the race to grab it. 1342 */ 1343 if (error == EIO && !pty_isfree(md)) 1344 goto retry; 1345 DPRINTF(("ptm_vn_open %d\n", error)); 1346 goto bad; 1347 } 1348 fp->f_flag = FREAD|FWRITE; 1349 fp->f_type = DTYPE_VNODE; 1350 fp->f_ops = &vnops; 1351 fp->f_data = nd.ni_vp; 1352 VOP_UNLOCK(nd.ni_vp, 0); 1353 FILE_SET_MATURE(fp); 1354 FILE_UNUSE(fp, p); 1355 return 0; 1356 bad: 1357 FILE_UNUSE(fp, p); 1358 fdremove(p->p_fd, *fd); 1359 ffree(fp); 1360 return error; 1361 } 1362 1363 static int 1364 pty_grant_slave(struct proc *p, dev_t dev) 1365 { 1366 int error; 1367 struct nameidata nd; 1368 char name[TTY_NAMESIZE]; 1369 1370 /* 1371 * Open the slave. 1372 * namei -> setattr -> unlock -> revoke -> vrele -> 1373 * namei -> open -> unlock 1374 * Three stage rocket: 1375 * 1. Change the owner and permissions on the slave. 1376 * 2. Revoke all the users of the slave. 1377 * 3. open the slave. 1378 */ 1379 NDINIT(&nd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, 1380 pty_makename(name, dev, 't'), p); 1381 if ((error = namei(&nd)) != 0) { 1382 DPRINTF(("namei %d\n", error)); 1383 return error; 1384 } 1385 if ((nd.ni_vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 1386 struct vattr vattr; 1387 struct ucred *cred; 1388 gid_t gid = _TTY_GID; 1389 /* get real uid */ 1390 uid_t uid = p->p_cred->p_ruid; 1391 1392 VATTR_NULL(&vattr); 1393 vattr.va_uid = uid; 1394 vattr.va_gid = gid; 1395 vattr.va_mode = (S_IRUSR|S_IWUSR|S_IWGRP) & ALLPERMS; 1396 /* Get a fake cred to pretend we're root. */ 1397 cred = crget(); 1398 error = VOP_SETATTR(nd.ni_vp, &vattr, cred, p); 1399 crfree(cred); 1400 if (error) { 1401 DPRINTF(("setattr %d\n", error)); 1402 VOP_UNLOCK(nd.ni_vp, 0); 1403 vrele(nd.ni_vp); 1404 return error; 1405 } 1406 } 1407 VOP_UNLOCK(nd.ni_vp, 0); 1408 if (nd.ni_vp->v_usecount > 1 || 1409 (nd.ni_vp->v_flag & (VALIASED | VLAYER))) 1410 VOP_REVOKE(nd.ni_vp, REVOKEALL); 1411 1412 /* 1413 * The vnode is useless after the revoke, we need to 1414 * namei again. 1415 */ 1416 vrele(nd.ni_vp); 1417 return 0; 1418 } 1419 1420 static int 1421 pty_alloc_slave(struct proc *p, int *fd, dev_t dev) 1422 { 1423 int error; 1424 struct file *fp; 1425 struct nameidata nd; 1426 char name[TTY_NAMESIZE]; 1427 1428 /* Grab a filedescriptor for the slave */ 1429 if ((error = falloc(p, &fp, fd)) != 0) { 1430 DPRINTF(("falloc %d\n", error)); 1431 return error; 1432 } 1433 1434 NDINIT(&nd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, 1435 pty_makename(name, dev, 't'), p); 1436 1437 /* now open it */ 1438 if ((error = ptm_vn_open(&nd)) != 0) { 1439 DPRINTF(("vn_open %d\n", error)); 1440 FILE_UNUSE(fp, p); 1441 fdremove(p->p_fd, *fd); 1442 ffree(fp); 1443 return error; 1444 } 1445 fp->f_flag = FREAD|FWRITE; 1446 fp->f_type = DTYPE_VNODE; 1447 fp->f_ops = &vnops; 1448 fp->f_data = nd.ni_vp; 1449 VOP_UNLOCK(nd.ni_vp, 0); 1450 FILE_SET_MATURE(fp); 1451 FILE_UNUSE(fp, p); 1452 return 0; 1453 } 1454 1455 static void 1456 pty_fill_ptmget(dev_t dev, int cfd, int sfd, void *data) 1457 { 1458 struct ptmget *ptm = data; 1459 ptm->cfd = cfd; 1460 ptm->sfd = sfd; 1461 (void)pty_makename(ptm->cn, dev, 'p'); 1462 (void)pty_makename(ptm->sn, dev, 't'); 1463 } 1464 1465 void 1466 /*ARGSUSED*/ 1467 ptmattach(int n) 1468 { 1469 /* find the major and minor of the pty devices */ 1470 if ((pts_major = cdevsw_lookup_major(&pts_cdevsw)) == -1) 1471 panic("ptmattach: Can't find pty slave in cdevsw"); 1472 } 1473 1474 int 1475 /*ARGSUSED*/ 1476 ptmopen(dev_t dev, int flag, int mode, struct proc *p) 1477 { 1478 int error; 1479 int fd; 1480 1481 switch(minor(dev)) { 1482 case 0: /* /dev/ptmx */ 1483 if ((error = pty_alloc_master(p, &fd, &dev)) != 0) 1484 return error; 1485 curlwp->l_dupfd = fd; 1486 return ENXIO; 1487 case 1: /* /dev/ptm */ 1488 return 0; 1489 default: 1490 return ENODEV; 1491 } 1492 1493 } 1494 1495 int 1496 /*ARGSUSED*/ 1497 ptmclose(dev_t dev, int flag, int mode, struct proc *p) 1498 { 1499 return (0); 1500 } 1501 1502 int 1503 /*ARGSUSED*/ 1504 ptmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 1505 { 1506 int error; 1507 dev_t newdev; 1508 int cfd, sfd; 1509 struct file *fp; 1510 1511 error = 0; 1512 switch (cmd) { 1513 case TIOCPTMGET: 1514 if ((error = pty_alloc_master(p, &cfd, &newdev)) != 0) 1515 return error; 1516 1517 if ((error = pty_grant_slave(p, newdev)) != 0) 1518 goto bad; 1519 1520 if ((error = pty_alloc_slave(p, &sfd, newdev)) != 0) 1521 goto bad; 1522 1523 /* now, put the indices and names into struct ptmget */ 1524 pty_fill_ptmget(newdev, cfd, sfd, data); 1525 return 0; 1526 default: 1527 DPRINTF(("ptmioctl EINVAL\n")); 1528 return EINVAL; 1529 } 1530 bad: 1531 fp = fd_getfile(p->p_fd, cfd); 1532 fdremove(p->p_fd, cfd); 1533 ffree(fp); 1534 return error; 1535 } 1536 #endif 1537