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