pty.c revision 115463
1/* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 34 * $FreeBSD: head/sys/kern/tty_pty.c 115463 2003-05-31 16:53:16Z phk $ 35 */ 36 37/* 38 * Pseudo-teletype Driver 39 * (Actually two drivers, requiring two entries in 'cdevsw') 40 */ 41#include "opt_compat.h" 42#include "opt_tty.h" 43#include <sys/param.h> 44#include <sys/systm.h> 45#include <sys/lock.h> 46#include <sys/mutex.h> 47#include <sys/sx.h> 48#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 49#include <sys/ioctl_compat.h> 50#endif 51#include <sys/proc.h> 52#include <sys/tty.h> 53#include <sys/conf.h> 54#include <sys/fcntl.h> 55#include <sys/poll.h> 56#include <sys/kernel.h> 57#include <sys/vnode.h> 58#include <sys/signalvar.h> 59#include <sys/malloc.h> 60 61static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures"); 62 63static void ptsstart(struct tty *tp); 64static void ptsstop(struct tty *tp, int rw); 65static void ptcwakeup(struct tty *tp, int flag); 66static dev_t ptyinit(dev_t cdev); 67 68static d_open_t ptsopen; 69static d_close_t ptsclose; 70static d_read_t ptsread; 71static d_write_t ptswrite; 72static d_ioctl_t ptyioctl; 73static d_open_t ptcopen; 74static d_close_t ptcclose; 75static d_read_t ptcread; 76static d_write_t ptcwrite; 77static d_poll_t ptcpoll; 78 79#define CDEV_MAJOR_S 5 80static struct cdevsw pts_cdevsw = { 81 .d_open = ptsopen, 82 .d_close = ptsclose, 83 .d_read = ptsread, 84 .d_write = ptswrite, 85 .d_ioctl = ptyioctl, 86 .d_poll = ttypoll, 87 .d_name = "pts", 88 .d_maj = CDEV_MAJOR_S, 89 .d_flags = D_TTY, 90 .d_kqfilter = ttykqfilter, 91}; 92 93#define CDEV_MAJOR_C 6 94static struct cdevsw ptc_cdevsw = { 95 .d_open = ptcopen, 96 .d_close = ptcclose, 97 .d_read = ptcread, 98 .d_write = ptcwrite, 99 .d_ioctl = ptyioctl, 100 .d_poll = ptcpoll, 101 .d_name = "ptc", 102 .d_maj = CDEV_MAJOR_C, 103 .d_flags = D_TTY, 104 .d_kqfilter = ttykqfilter, 105}; 106 107#define BUFSIZ 100 /* Chunk size iomoved to/from user */ 108 109struct pt_ioctl { 110 int pt_flags; 111 struct selinfo pt_selr, pt_selw; 112 u_char pt_send; 113 u_char pt_ucntl; 114 struct tty pt_tty; 115 dev_t devs, devc; 116 struct prison *pt_prison; 117}; 118 119#define PF_PKT 0x08 /* packet mode */ 120#define PF_STOPPED 0x10 /* user told stopped */ 121#define PF_REMOTE 0x20 /* remote and flow controlled input */ 122#define PF_NOSTOP 0x40 123#define PF_UCNTL 0x80 /* user control mode */ 124 125static char *names = "pqrsPQRS"; 126/* 127 * This function creates and initializes a pts/ptc pair 128 * 129 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 130 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 131 * 132 * XXX: define and add mapping of upper minor bits to allow more 133 * than 256 ptys. 134 */ 135static dev_t 136ptyinit(dev_t devc) 137{ 138 dev_t devs; 139 struct pt_ioctl *pt; 140 int n; 141 142 n = minor(devc); 143 /* For now we only map the lower 8 bits of the minor */ 144 if (n & ~0xff) 145 return (NODEV); 146 147 devc->si_flags &= ~SI_CHEAPCLONE; 148 149 pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO); 150 pt->devs = devs = make_dev(&pts_cdevsw, n, 151 UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32); 152 pt->devc = devc; 153 154 devs->si_drv1 = devc->si_drv1 = pt; 155 devs->si_tty = devc->si_tty = &pt->pt_tty; 156 pt->pt_tty.t_dev = devs; 157 ttyregister(&pt->pt_tty); 158 return (devc); 159} 160 161/*ARGSUSED*/ 162static int 163ptsopen(dev, flag, devtype, td) 164 dev_t dev; 165 int flag, devtype; 166 struct thread *td; 167{ 168 struct tty *tp; 169 int error; 170 struct pt_ioctl *pti; 171 172 if (!dev->si_drv1) 173 return(ENXIO); 174 pti = dev->si_drv1; 175 tp = dev->si_tty; 176 if ((tp->t_state & TS_ISOPEN) == 0) { 177 ttychars(tp); /* Set up default chars */ 178 tp->t_iflag = TTYDEF_IFLAG; 179 tp->t_oflag = TTYDEF_OFLAG; 180 tp->t_lflag = TTYDEF_LFLAG; 181 tp->t_cflag = TTYDEF_CFLAG; 182 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 183 } else if (tp->t_state & TS_XCLUDE && suser(td)) { 184 return (EBUSY); 185 } else if (pti->pt_prison != td->td_ucred->cr_prison) { 186 return (EBUSY); 187 } 188 if (tp->t_oproc) /* Ctrlr still around. */ 189 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 190 while ((tp->t_state & TS_CARR_ON) == 0) { 191 if (flag&FNONBLOCK) 192 break; 193 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, 194 "ptsopn", 0); 195 if (error) 196 return (error); 197 } 198 error = (*linesw[tp->t_line].l_open)(dev, tp); 199 if (error == 0) 200 ptcwakeup(tp, FREAD|FWRITE); 201 return (error); 202} 203 204static int 205ptsclose(dev, flag, mode, td) 206 dev_t dev; 207 int flag, mode; 208 struct thread *td; 209{ 210 struct tty *tp; 211 int err; 212 213 tp = dev->si_tty; 214 err = (*linesw[tp->t_line].l_close)(tp, flag); 215 ptsstop(tp, FREAD|FWRITE); 216 (void) ttyclose(tp); 217 return (err); 218} 219 220static int 221ptsread(dev, uio, flag) 222 dev_t dev; 223 struct uio *uio; 224 int flag; 225{ 226 struct thread *td = curthread; 227 struct proc *p = td->td_proc; 228 struct tty *tp = dev->si_tty; 229 struct pt_ioctl *pti = dev->si_drv1; 230 struct pgrp *pg; 231 int error = 0; 232 233again: 234 if (pti->pt_flags & PF_REMOTE) { 235 while (isbackground(p, tp)) { 236 sx_slock(&proctree_lock); 237 PROC_LOCK(p); 238 if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) || 239 SIGISMEMBER(td->td_sigmask, SIGTTIN) || 240 p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) { 241 PROC_UNLOCK(p); 242 sx_sunlock(&proctree_lock); 243 return (EIO); 244 } 245 pg = p->p_pgrp; 246 PROC_UNLOCK(p); 247 PGRP_LOCK(pg); 248 sx_sunlock(&proctree_lock); 249 pgsignal(pg, SIGTTIN, 1); 250 PGRP_UNLOCK(pg); 251 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg", 252 0); 253 if (error) 254 return (error); 255 } 256 if (tp->t_canq.c_cc == 0) { 257 if (flag & IO_NDELAY) 258 return (EWOULDBLOCK); 259 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH, 260 "ptsin", 0); 261 if (error) 262 return (error); 263 goto again; 264 } 265 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 266 if (ureadc(getc(&tp->t_canq), uio) < 0) { 267 error = EFAULT; 268 break; 269 } 270 if (tp->t_canq.c_cc == 1) 271 (void) getc(&tp->t_canq); 272 if (tp->t_canq.c_cc) 273 return (error); 274 } else 275 if (tp->t_oproc) 276 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 277 ptcwakeup(tp, FWRITE); 278 return (error); 279} 280 281/* 282 * Write to pseudo-tty. 283 * Wakeups of controlling tty will happen 284 * indirectly, when tty driver calls ptsstart. 285 */ 286static int 287ptswrite(dev, uio, flag) 288 dev_t dev; 289 struct uio *uio; 290 int flag; 291{ 292 struct tty *tp; 293 294 tp = dev->si_tty; 295 if (tp->t_oproc == 0) 296 return (EIO); 297 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 298} 299 300/* 301 * Start output on pseudo-tty. 302 * Wake up process selecting or sleeping for input from controlling tty. 303 */ 304static void 305ptsstart(tp) 306 struct tty *tp; 307{ 308 struct pt_ioctl *pti = tp->t_dev->si_drv1; 309 310 if (tp->t_state & TS_TTSTOP) 311 return; 312 if (pti->pt_flags & PF_STOPPED) { 313 pti->pt_flags &= ~PF_STOPPED; 314 pti->pt_send = TIOCPKT_START; 315 } 316 ptcwakeup(tp, FREAD); 317} 318 319static void 320ptcwakeup(tp, flag) 321 struct tty *tp; 322 int flag; 323{ 324 struct pt_ioctl *pti = tp->t_dev->si_drv1; 325 326 if (flag & FREAD) { 327 selwakeup(&pti->pt_selr); 328 wakeup(TSA_PTC_READ(tp)); 329 } 330 if (flag & FWRITE) { 331 selwakeup(&pti->pt_selw); 332 wakeup(TSA_PTC_WRITE(tp)); 333 } 334} 335 336static int 337ptcopen(dev, flag, devtype, td) 338 dev_t dev; 339 int flag, devtype; 340 struct thread *td; 341{ 342 struct tty *tp; 343 struct pt_ioctl *pti; 344 345 if (!dev->si_drv1) 346 ptyinit(dev); 347 if (!dev->si_drv1) 348 return(ENXIO); 349 tp = dev->si_tty; 350 if (tp->t_oproc) 351 return (EIO); 352 tp->t_timeout = -1; 353 tp->t_oproc = ptsstart; 354 tp->t_stop = ptsstop; 355 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 356 tp->t_lflag &= ~EXTPROC; 357 pti = dev->si_drv1; 358 pti->pt_prison = td->td_ucred->cr_prison; 359 pti->pt_flags = 0; 360 pti->pt_send = 0; 361 pti->pt_ucntl = 0; 362 return (0); 363} 364 365static int 366ptcclose(dev, flags, fmt, td) 367 dev_t dev; 368 int flags; 369 int fmt; 370 struct thread *td; 371{ 372 struct tty *tp; 373 374 tp = dev->si_tty; 375 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 376 377 /* 378 * XXX MDMBUF makes no sense for ptys but would inhibit the above 379 * l_modem(). CLOCAL makes sense but isn't supported. Special 380 * l_modem()s that ignore carrier drop make no sense for ptys but 381 * may be in use because other parts of the line discipline make 382 * sense for ptys. Recover by doing everything that a normal 383 * ttymodem() would have done except for sending a SIGHUP. 384 */ 385 if (tp->t_state & TS_ISOPEN) { 386 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED); 387 tp->t_state |= TS_ZOMBIE; 388 ttyflush(tp, FREAD | FWRITE); 389 } 390 391 tp->t_oproc = 0; /* mark closed */ 392 return (0); 393} 394 395static int 396ptcread(dev, uio, flag) 397 dev_t dev; 398 struct uio *uio; 399 int flag; 400{ 401 struct tty *tp = dev->si_tty; 402 struct pt_ioctl *pti = dev->si_drv1; 403 char buf[BUFSIZ]; 404 int error = 0, cc; 405 406 /* 407 * We want to block until the slave 408 * is open, and there's something to read; 409 * but if we lost the slave or we're NBIO, 410 * then return the appropriate error instead. 411 */ 412 for (;;) { 413 if (tp->t_state&TS_ISOPEN) { 414 if (pti->pt_flags&PF_PKT && pti->pt_send) { 415 error = ureadc((int)pti->pt_send, uio); 416 if (error) 417 return (error); 418 if (pti->pt_send & TIOCPKT_IOCTL) { 419 cc = min(uio->uio_resid, 420 sizeof(tp->t_termios)); 421 uiomove(&tp->t_termios, cc, uio); 422 } 423 pti->pt_send = 0; 424 return (0); 425 } 426 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 427 error = ureadc((int)pti->pt_ucntl, uio); 428 if (error) 429 return (error); 430 pti->pt_ucntl = 0; 431 return (0); 432 } 433 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 434 break; 435 } 436 if ((tp->t_state & TS_CONNECTED) == 0) 437 return (0); /* EOF */ 438 if (flag & IO_NDELAY) 439 return (EWOULDBLOCK); 440 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0); 441 if (error) 442 return (error); 443 } 444 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 445 error = ureadc(0, uio); 446 while (uio->uio_resid > 0 && error == 0) { 447 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ)); 448 if (cc <= 0) 449 break; 450 error = uiomove(buf, cc, uio); 451 } 452 ttwwakeup(tp); 453 return (error); 454} 455 456static void 457ptsstop(tp, flush) 458 struct tty *tp; 459 int flush; 460{ 461 struct pt_ioctl *pti = tp->t_dev->si_drv1; 462 int flag; 463 464 /* note: FLUSHREAD and FLUSHWRITE already ok */ 465 if (flush == 0) { 466 flush = TIOCPKT_STOP; 467 pti->pt_flags |= PF_STOPPED; 468 } else 469 pti->pt_flags &= ~PF_STOPPED; 470 pti->pt_send |= flush; 471 /* change of perspective */ 472 flag = 0; 473 if (flush & FREAD) 474 flag |= FWRITE; 475 if (flush & FWRITE) 476 flag |= FREAD; 477 ptcwakeup(tp, flag); 478} 479 480static int 481ptcpoll(dev, events, td) 482 dev_t dev; 483 int events; 484 struct thread *td; 485{ 486 struct tty *tp = dev->si_tty; 487 struct pt_ioctl *pti = dev->si_drv1; 488 int revents = 0; 489 int s; 490 491 if ((tp->t_state & TS_CONNECTED) == 0) 492 return (seltrue(dev, events, td) | POLLHUP); 493 494 /* 495 * Need to block timeouts (ttrstart). 496 */ 497 s = spltty(); 498 499 if (events & (POLLIN | POLLRDNORM)) 500 if ((tp->t_state & TS_ISOPEN) && 501 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) || 502 ((pti->pt_flags & PF_PKT) && pti->pt_send) || 503 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) 504 revents |= events & (POLLIN | POLLRDNORM); 505 506 if (events & (POLLOUT | POLLWRNORM)) 507 if (tp->t_state & TS_ISOPEN && 508 ((pti->pt_flags & PF_REMOTE) ? 509 (tp->t_canq.c_cc == 0) : 510 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) || 511 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON))))) 512 revents |= events & (POLLOUT | POLLWRNORM); 513 514 if (events & POLLHUP) 515 if ((tp->t_state & TS_CARR_ON) == 0) 516 revents |= POLLHUP; 517 518 if (revents == 0) { 519 if (events & (POLLIN | POLLRDNORM)) 520 selrecord(td, &pti->pt_selr); 521 522 if (events & (POLLOUT | POLLWRNORM)) 523 selrecord(td, &pti->pt_selw); 524 } 525 splx(s); 526 527 return (revents); 528} 529 530static int 531ptcwrite(dev, uio, flag) 532 dev_t dev; 533 struct uio *uio; 534 int flag; 535{ 536 struct tty *tp = dev->si_tty; 537 u_char *cp = 0; 538 int cc = 0; 539 u_char locbuf[BUFSIZ]; 540 int cnt = 0; 541 struct pt_ioctl *pti = dev->si_drv1; 542 int error = 0; 543 544again: 545 if ((tp->t_state&TS_ISOPEN) == 0) 546 goto block; 547 if (pti->pt_flags & PF_REMOTE) { 548 if (tp->t_canq.c_cc) 549 goto block; 550 while ((uio->uio_resid > 0 || cc > 0) && 551 tp->t_canq.c_cc < TTYHOG - 1) { 552 if (cc == 0) { 553 cc = min(uio->uio_resid, BUFSIZ); 554 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 555 cp = locbuf; 556 error = uiomove(cp, cc, uio); 557 if (error) 558 return (error); 559 /* check again for safety */ 560 if ((tp->t_state & TS_ISOPEN) == 0) { 561 /* adjust as usual */ 562 uio->uio_resid += cc; 563 return (EIO); 564 } 565 } 566 if (cc > 0) { 567 cc = b_to_q((char *)cp, cc, &tp->t_canq); 568 /* 569 * XXX we don't guarantee that the canq size 570 * is >= TTYHOG, so the above b_to_q() may 571 * leave some bytes uncopied. However, space 572 * is guaranteed for the null terminator if 573 * we don't fail here since (TTYHOG - 1) is 574 * not a multiple of CBSIZE. 575 */ 576 if (cc > 0) 577 break; 578 } 579 } 580 /* adjust for data copied in but not written */ 581 uio->uio_resid += cc; 582 (void) putc(0, &tp->t_canq); 583 ttwakeup(tp); 584 wakeup(TSA_PTS_READ(tp)); 585 return (0); 586 } 587 while (uio->uio_resid > 0 || cc > 0) { 588 if (cc == 0) { 589 cc = min(uio->uio_resid, BUFSIZ); 590 cp = locbuf; 591 error = uiomove(cp, cc, uio); 592 if (error) 593 return (error); 594 /* check again for safety */ 595 if ((tp->t_state & TS_ISOPEN) == 0) { 596 /* adjust for data copied in but not written */ 597 uio->uio_resid += cc; 598 return (EIO); 599 } 600 } 601 while (cc > 0) { 602 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 603 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) { 604 wakeup(TSA_HUP_OR_INPUT(tp)); 605 goto block; 606 } 607 (*linesw[tp->t_line].l_rint)(*cp++, tp); 608 cnt++; 609 cc--; 610 } 611 cc = 0; 612 } 613 return (0); 614block: 615 /* 616 * Come here to wait for slave to open, for space 617 * in outq, or space in rawq, or an empty canq. 618 */ 619 if ((tp->t_state & TS_CONNECTED) == 0) { 620 /* adjust for data copied in but not written */ 621 uio->uio_resid += cc; 622 return (EIO); 623 } 624 if (flag & IO_NDELAY) { 625 /* adjust for data copied in but not written */ 626 uio->uio_resid += cc; 627 if (cnt == 0) 628 return (EWOULDBLOCK); 629 return (0); 630 } 631 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0); 632 if (error) { 633 /* adjust for data copied in but not written */ 634 uio->uio_resid += cc; 635 return (error); 636 } 637 goto again; 638} 639 640/*ARGSUSED*/ 641static int 642ptyioctl(dev, cmd, data, flag, td) 643 dev_t dev; 644 u_long cmd; 645 caddr_t data; 646 int flag; 647 struct thread *td; 648{ 649 struct tty *tp = dev->si_tty; 650 struct pt_ioctl *pti = dev->si_drv1; 651 u_char *cc = tp->t_cc; 652 int stop, error; 653 654 if (devsw(dev)->d_open == ptcopen) { 655 switch (cmd) { 656 657 case TIOCGPGRP: 658 /* 659 * We avoid calling ttioctl on the controller since, 660 * in that case, tp must be the controlling terminal. 661 */ 662 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 663 return (0); 664 665 case TIOCPKT: 666 if (*(int *)data) { 667 if (pti->pt_flags & PF_UCNTL) 668 return (EINVAL); 669 pti->pt_flags |= PF_PKT; 670 } else 671 pti->pt_flags &= ~PF_PKT; 672 return (0); 673 674 case TIOCUCNTL: 675 if (*(int *)data) { 676 if (pti->pt_flags & PF_PKT) 677 return (EINVAL); 678 pti->pt_flags |= PF_UCNTL; 679 } else 680 pti->pt_flags &= ~PF_UCNTL; 681 return (0); 682 683 case TIOCREMOTE: 684 if (*(int *)data) 685 pti->pt_flags |= PF_REMOTE; 686 else 687 pti->pt_flags &= ~PF_REMOTE; 688 ttyflush(tp, FREAD|FWRITE); 689 return (0); 690 } 691 692 /* 693 * The rest of the ioctls shouldn't be called until 694 * the slave is open. 695 */ 696 if ((tp->t_state & TS_ISOPEN) == 0) 697 return (EAGAIN); 698 699 switch (cmd) { 700#ifdef COMPAT_43 701 case TIOCSETP: 702 case TIOCSETN: 703#endif 704 case TIOCSETD: 705 case TIOCSETA: 706 case TIOCSETAW: 707 case TIOCSETAF: 708 /* 709 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 710 * ttywflush(tp) will hang if there are characters in 711 * the outq. 712 */ 713 ndflush(&tp->t_outq, tp->t_outq.c_cc); 714 break; 715 716 case TIOCSIG: 717 if (*(unsigned int *)data >= NSIG || 718 *(unsigned int *)data == 0) 719 return(EINVAL); 720 if ((tp->t_lflag&NOFLSH) == 0) 721 ttyflush(tp, FREAD|FWRITE); 722 if (tp->t_pgrp != NULL) { 723 PGRP_LOCK(tp->t_pgrp); 724 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 725 PGRP_UNLOCK(tp->t_pgrp); 726 } 727 if ((*(unsigned int *)data == SIGINFO) && 728 ((tp->t_lflag&NOKERNINFO) == 0)) 729 ttyinfo(tp); 730 return(0); 731 } 732 } 733 if (cmd == TIOCEXT) { 734 /* 735 * When the EXTPROC bit is being toggled, we need 736 * to send an TIOCPKT_IOCTL if the packet driver 737 * is turned on. 738 */ 739 if (*(int *)data) { 740 if (pti->pt_flags & PF_PKT) { 741 pti->pt_send |= TIOCPKT_IOCTL; 742 ptcwakeup(tp, FREAD); 743 } 744 tp->t_lflag |= EXTPROC; 745 } else { 746 if ((tp->t_lflag & EXTPROC) && 747 (pti->pt_flags & PF_PKT)) { 748 pti->pt_send |= TIOCPKT_IOCTL; 749 ptcwakeup(tp, FREAD); 750 } 751 tp->t_lflag &= ~EXTPROC; 752 } 753 return(0); 754 } 755 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 756 if (error == ENOIOCTL) 757 error = ttioctl(tp, cmd, data, flag); 758 if (error == ENOIOCTL) { 759 if (pti->pt_flags & PF_UCNTL && 760 (cmd & ~0xff) == UIOCCMD(0)) { 761 if (cmd & 0xff) { 762 pti->pt_ucntl = (u_char)cmd; 763 ptcwakeup(tp, FREAD); 764 } 765 return (0); 766 } 767 error = ENOTTY; 768 } 769 /* 770 * If external processing and packet mode send ioctl packet. 771 */ 772 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 773 switch(cmd) { 774 case TIOCSETA: 775 case TIOCSETAW: 776 case TIOCSETAF: 777#ifdef COMPAT_43 778 case TIOCSETP: 779 case TIOCSETN: 780#endif 781#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 782 case TIOCSETC: 783 case TIOCSLTC: 784 case TIOCLBIS: 785 case TIOCLBIC: 786 case TIOCLSET: 787#endif 788 pti->pt_send |= TIOCPKT_IOCTL; 789 ptcwakeup(tp, FREAD); 790 break; 791 default: 792 break; 793 } 794 } 795 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 796 && CCEQ(cc[VSTART], CTRL('q')); 797 if (pti->pt_flags & PF_NOSTOP) { 798 if (stop) { 799 pti->pt_send &= ~TIOCPKT_NOSTOP; 800 pti->pt_send |= TIOCPKT_DOSTOP; 801 pti->pt_flags &= ~PF_NOSTOP; 802 ptcwakeup(tp, FREAD); 803 } 804 } else { 805 if (!stop) { 806 pti->pt_send &= ~TIOCPKT_DOSTOP; 807 pti->pt_send |= TIOCPKT_NOSTOP; 808 pti->pt_flags |= PF_NOSTOP; 809 ptcwakeup(tp, FREAD); 810 } 811 } 812 return (error); 813} 814 815 816static void ptc_drvinit(void *unused); 817 818static void pty_clone(void *arg, char *name, int namelen, dev_t *dev); 819 820static void 821pty_clone(arg, name, namelen, dev) 822 void *arg; 823 char *name; 824 int namelen; 825 dev_t *dev; 826{ 827 int u; 828 829 if (*dev != NODEV) 830 return; 831 if (bcmp(name, "pty", 3) != 0) 832 return; 833 if (name[5] != '\0') 834 return; 835 switch (name[3]) { 836 case 'p': u = 0; break; 837 case 'q': u = 32; break; 838 case 'r': u = 64; break; 839 case 's': u = 96; break; 840 case 'P': u = 128; break; 841 case 'Q': u = 160; break; 842 case 'R': u = 192; break; 843 case 'S': u = 224; break; 844 default: return; 845 } 846 if (name[4] >= '0' && name[4] <= '9') 847 u += name[4] - '0'; 848 else if (name[4] >= 'a' && name[4] <= 'v') 849 u += name[4] - 'a' + 10; 850 else 851 return; 852 *dev = make_dev(&ptc_cdevsw, u, 853 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32); 854 (*dev)->si_flags |= SI_CHEAPCLONE; 855 return; 856} 857 858static void 859ptc_drvinit(unused) 860 void *unused; 861{ 862 863 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000); 864} 865 866SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL) 867