1 /* $NetBSD: tty_pty.c,v 1.56 2001/05/02 10:32:08 scw 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 36 */ 37 38 /* 39 * Pseudo-teletype Driver 40 * (Actually two drivers, requiring two entries in 'cdevsw') 41 */ 42 43 #include "opt_compat_sunos.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/ioctl.h> 48 #include <sys/proc.h> 49 #include <sys/tty.h> 50 #include <sys/file.h> 51 #include <sys/uio.h> 52 #include <sys/kernel.h> 53 #include <sys/vnode.h> 54 #include <sys/signalvar.h> 55 #include <sys/uio.h> 56 #include <sys/conf.h> 57 #include <sys/poll.h> 58 #include <sys/malloc.h> 59 60 #define DEFAULT_NPTYS 16 /* default number of initial ptys */ 61 #define DEFAULT_MAXPTYS 256 /* default maximum number of ptys */ 62 63 /* Macros to clear/set/test flags. */ 64 #define SET(t, f) (t) |= (f) 65 #define CLR(t, f) (t) &= ~((unsigned)(f)) 66 #define ISSET(t, f) ((t) & (f)) 67 68 #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 69 70 /* 71 * pts == /dev/tty[pqrs]? 72 * ptc == /dev/pty[pqrs]? 73 */ 74 struct pt_softc { 75 struct tty *pt_tty; 76 int pt_flags; 77 struct selinfo pt_selr, pt_selw; 78 u_char pt_send; 79 u_char pt_ucntl; 80 }; 81 82 static struct pt_softc **pt_softc = NULL; /* pty array */ 83 static int npty = 0; /* for pstat -t */ 84 static int maxptys = DEFAULT_MAXPTYS; /* maximum number of ptys (sysctable) */ 85 static struct simplelock pt_softc_mutex = SIMPLELOCK_INITIALIZER; 86 87 #define PF_PKT 0x08 /* packet mode */ 88 #define PF_STOPPED 0x10 /* user told stopped */ 89 #define PF_REMOTE 0x20 /* remote and flow controlled input */ 90 #define PF_NOSTOP 0x40 91 #define PF_UCNTL 0x80 /* user control mode */ 92 93 void ptyattach __P((int)); 94 void ptcwakeup __P((struct tty *, int)); 95 int ptcopen __P((dev_t, int, int, struct proc *)); 96 struct tty *ptytty __P((dev_t)); 97 void ptsstart __P((struct tty *)); 98 int pty_maxptys __P((int, int)); 99 100 static struct pt_softc **ptyarralloc __P((int)); 101 static int check_pty __P((dev_t)); 102 103 /* 104 * Allocate and zero array of nelem elements. 105 */ 106 static struct pt_softc ** 107 ptyarralloc(nelem) 108 int nelem; 109 { 110 struct pt_softc **pt; 111 nelem += 10; 112 pt = malloc(nelem * sizeof(struct pt_softc *), M_DEVBUF, M_WAITOK); 113 memset(pt, '\0', nelem * sizeof(struct pt_softc *)); 114 return pt; 115 } 116 117 /* 118 * Check if the minor is correct and ensure necessary structures 119 * are properly allocated. 120 */ 121 static int 122 check_pty(dev) 123 dev_t dev; 124 { 125 struct pt_softc *pti; 126 127 if (minor(dev) >= npty) { 128 struct pt_softc **newpt; 129 int newnpty; 130 131 /* check if the requested pty can be granted */ 132 if (minor(dev) >= maxptys) { 133 limit_reached: 134 tablefull("pty", "increase kern.maxptys"); 135 return (ENXIO); 136 } 137 138 /* 139 * Now grab the pty array mutex - we need to ensure 140 * that the pty array is consistent while copying it's 141 * content to newly allocated, larger space; we also 142 * need to be safe against pty_maxptys(). 143 */ 144 simple_lock(&pt_softc_mutex); 145 146 do { 147 for(newnpty = npty; newnpty <= minor(dev); 148 newnpty *= 2); 149 150 if (newnpty > maxptys) 151 newnpty = maxptys; 152 153 simple_unlock(&pt_softc_mutex); 154 newpt = ptyarralloc(newnpty); 155 simple_lock(&pt_softc_mutex); 156 157 if (maxptys == npty) { 158 simple_unlock(&pt_softc_mutex); 159 goto limit_reached; 160 } 161 } while(newnpty > maxptys); 162 163 /* 164 * If the pty array was not enlarged while we were waiting 165 * for mutex, copy current contents of pt_softc[] to newly 166 * allocated array and start using the new bigger array. 167 */ 168 if (minor(dev) >= npty) { 169 memcpy(newpt, pt_softc, npty*sizeof(struct pt_softc *)); 170 free(pt_softc, M_DEVBUF); 171 172 pt_softc = newpt; 173 npty = newnpty; 174 } else { 175 /* was enlarged when waited fot lock, free new space */ 176 free(newpt, M_DEVBUF); 177 } 178 179 simple_unlock(&pt_softc_mutex); 180 } 181 182 /* 183 * If the entry is not yet allocated, allocate one. The mutex is 184 * needed so that the state of pt_softc[] array is consistant 185 * in case it has been longened above. 186 */ 187 if (!pt_softc[minor(dev)]) { 188 MALLOC(pti, struct pt_softc *, sizeof(struct pt_softc), 189 M_DEVBUF, M_WAITOK); 190 191 pti->pt_tty = ttymalloc(); 192 193 simple_lock(&pt_softc_mutex); 194 195 /* 196 * Check the entry again - it might have been 197 * added while we were waiting for mutex. 198 */ 199 if (!pt_softc[minor(dev)]) { 200 tty_attach(pti->pt_tty); 201 pt_softc[minor(dev)] = pti; 202 } else { 203 ttyfree(pti->pt_tty); 204 FREE(pti, M_DEVBUF); 205 } 206 207 simple_unlock(&pt_softc_mutex); 208 } 209 210 return (0); 211 } 212 213 /* 214 * Set maxpty in thread-safe way. Returns 0 in case of error, otherwise 215 * new value of maxptys. 216 */ 217 int 218 pty_maxptys(newmax, set) 219 int newmax, set; 220 { 221 if (!set) 222 return (maxptys); 223 224 /* the value cannot be set to value lower than current number of ptys */ 225 if (newmax < npty) 226 return (0); 227 228 /* can proceed immediatelly if bigger than current maximum */ 229 if (newmax > maxptys) { 230 maxptys = newmax; 231 return (maxptys); 232 } 233 234 /* 235 * We have to grab the pt_softc lock, so that we would pick correct 236 * value of npty (might be modified in check_pty()). 237 */ 238 simple_lock(&pt_softc_mutex); 239 240 if (newmax > npty) 241 maxptys = newmax; 242 243 simple_unlock(&pt_softc_mutex); 244 245 return (maxptys); 246 } 247 248 /* 249 * Establish n (or default if n is 1) ptys in the system. 250 */ 251 void 252 ptyattach(n) 253 int n; 254 { 255 /* maybe should allow 0 => none? */ 256 if (n <= 1) 257 n = DEFAULT_NPTYS; 258 pt_softc = ptyarralloc(n); 259 npty = n; 260 } 261 262 /*ARGSUSED*/ 263 int 264 ptsopen(dev, flag, devtype, p) 265 dev_t dev; 266 int flag, devtype; 267 struct proc *p; 268 { 269 struct pt_softc *pti; 270 struct tty *tp; 271 int error; 272 273 if ((error = check_pty(dev))) 274 return (error); 275 276 pti = pt_softc[minor(dev)]; 277 tp = pti->pt_tty; 278 279 if (!ISSET(tp->t_state, TS_ISOPEN)) { 280 ttychars(tp); /* Set up default chars */ 281 tp->t_iflag = TTYDEF_IFLAG; 282 tp->t_oflag = TTYDEF_OFLAG; 283 tp->t_lflag = TTYDEF_LFLAG; 284 tp->t_cflag = TTYDEF_CFLAG; 285 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 286 ttsetwater(tp); /* would be done in xxparam() */ 287 } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) 288 return (EBUSY); 289 if (tp->t_oproc) /* Ctrlr still around. */ 290 SET(tp->t_state, TS_CARR_ON); 291 if (!ISSET(flag, O_NONBLOCK)) 292 while (!ISSET(tp->t_state, TS_CARR_ON)) { 293 tp->t_wopen++; 294 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 295 ttopen, 0); 296 tp->t_wopen--; 297 if (error) 298 return (error); 299 } 300 error = (*tp->t_linesw->l_open)(dev, tp); 301 ptcwakeup(tp, FREAD|FWRITE); 302 return (error); 303 } 304 305 int 306 ptsclose(dev, flag, mode, p) 307 dev_t dev; 308 int flag, mode; 309 struct proc *p; 310 { 311 struct pt_softc *pti = pt_softc[minor(dev)]; 312 struct tty *tp = pti->pt_tty; 313 int error; 314 315 error = (*tp->t_linesw->l_close)(tp, flag); 316 error |= ttyclose(tp); 317 ptcwakeup(tp, FREAD|FWRITE); 318 return (error); 319 } 320 321 int 322 ptsread(dev, uio, flag) 323 dev_t dev; 324 struct uio *uio; 325 int flag; 326 { 327 struct proc *p = curproc; 328 struct pt_softc *pti = pt_softc[minor(dev)]; 329 struct tty *tp = pti->pt_tty; 330 int error = 0; 331 332 again: 333 if (pti->pt_flags & PF_REMOTE) { 334 while (isbackground(p, tp)) { 335 if (sigismasked(p, SIGTTIN) || 336 p->p_pgrp->pg_jobc == 0 || 337 p->p_flag & P_PPWAIT) 338 return (EIO); 339 pgsignal(p->p_pgrp, SIGTTIN, 1); 340 error = ttysleep(tp, (caddr_t)&lbolt, 341 TTIPRI | PCATCH, ttybg, 0); 342 if (error) 343 return (error); 344 } 345 if (tp->t_canq.c_cc == 0) { 346 if (flag & IO_NDELAY) 347 return (EWOULDBLOCK); 348 error = ttysleep(tp, (caddr_t)&tp->t_canq, 349 TTIPRI | PCATCH, ttyin, 0); 350 if (error) 351 return (error); 352 goto again; 353 } 354 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 355 if (ureadc(getc(&tp->t_canq), uio) < 0) { 356 error = EFAULT; 357 break; 358 } 359 if (tp->t_canq.c_cc == 1) 360 (void) getc(&tp->t_canq); 361 if (tp->t_canq.c_cc) 362 return (error); 363 } else 364 if (tp->t_oproc) 365 error = (*tp->t_linesw->l_read)(tp, uio, flag); 366 ptcwakeup(tp, FWRITE); 367 return (error); 368 } 369 370 /* 371 * Write to pseudo-tty. 372 * Wakeups of controlling tty will happen 373 * indirectly, when tty driver calls ptsstart. 374 */ 375 int 376 ptswrite(dev, uio, flag) 377 dev_t dev; 378 struct uio *uio; 379 int flag; 380 { 381 struct pt_softc *pti = pt_softc[minor(dev)]; 382 struct tty *tp = pti->pt_tty; 383 384 if (tp->t_oproc == 0) 385 return (EIO); 386 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 387 } 388 389 /* 390 * Poll pseudo-tty. 391 */ 392 int 393 ptspoll(dev, events, p) 394 dev_t dev; 395 int events; 396 struct proc *p; 397 { 398 struct pt_softc *pti = pt_softc[minor(dev)]; 399 struct tty *tp = pti->pt_tty; 400 401 if (tp->t_oproc == 0) 402 return (EIO); 403 404 return ((*tp->t_linesw->l_poll)(tp, events, p)); 405 } 406 407 /* 408 * Start output on pseudo-tty. 409 * Wake up process polling or sleeping for input from controlling tty. 410 */ 411 void 412 ptsstart(tp) 413 struct tty *tp; 414 { 415 struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; 416 417 if (ISSET(tp->t_state, TS_TTSTOP)) 418 return; 419 if (pti->pt_flags & PF_STOPPED) { 420 pti->pt_flags &= ~PF_STOPPED; 421 pti->pt_send = TIOCPKT_START; 422 } 423 ptcwakeup(tp, FREAD); 424 } 425 426 void 427 ptsstop(tp, flush) 428 struct tty *tp; 429 int flush; 430 { 431 struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; 432 int flag; 433 434 /* note: FLUSHREAD and FLUSHWRITE already ok */ 435 if (flush == 0) { 436 flush = TIOCPKT_STOP; 437 pti->pt_flags |= PF_STOPPED; 438 } else 439 pti->pt_flags &= ~PF_STOPPED; 440 pti->pt_send |= flush; 441 /* change of perspective */ 442 flag = 0; 443 if (flush & FREAD) 444 flag |= FWRITE; 445 if (flush & FWRITE) 446 flag |= FREAD; 447 ptcwakeup(tp, flag); 448 } 449 450 void 451 ptcwakeup(tp, flag) 452 struct tty *tp; 453 int flag; 454 { 455 struct pt_softc *pti = pt_softc[minor(tp->t_dev)]; 456 457 if (flag & FREAD) { 458 selwakeup(&pti->pt_selr); 459 wakeup((caddr_t)&tp->t_outq.c_cf); 460 } 461 if (flag & FWRITE) { 462 selwakeup(&pti->pt_selw); 463 wakeup((caddr_t)&tp->t_rawq.c_cf); 464 } 465 } 466 467 /*ARGSUSED*/ 468 int 469 ptcopen(dev, flag, devtype, p) 470 dev_t dev; 471 int flag, devtype; 472 struct proc *p; 473 { 474 struct pt_softc *pti; 475 struct tty *tp; 476 int error; 477 478 if ((error = check_pty(dev))) 479 return (error); 480 481 pti = pt_softc[minor(dev)]; 482 tp = pti->pt_tty; 483 484 if (tp->t_oproc) 485 return (EIO); 486 tp->t_oproc = ptsstart; 487 (void)(*tp->t_linesw->l_modem)(tp, 1); 488 CLR(tp->t_lflag, EXTPROC); 489 pti->pt_flags = 0; 490 pti->pt_send = 0; 491 pti->pt_ucntl = 0; 492 return (0); 493 } 494 495 /*ARGSUSED*/ 496 int 497 ptcclose(dev, flag, devtype, p) 498 dev_t dev; 499 int flag, devtype; 500 struct proc *p; 501 { 502 struct pt_softc *pti = pt_softc[minor(dev)]; 503 struct tty *tp = pti->pt_tty; 504 505 (void)(*tp->t_linesw->l_modem)(tp, 0); 506 CLR(tp->t_state, TS_CARR_ON); 507 tp->t_oproc = 0; /* mark closed */ 508 return (0); 509 } 510 511 int 512 ptcread(dev, uio, flag) 513 dev_t dev; 514 struct uio *uio; 515 int flag; 516 { 517 struct pt_softc *pti = pt_softc[minor(dev)]; 518 struct tty *tp = pti->pt_tty; 519 char buf[BUFSIZ]; 520 int error = 0, cc; 521 522 /* 523 * We want to block until the slave 524 * is open, and there's something to read; 525 * but if we lost the slave or we're NBIO, 526 * then return the appropriate error instead. 527 */ 528 for (;;) { 529 if (ISSET(tp->t_state, TS_ISOPEN)) { 530 if (pti->pt_flags&PF_PKT && pti->pt_send) { 531 error = ureadc((int)pti->pt_send, uio); 532 if (error) 533 return (error); 534 if (pti->pt_send & TIOCPKT_IOCTL) { 535 cc = min(uio->uio_resid, 536 sizeof(tp->t_termios)); 537 uiomove((caddr_t) &tp->t_termios, 538 cc, uio); 539 } 540 pti->pt_send = 0; 541 return (0); 542 } 543 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 544 error = ureadc((int)pti->pt_ucntl, uio); 545 if (error) 546 return (error); 547 pti->pt_ucntl = 0; 548 return (0); 549 } 550 if (tp->t_outq.c_cc && !ISSET(tp->t_state, TS_TTSTOP)) 551 break; 552 } 553 if (!ISSET(tp->t_state, TS_CARR_ON)) 554 return (0); /* EOF */ 555 if (flag & IO_NDELAY) 556 return (EWOULDBLOCK); 557 error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH, 558 ttyin, 0); 559 if (error) 560 return (error); 561 } 562 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 563 error = ureadc(0, uio); 564 while (uio->uio_resid > 0 && error == 0) { 565 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ)); 566 if (cc <= 0) 567 break; 568 error = uiomove(buf, cc, uio); 569 } 570 if (tp->t_outq.c_cc <= tp->t_lowat) { 571 if (ISSET(tp->t_state, TS_ASLEEP)) { 572 CLR(tp->t_state, TS_ASLEEP); 573 wakeup((caddr_t)&tp->t_outq); 574 } 575 selwakeup(&tp->t_wsel); 576 } 577 return (error); 578 } 579 580 581 int 582 ptcwrite(dev, uio, flag) 583 dev_t dev; 584 struct uio *uio; 585 int flag; 586 { 587 struct pt_softc *pti = pt_softc[minor(dev)]; 588 struct tty *tp = pti->pt_tty; 589 u_char *cp = NULL; 590 int cc = 0; 591 u_char locbuf[BUFSIZ]; 592 int cnt = 0; 593 int error = 0; 594 595 again: 596 if (!ISSET(tp->t_state, TS_ISOPEN)) 597 goto block; 598 if (pti->pt_flags & PF_REMOTE) { 599 if (tp->t_canq.c_cc) 600 goto block; 601 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 602 if (cc == 0) { 603 cc = min(uio->uio_resid, BUFSIZ); 604 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 605 cp = locbuf; 606 error = uiomove((caddr_t)cp, cc, uio); 607 if (error) 608 return (error); 609 /* check again for safety */ 610 if (!ISSET(tp->t_state, TS_ISOPEN)) 611 return (EIO); 612 } 613 if (cc) 614 (void) b_to_q((char *)cp, cc, &tp->t_canq); 615 cc = 0; 616 } 617 (void) putc(0, &tp->t_canq); 618 ttwakeup(tp); 619 wakeup((caddr_t)&tp->t_canq); 620 return (0); 621 } 622 while (uio->uio_resid > 0) { 623 if (cc == 0) { 624 cc = min(uio->uio_resid, BUFSIZ); 625 cp = locbuf; 626 error = uiomove((caddr_t)cp, cc, uio); 627 if (error) 628 return (error); 629 /* check again for safety */ 630 if (!ISSET(tp->t_state, TS_ISOPEN)) 631 return (EIO); 632 } 633 while (cc > 0) { 634 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 635 (tp->t_canq.c_cc > 0 || !ISSET(tp->t_iflag, ICANON))) { 636 wakeup((caddr_t)&tp->t_rawq); 637 goto block; 638 } 639 (*tp->t_linesw->l_rint)(*cp++, tp); 640 cnt++; 641 cc--; 642 } 643 cc = 0; 644 } 645 return (0); 646 block: 647 /* 648 * Come here to wait for slave to open, for space 649 * in outq, or space in rawq. 650 */ 651 if (!ISSET(tp->t_state, TS_CARR_ON)) 652 return (EIO); 653 if (flag & IO_NDELAY) { 654 /* adjust for data copied in but not written */ 655 uio->uio_resid += cc; 656 if (cnt == 0) 657 return (EWOULDBLOCK); 658 return (0); 659 } 660 error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH, 661 ttyout, 0); 662 if (error) { 663 /* adjust for data copied in but not written */ 664 uio->uio_resid += cc; 665 return (error); 666 } 667 goto again; 668 } 669 670 int 671 ptcpoll(dev, events, p) 672 dev_t dev; 673 int events; 674 struct proc *p; 675 { 676 struct pt_softc *pti = pt_softc[minor(dev)]; 677 struct tty *tp = pti->pt_tty; 678 int revents = 0; 679 int s = splsoftclock(); 680 681 if (events & (POLLIN | POLLRDNORM)) 682 if (ISSET(tp->t_state, TS_ISOPEN) && 683 ((tp->t_outq.c_cc > 0 && !ISSET(tp->t_state, TS_TTSTOP)) || 684 ((pti->pt_flags & PF_PKT) && pti->pt_send) || 685 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) 686 revents |= events & (POLLIN | POLLRDNORM); 687 688 if (events & (POLLOUT | POLLWRNORM)) 689 if (ISSET(tp->t_state, TS_ISOPEN) && 690 ((pti->pt_flags & PF_REMOTE) ? 691 (tp->t_canq.c_cc == 0) : 692 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) || 693 (tp->t_canq.c_cc == 0 && ISSET(tp->t_iflag, ICANON))))) 694 revents |= events & (POLLOUT | POLLWRNORM); 695 696 if (events & POLLHUP) 697 if (!ISSET(tp->t_state, TS_CARR_ON)) 698 revents |= POLLHUP; 699 700 if (revents == 0) { 701 if (events & (POLLIN | POLLHUP | POLLRDNORM)) 702 selrecord(p, &pti->pt_selr); 703 704 if (events & (POLLOUT | POLLWRNORM)) 705 selrecord(p, &pti->pt_selw); 706 } 707 708 splx(s); 709 return (revents); 710 } 711 712 713 struct tty * 714 ptytty(dev) 715 dev_t dev; 716 { 717 struct pt_softc *pti = pt_softc[minor(dev)]; 718 struct tty *tp = pti->pt_tty; 719 720 return (tp); 721 } 722 723 /*ARGSUSED*/ 724 int 725 ptyioctl(dev, cmd, data, flag, p) 726 dev_t dev; 727 u_long cmd; 728 caddr_t data; 729 int flag; 730 struct proc *p; 731 { 732 struct pt_softc *pti = pt_softc[minor(dev)]; 733 struct tty *tp = pti->pt_tty; 734 u_char *cc = tp->t_cc; 735 int stop, error, sig; 736 737 /* 738 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 739 * ttywflush(tp) will hang if there are characters in the outq. 740 */ 741 if (cmd == TIOCEXT) { 742 /* 743 * When the EXTPROC bit is being toggled, we need 744 * to send an TIOCPKT_IOCTL if the packet driver 745 * is turned on. 746 */ 747 if (*(int *)data) { 748 if (pti->pt_flags & PF_PKT) { 749 pti->pt_send |= TIOCPKT_IOCTL; 750 ptcwakeup(tp, FREAD); 751 } 752 SET(tp->t_lflag, EXTPROC); 753 } else { 754 if (ISSET(tp->t_lflag, EXTPROC) && 755 (pti->pt_flags & PF_PKT)) { 756 pti->pt_send |= TIOCPKT_IOCTL; 757 ptcwakeup(tp, FREAD); 758 } 759 CLR(tp->t_lflag, EXTPROC); 760 } 761 return(0); 762 } else 763 if (cdevsw[major(dev)].d_open == ptcopen) 764 switch (cmd) { 765 766 case TIOCGPGRP: 767 #ifdef COMPAT_SUNOS 768 { 769 /* 770 * I'm not sure about SunOS TIOCGPGRP semantics 771 * on PTYs, but it's something like this: 772 */ 773 extern struct emul emul_sunos; 774 if (p->p_emul == &emul_sunos && tp->t_pgrp == 0) 775 return (EIO); 776 *(int *)data = tp->t_pgrp->pg_id; 777 return (0); 778 } 779 #endif 780 /* 781 * We avoid calling ttioctl on the controller since, 782 * in that case, tp must be the controlling terminal. 783 */ 784 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 785 return (0); 786 787 case TIOCPKT: 788 if (*(int *)data) { 789 if (pti->pt_flags & PF_UCNTL) 790 return (EINVAL); 791 pti->pt_flags |= PF_PKT; 792 } else 793 pti->pt_flags &= ~PF_PKT; 794 return (0); 795 796 case TIOCUCNTL: 797 if (*(int *)data) { 798 if (pti->pt_flags & PF_PKT) 799 return (EINVAL); 800 pti->pt_flags |= PF_UCNTL; 801 } else 802 pti->pt_flags &= ~PF_UCNTL; 803 return (0); 804 805 case TIOCREMOTE: 806 if (*(int *)data) 807 pti->pt_flags |= PF_REMOTE; 808 else 809 pti->pt_flags &= ~PF_REMOTE; 810 ttyflush(tp, FREAD|FWRITE); 811 return (0); 812 813 #ifdef COMPAT_OLDTTY 814 case TIOCSETP: 815 case TIOCSETN: 816 #endif 817 case TIOCSETD: 818 case TIOCSETA: 819 case TIOCSETAW: 820 case TIOCSETAF: 821 ndflush(&tp->t_outq, tp->t_outq.c_cc); 822 break; 823 824 case TIOCSIG: 825 sig = (int)(long)*(caddr_t *)data; 826 if (sig <= 0 || sig >= NSIG) 827 return (EINVAL); 828 if (!ISSET(tp->t_lflag, NOFLSH)) 829 ttyflush(tp, FREAD|FWRITE); 830 pgsignal(tp->t_pgrp, sig, 1); 831 if ((sig == SIGINFO) && 832 (!ISSET(tp->t_lflag, NOKERNINFO))) 833 ttyinfo(tp); 834 return(0); 835 } 836 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 837 if (error < 0) 838 error = ttioctl(tp, cmd, data, flag, p); 839 if (error < 0) { 840 if (pti->pt_flags & PF_UCNTL && 841 (cmd & ~0xff) == UIOCCMD(0)) { 842 if (cmd & 0xff) { 843 pti->pt_ucntl = (u_char)cmd; 844 ptcwakeup(tp, FREAD); 845 } 846 return (0); 847 } 848 error = ENOTTY; 849 } 850 /* 851 * If external processing and packet mode send ioctl packet. 852 */ 853 if (ISSET(tp->t_lflag, EXTPROC) && (pti->pt_flags & PF_PKT)) { 854 switch(cmd) { 855 case TIOCSETA: 856 case TIOCSETAW: 857 case TIOCSETAF: 858 #ifdef COMPAT_OLDTTY 859 case TIOCSETP: 860 case TIOCSETN: 861 case TIOCSETC: 862 case TIOCSLTC: 863 case TIOCLBIS: 864 case TIOCLBIC: 865 case TIOCLSET: 866 #endif 867 pti->pt_send |= TIOCPKT_IOCTL; 868 ptcwakeup(tp, FREAD); 869 default: 870 break; 871 } 872 } 873 stop = ISSET(tp->t_iflag, IXON) && CCEQ(cc[VSTOP], CTRL('s')) 874 && CCEQ(cc[VSTART], CTRL('q')); 875 if (pti->pt_flags & PF_NOSTOP) { 876 if (stop) { 877 pti->pt_send &= ~TIOCPKT_NOSTOP; 878 pti->pt_send |= TIOCPKT_DOSTOP; 879 pti->pt_flags &= ~PF_NOSTOP; 880 ptcwakeup(tp, FREAD); 881 } 882 } else { 883 if (!stop) { 884 pti->pt_send &= ~TIOCPKT_DOSTOP; 885 pti->pt_send |= TIOCPKT_NOSTOP; 886 pti->pt_flags |= PF_NOSTOP; 887 ptcwakeup(tp, FREAD); 888 } 889 } 890 return (error); 891 } 892