pty.c revision 126080
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 */ 35 36#include <sys/cdefs.h> 37__FBSDID("$FreeBSD: head/sys/kern/tty_pty.c 126080 2004-02-21 21:10:55Z phk $"); 38 39/* 40 * Pseudo-teletype Driver 41 * (Actually two drivers, requiring two entries in 'cdevsw') 42 */ 43#include "opt_compat.h" 44#include "opt_tty.h" 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/lock.h> 48#include <sys/mutex.h> 49#include <sys/sx.h> 50#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 51#include <sys/ioctl_compat.h> 52#endif 53#include <sys/proc.h> 54#include <sys/tty.h> 55#include <sys/conf.h> 56#include <sys/fcntl.h> 57#include <sys/poll.h> 58#include <sys/kernel.h> 59#include <sys/vnode.h> 60#include <sys/signalvar.h> 61#include <sys/malloc.h> 62 63static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures"); 64 65static void ptsstart(struct tty *tp); 66static void ptsstop(struct tty *tp, int rw); 67static void ptcwakeup(struct tty *tp, int flag); 68static dev_t ptyinit(dev_t cdev); 69 70static d_open_t ptsopen; 71static d_close_t ptsclose; 72static d_read_t ptsread; 73static d_write_t ptswrite; 74static d_ioctl_t ptyioctl; 75static d_open_t ptcopen; 76static d_close_t ptcclose; 77static d_read_t ptcread; 78static d_write_t ptcwrite; 79static d_poll_t ptcpoll; 80 81#define CDEV_MAJOR_S 5 82static struct cdevsw pts_cdevsw = { 83 .d_version = D_VERSION, 84 .d_open = ptsopen, 85 .d_close = ptsclose, 86 .d_read = ptsread, 87 .d_write = ptswrite, 88 .d_ioctl = ptyioctl, 89 .d_name = "pts", 90 .d_maj = CDEV_MAJOR_S, 91 .d_flags = D_TTY | D_NEEDGIANT, 92}; 93 94#define CDEV_MAJOR_C 6 95static struct cdevsw ptc_cdevsw = { 96 .d_version = D_VERSION, 97 .d_open = ptcopen, 98 .d_close = ptcclose, 99 .d_read = ptcread, 100 .d_write = ptcwrite, 101 .d_ioctl = ptyioctl, 102 .d_poll = ptcpoll, 103 .d_name = "ptc", 104 .d_maj = CDEV_MAJOR_C, 105 .d_flags = D_TTY | D_NEEDGIANT, 106}; 107 108#define BUFSIZ 100 /* Chunk size iomoved to/from user */ 109 110struct pt_ioctl { 111 int pt_flags; 112 struct selinfo pt_selr, pt_selw; 113 u_char pt_send; 114 u_char pt_ucntl; 115 struct tty pt_tty; 116 dev_t devs, devc; 117 struct prison *pt_prison; 118}; 119 120#define PF_PKT 0x08 /* packet mode */ 121#define PF_STOPPED 0x10 /* user told stopped */ 122#define PF_REMOTE 0x20 /* remote and flow controlled input */ 123#define PF_NOSTOP 0x40 124#define PF_UCNTL 0x80 /* user control mode */ 125 126static char *names = "pqrsPQRS"; 127/* 128 * This function creates and initializes a pts/ptc pair 129 * 130 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 131 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv] 132 * 133 * XXX: define and add mapping of upper minor bits to allow more 134 * than 256 ptys. 135 */ 136static dev_t 137ptyinit(dev_t devc) 138{ 139 dev_t devs; 140 struct pt_ioctl *pt; 141 int n; 142 143 n = minor(devc); 144 /* For now we only map the lower 8 bits of the minor */ 145 if (n & ~0xff) 146 return (NODEV); 147 148 devc->si_flags &= ~SI_CHEAPCLONE; 149 150 pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO); 151 pt->devs = devs = make_dev(&pts_cdevsw, n, 152 UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32); 153 pt->devc = devc; 154 155 devs->si_drv1 = devc->si_drv1 = pt; 156 devs->si_tty = devc->si_tty = &pt->pt_tty; 157 pt->pt_tty.t_dev = devs; 158 ttyregister(&pt->pt_tty); 159 return (devc); 160} 161 162/*ARGSUSED*/ 163static int 164ptsopen(dev, flag, devtype, td) 165 dev_t dev; 166 int flag, devtype; 167 struct thread *td; 168{ 169 struct tty *tp; 170 int error; 171 struct pt_ioctl *pti; 172 173 if (!dev->si_drv1) 174 return(ENXIO); 175 pti = dev->si_drv1; 176 tp = dev->si_tty; 177 if ((tp->t_state & TS_ISOPEN) == 0) { 178 ttychars(tp); /* Set up default chars */ 179 tp->t_iflag = TTYDEF_IFLAG; 180 tp->t_oflag = TTYDEF_OFLAG; 181 tp->t_lflag = TTYDEF_LFLAG; 182 tp->t_cflag = TTYDEF_CFLAG; 183 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 184 } else if (tp->t_state & TS_XCLUDE && suser(td)) 185 return (EBUSY); 186 else if (pti->pt_prison != td->td_ucred->cr_prison) 187 return (EBUSY); 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 selwakeuppri(&pti->pt_selr, TTIPRI); 328 wakeup(TSA_PTC_READ(tp)); 329 } 330 if (flag & FWRITE) { 331 selwakeuppri(&pti->pt_selw, TTOPRI); 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 (events & 493 (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)); 494 495 /* 496 * Need to block timeouts (ttrstart). 497 */ 498 s = spltty(); 499 500 if (events & (POLLIN | POLLRDNORM)) 501 if ((tp->t_state & TS_ISOPEN) && 502 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) || 503 ((pti->pt_flags & PF_PKT) && pti->pt_send) || 504 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) 505 revents |= events & (POLLIN | POLLRDNORM); 506 507 if (events & (POLLOUT | POLLWRNORM)) 508 if (tp->t_state & TS_ISOPEN && 509 ((pti->pt_flags & PF_REMOTE) ? 510 (tp->t_canq.c_cc == 0) : 511 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) || 512 (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON))))) 513 revents |= events & (POLLOUT | POLLWRNORM); 514 515 if (events & POLLHUP) 516 if ((tp->t_state & TS_CARR_ON) == 0) 517 revents |= POLLHUP; 518 519 if (revents == 0) { 520 if (events & (POLLIN | POLLRDNORM)) 521 selrecord(td, &pti->pt_selr); 522 523 if (events & (POLLOUT | POLLWRNORM)) 524 selrecord(td, &pti->pt_selw); 525 } 526 splx(s); 527 528 return (revents); 529} 530 531static int 532ptcwrite(dev, uio, flag) 533 dev_t dev; 534 struct uio *uio; 535 int flag; 536{ 537 struct tty *tp = dev->si_tty; 538 u_char *cp = 0; 539 int cc = 0; 540 u_char locbuf[BUFSIZ]; 541 int cnt = 0; 542 struct pt_ioctl *pti = dev->si_drv1; 543 int error = 0; 544 545again: 546 if ((tp->t_state&TS_ISOPEN) == 0) 547 goto block; 548 if (pti->pt_flags & PF_REMOTE) { 549 if (tp->t_canq.c_cc) 550 goto block; 551 while ((uio->uio_resid > 0 || cc > 0) && 552 tp->t_canq.c_cc < TTYHOG - 1) { 553 if (cc == 0) { 554 cc = min(uio->uio_resid, BUFSIZ); 555 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 556 cp = locbuf; 557 error = uiomove(cp, cc, uio); 558 if (error) 559 return (error); 560 /* check again for safety */ 561 if ((tp->t_state & TS_ISOPEN) == 0) { 562 /* adjust as usual */ 563 uio->uio_resid += cc; 564 return (EIO); 565 } 566 } 567 if (cc > 0) { 568 cc = b_to_q((char *)cp, cc, &tp->t_canq); 569 /* 570 * XXX we don't guarantee that the canq size 571 * is >= TTYHOG, so the above b_to_q() may 572 * leave some bytes uncopied. However, space 573 * is guaranteed for the null terminator if 574 * we don't fail here since (TTYHOG - 1) is 575 * not a multiple of CBSIZE. 576 */ 577 if (cc > 0) 578 break; 579 } 580 } 581 /* adjust for data copied in but not written */ 582 uio->uio_resid += cc; 583 (void) putc(0, &tp->t_canq); 584 ttwakeup(tp); 585 wakeup(TSA_PTS_READ(tp)); 586 return (0); 587 } 588 while (uio->uio_resid > 0 || cc > 0) { 589 if (cc == 0) { 590 cc = min(uio->uio_resid, BUFSIZ); 591 cp = locbuf; 592 error = uiomove(cp, cc, uio); 593 if (error) 594 return (error); 595 /* check again for safety */ 596 if ((tp->t_state & TS_ISOPEN) == 0) { 597 /* adjust for data copied in but not written */ 598 uio->uio_resid += cc; 599 return (EIO); 600 } 601 } 602 while (cc > 0) { 603 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 604 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) { 605 wakeup(TSA_HUP_OR_INPUT(tp)); 606 goto block; 607 } 608 (*linesw[tp->t_line].l_rint)(*cp++, tp); 609 cnt++; 610 cc--; 611 } 612 cc = 0; 613 } 614 return (0); 615block: 616 /* 617 * Come here to wait for slave to open, for space 618 * in outq, or space in rawq, or an empty canq. 619 */ 620 if ((tp->t_state & TS_CONNECTED) == 0) { 621 /* adjust for data copied in but not written */ 622 uio->uio_resid += cc; 623 return (EIO); 624 } 625 if (flag & IO_NDELAY) { 626 /* adjust for data copied in but not written */ 627 uio->uio_resid += cc; 628 if (cnt == 0) 629 return (EWOULDBLOCK); 630 return (0); 631 } 632 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0); 633 if (error) { 634 /* adjust for data copied in but not written */ 635 uio->uio_resid += cc; 636 return (error); 637 } 638 goto again; 639} 640 641/*ARGSUSED*/ 642static int 643ptyioctl(dev, cmd, data, flag, td) 644 dev_t dev; 645 u_long cmd; 646 caddr_t data; 647 int flag; 648 struct thread *td; 649{ 650 struct tty *tp = dev->si_tty; 651 struct pt_ioctl *pti = dev->si_drv1; 652 u_char *cc = tp->t_cc; 653 int stop, error; 654 655 if (devsw(dev)->d_open == ptcopen) { 656 switch (cmd) { 657 658 case TIOCGPGRP: 659 /* 660 * We avoid calling ttioctl on the controller since, 661 * in that case, tp must be the controlling terminal. 662 */ 663 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 664 return (0); 665 666 case TIOCPKT: 667 if (*(int *)data) { 668 if (pti->pt_flags & PF_UCNTL) 669 return (EINVAL); 670 pti->pt_flags |= PF_PKT; 671 } else 672 pti->pt_flags &= ~PF_PKT; 673 return (0); 674 675 case TIOCUCNTL: 676 if (*(int *)data) { 677 if (pti->pt_flags & PF_PKT) 678 return (EINVAL); 679 pti->pt_flags |= PF_UCNTL; 680 } else 681 pti->pt_flags &= ~PF_UCNTL; 682 return (0); 683 684 case TIOCREMOTE: 685 if (*(int *)data) 686 pti->pt_flags |= PF_REMOTE; 687 else 688 pti->pt_flags &= ~PF_REMOTE; 689 ttyflush(tp, FREAD|FWRITE); 690 return (0); 691 } 692 693 /* 694 * The rest of the ioctls shouldn't be called until 695 * the slave is open. 696 */ 697 if ((tp->t_state & TS_ISOPEN) == 0) 698 return (EAGAIN); 699 700 switch (cmd) { 701#ifdef COMPAT_43 702 case TIOCSETP: 703 case TIOCSETN: 704#endif 705 case TIOCSETD: 706 case TIOCSETA: 707 case TIOCSETAW: 708 case TIOCSETAF: 709 /* 710 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 711 * ttywflush(tp) will hang if there are characters in 712 * the outq. 713 */ 714 ndflush(&tp->t_outq, tp->t_outq.c_cc); 715 break; 716 717 case TIOCSIG: 718 if (*(unsigned int *)data >= NSIG || 719 *(unsigned int *)data == 0) 720 return(EINVAL); 721 if ((tp->t_lflag&NOFLSH) == 0) 722 ttyflush(tp, FREAD|FWRITE); 723 if (tp->t_pgrp != NULL) { 724 PGRP_LOCK(tp->t_pgrp); 725 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 726 PGRP_UNLOCK(tp->t_pgrp); 727 } 728 if ((*(unsigned int *)data == SIGINFO) && 729 ((tp->t_lflag&NOKERNINFO) == 0)) 730 ttyinfo(tp); 731 return(0); 732 } 733 } 734 if (cmd == TIOCEXT) { 735 /* 736 * When the EXTPROC bit is being toggled, we need 737 * to send an TIOCPKT_IOCTL if the packet driver 738 * is turned on. 739 */ 740 if (*(int *)data) { 741 if (pti->pt_flags & PF_PKT) { 742 pti->pt_send |= TIOCPKT_IOCTL; 743 ptcwakeup(tp, FREAD); 744 } 745 tp->t_lflag |= EXTPROC; 746 } else { 747 if ((tp->t_lflag & EXTPROC) && 748 (pti->pt_flags & PF_PKT)) { 749 pti->pt_send |= TIOCPKT_IOCTL; 750 ptcwakeup(tp, FREAD); 751 } 752 tp->t_lflag &= ~EXTPROC; 753 } 754 return(0); 755 } 756 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 757 if (error == ENOIOCTL) 758 error = ttioctl(tp, cmd, data, flag); 759 if (error == ENOIOCTL) { 760 if (pti->pt_flags & PF_UCNTL && 761 (cmd & ~0xff) == UIOCCMD(0)) { 762 if (cmd & 0xff) { 763 pti->pt_ucntl = (u_char)cmd; 764 ptcwakeup(tp, FREAD); 765 } 766 return (0); 767 } 768 error = ENOTTY; 769 } 770 /* 771 * If external processing and packet mode send ioctl packet. 772 */ 773 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 774 switch(cmd) { 775 case TIOCSETA: 776 case TIOCSETAW: 777 case TIOCSETAF: 778#ifdef COMPAT_43 779 case TIOCSETP: 780 case TIOCSETN: 781#endif 782#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 783 case TIOCSETC: 784 case TIOCSLTC: 785 case TIOCLBIS: 786 case TIOCLBIC: 787 case TIOCLSET: 788#endif 789 pti->pt_send |= TIOCPKT_IOCTL; 790 ptcwakeup(tp, FREAD); 791 break; 792 default: 793 break; 794 } 795 } 796 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 797 && CCEQ(cc[VSTART], CTRL('q')); 798 if (pti->pt_flags & PF_NOSTOP) { 799 if (stop) { 800 pti->pt_send &= ~TIOCPKT_NOSTOP; 801 pti->pt_send |= TIOCPKT_DOSTOP; 802 pti->pt_flags &= ~PF_NOSTOP; 803 ptcwakeup(tp, FREAD); 804 } 805 } else { 806 if (!stop) { 807 pti->pt_send &= ~TIOCPKT_DOSTOP; 808 pti->pt_send |= TIOCPKT_NOSTOP; 809 pti->pt_flags |= PF_NOSTOP; 810 ptcwakeup(tp, FREAD); 811 } 812 } 813 return (error); 814} 815 816 817static void ptc_drvinit(void *unused); 818 819static void pty_clone(void *arg, char *name, int namelen, dev_t *dev); 820 821static void 822pty_clone(arg, name, namelen, dev) 823 void *arg; 824 char *name; 825 int namelen; 826 dev_t *dev; 827{ 828 int u; 829 830 if (*dev != NODEV) 831 return; 832 if (bcmp(name, "pty", 3) != 0) 833 return; 834 if (name[5] != '\0') 835 return; 836 switch (name[3]) { 837 case 'p': u = 0; break; 838 case 'q': u = 32; break; 839 case 'r': u = 64; break; 840 case 's': u = 96; break; 841 case 'P': u = 128; break; 842 case 'Q': u = 160; break; 843 case 'R': u = 192; break; 844 case 'S': u = 224; break; 845 default: return; 846 } 847 if (name[4] >= '0' && name[4] <= '9') 848 u += name[4] - '0'; 849 else if (name[4] >= 'a' && name[4] <= 'v') 850 u += name[4] - 'a' + 10; 851 else 852 return; 853 *dev = make_dev(&ptc_cdevsw, u, 854 UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32); 855 (*dev)->si_flags |= SI_CHEAPCLONE; 856 return; 857} 858 859static void 860ptc_drvinit(unused) 861 void *unused; 862{ 863 864 EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000); 865} 866 867SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL) 868