1/* 2 * Copyright (c) 1997-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1982, 1986, 1989, 1993 30 * The Regents of the University of California. All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 3. All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed by the University of 43 * California, Berkeley and its contributors. 44 * 4. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 61 */ 62 63/* Common callbacks for the pseudo-teletype driver (pty/tty) 64 * and cloning pseudo-teletype driver (ptmx/pts). 65 */ 66 67#include <sys/param.h> 68#include <sys/systm.h> 69#include <sys/ioctl.h> 70#include <sys/proc_internal.h> 71#include <sys/kauth.h> 72#include <sys/tty.h> 73#include <sys/conf.h> 74#include <sys/file_internal.h> 75#include <sys/uio_internal.h> 76#include <sys/kernel.h> 77#include <sys/vnode.h> 78#include <sys/vnode_internal.h> /* _devfs_setattr() */ 79#include <sys/stat.h> /* _devfs_setattr() */ 80#include <sys/user.h> 81#include <sys/signalvar.h> 82#include <sys/sysctl.h> 83#include <miscfs/devfs/devfs.h> 84#include <miscfs/devfs/devfsdefs.h> /* DEVFS_LOCK()/DEVFS_UNLOCK() */ 85 86#if CONFIG_MACF 87#include <security/mac_framework.h> 88#endif 89 90#include "tty_dev.h" 91 92/* XXX belongs in devfs somewhere - LATER */ 93static int _devfs_setattr(void *, unsigned short, uid_t, gid_t); 94 95/* 96 * Forward declarations 97 */ 98static void ptcwakeup(struct tty *tp, int flag); 99__XNU_PRIVATE_EXTERN d_open_t ptsopen; 100__XNU_PRIVATE_EXTERN d_close_t ptsclose; 101__XNU_PRIVATE_EXTERN d_read_t ptsread; 102__XNU_PRIVATE_EXTERN d_write_t ptswrite; 103__XNU_PRIVATE_EXTERN d_ioctl_t ptyioctl; /* common ioctl */ 104__XNU_PRIVATE_EXTERN d_stop_t ptsstop; 105__XNU_PRIVATE_EXTERN d_reset_t ptsreset; 106__XNU_PRIVATE_EXTERN d_select_t ptsselect; 107__XNU_PRIVATE_EXTERN d_open_t ptcopen; 108__XNU_PRIVATE_EXTERN d_close_t ptcclose; 109__XNU_PRIVATE_EXTERN d_read_t ptcread; 110__XNU_PRIVATE_EXTERN d_write_t ptcwrite; 111__XNU_PRIVATE_EXTERN d_stop_t ptcstop; /* NO-OP */ 112__XNU_PRIVATE_EXTERN d_reset_t ptcreset; 113__XNU_PRIVATE_EXTERN d_select_t ptcselect; 114 115/* 116 * XXX Should be devfs function... and use VATTR mechanisms, per 117 * XXX vnode_setattr2(); only we maybe can't really get back to the 118 * XXX vnode here for cloning devices (but it works for *cloned* devices 119 * XXX that are not themselves cloning). 120 * 121 * Returns: 0 Success 122 * namei:??? 123 * vnode_setattr:??? 124 */ 125static int 126_devfs_setattr(void * handle, unsigned short mode, uid_t uid, gid_t gid) 127{ 128 devdirent_t *direntp = (devdirent_t *)handle; 129 devnode_t *devnodep; 130 int error = EACCES; 131 vfs_context_t ctx = vfs_context_current();; 132 struct vnode_attr va; 133 134 VATTR_INIT(&va); 135 VATTR_SET(&va, va_uid, uid); 136 VATTR_SET(&va, va_gid, gid); 137 VATTR_SET(&va, va_mode, mode & ALLPERMS); 138 139 /* 140 * If the TIOCPTYGRANT loses the race with the clone operation because 141 * this function is not part of devfs, and therefore can't take the 142 * devfs lock to protect the direntp update, then force user space to 143 * redrive the grant request. 144 */ 145 if (direntp == NULL || (devnodep = direntp->de_dnp) == NULL) { 146 error = ERESTART; 147 goto out; 148 } 149 150 /* 151 * Only do this if we are operating on device that doesn't clone 152 * each time it's referenced. We perform a lookup on the device 153 * to insure we get the right instance. We can't just use the call 154 * to devfs_dntovn() to get the vp for the operation, because 155 * dn_dvm may not have been initialized. 156 */ 157 if (devnodep->dn_clone == NULL) { 158 struct nameidata nd; 159 char name[128]; 160 161 snprintf(name, sizeof(name), "/dev/%s", direntp->de_name); 162 NDINIT(&nd, LOOKUP, OP_SETATTR, FOLLOW, UIO_SYSSPACE, CAST_USER_ADDR_T(name), ctx); 163 error = namei(&nd); 164 if (error) 165 goto out; 166 error = vnode_setattr(nd.ni_vp, &va, ctx); 167 vnode_put(nd.ni_vp); 168 nameidone(&nd); 169 goto out; 170 } 171 172out: 173 return(error); 174} 175 176#define BUFSIZ 100 /* Chunk size iomoved to/from user */ 177 178static struct tty_dev_t *tty_dev_head; 179 180__private_extern__ void 181tty_dev_register(struct tty_dev_t *driver) 182{ 183 if (driver) { 184 driver->next = tty_dev_head; 185 tty_dev_head = driver; 186 } 187} 188 189/* 190 * Given a minor number, return the corresponding structure for that minor 191 * number. If there isn't one, and the create flag is specified, we create 192 * one if possible. 193 * 194 * Parameters: minor Minor number of ptmx device 195 * open_flag PF_OPEN_M First open of master 196 * PF_OPEN_S First open of slave 197 * 0 Just want ioctl struct 198 * 199 * Returns: NULL Did not exist/could not create 200 * !NULL structure corresponding minor number 201 * 202 * Locks: tty_lock() on ptmx_ioctl->pt_tty NOT held on entry or exit. 203 */ 204 205static struct tty_dev_t * 206pty_get_driver(dev_t dev) 207{ 208 int major = major(dev); 209 struct tty_dev_t *driver; 210 for (driver = tty_dev_head; driver != NULL; driver = driver->next) { 211 if ((driver->master == major || driver->slave == major)) { 212 break; 213 } 214 } 215 return driver; 216} 217 218static struct ptmx_ioctl * 219pty_get_ioctl(dev_t dev, int open_flag, struct tty_dev_t **out_driver) 220{ 221 struct tty_dev_t *driver = pty_get_driver(dev); 222 if (out_driver) { 223 *out_driver = driver; 224 } 225 if (driver && driver->open) { 226 return driver->open(minor(dev), open_flag); 227 } 228 return NULL; 229} 230 231/* 232 * Locks: tty_lock() of old_ptmx_ioctl->pt_tty NOT held for this call. 233 */ 234static int 235pty_free_ioctl(dev_t dev, int open_flag) 236{ 237 struct tty_dev_t *driver = pty_get_driver(dev); 238 if (driver && driver->free) { 239 return driver->free(minor(dev), open_flag); 240 } 241 return 0; 242} 243 244static int 245pty_get_name(dev_t dev, char *buffer, size_t size) 246{ 247 struct tty_dev_t *driver = pty_get_driver(dev); 248 if (driver && driver->name) { 249 return driver->name(minor(dev), buffer, size); 250 } 251 return 0; 252} 253 254__private_extern__ int 255ptsopen(dev_t dev, int flag, __unused int devtype, __unused struct proc *p) 256{ 257 int error; 258 struct tty_dev_t *driver; 259 struct ptmx_ioctl *pti = pty_get_ioctl(dev, PF_OPEN_S, &driver); 260 if (pti == NULL) { 261 return ENXIO; 262 } 263 if (!(pti->pt_flags & PF_UNLOCKED)) { 264 return EAGAIN; 265 } 266 267 struct tty *tp = pti->pt_tty; 268 tty_lock(tp); 269 270 if ((tp->t_state & TS_ISOPEN) == 0) { 271 termioschars(&tp->t_termios); /* Set up default chars */ 272 tp->t_iflag = TTYDEF_IFLAG; 273 tp->t_oflag = TTYDEF_OFLAG; 274 tp->t_lflag = TTYDEF_LFLAG; 275 tp->t_cflag = TTYDEF_CFLAG; 276 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 277 ttsetwater(tp); /* would be done in xxparam() */ 278 } else if ((tp->t_state & TS_XCLUDE) && kauth_cred_issuser(kauth_cred_get())) { 279 error = EBUSY; 280 goto out; 281 } 282 if (tp->t_oproc) /* Ctrlr still around. */ 283 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 284 while ((tp->t_state & TS_CARR_ON) == 0) { 285 if (flag&FNONBLOCK) 286 break; 287 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, __FUNCTION__, 0); 288 if (error) 289 goto out; 290 } 291 error = (*linesw[tp->t_line].l_open)(dev, tp); 292 /* Successful open; mark as open by the slave */ 293 294 pti->pt_flags |= PF_OPEN_S; 295 CLR(tp->t_state, TS_IOCTL_NOT_OK); 296 if (error == 0) 297 ptcwakeup(tp, FREAD|FWRITE); 298 299out: 300 tty_unlock(tp); 301 return (error); 302} 303 304__private_extern__ int 305ptsclose(dev_t dev, int flag, __unused int mode, __unused proc_t p) 306{ 307 int err; 308 309 /* 310 * This is temporary until the VSX conformance tests 311 * are fixed. They are hanging with a deadlock 312 * where close() will not complete without t_timeout set 313 */ 314#define FIX_VSX_HANG 1 315#ifdef FIX_VSX_HANG 316 int save_timeout; 317#endif 318 struct tty_dev_t *driver; 319 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver); 320 struct tty *tp; 321 322 if (pti == NULL) 323 return (ENXIO); 324 325 tp = pti->pt_tty; 326 tty_lock(tp); 327#ifdef FIX_VSX_HANG 328 save_timeout = tp->t_timeout; 329 tp->t_timeout = 60; 330#endif 331 err = (*linesw[tp->t_line].l_close)(tp, flag); 332 ptsstop(tp, FREAD|FWRITE); 333 (void) ttyclose(tp); 334#ifdef FIX_VSX_HANG 335 tp->t_timeout = save_timeout; 336#endif 337 tty_unlock(tp); 338 339 if ((flag & IO_REVOKE) == IO_REVOKE && driver->revoke) { 340 driver->revoke(minor(dev), tp); 341 } 342 /* unconditional, just like ttyclose() */ 343 pty_free_ioctl(dev, PF_OPEN_S); 344 345 return (err); 346} 347 348__private_extern__ int 349ptsread(dev_t dev, struct uio *uio, int flag) 350{ 351 proc_t p = current_proc(); 352 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL); 353 struct tty *tp; 354 int error = 0; 355 struct uthread *ut; 356 struct pgrp *pg; 357 358 if (pti == NULL) 359 return (ENXIO); 360 tp = pti->pt_tty; 361 tty_lock(tp); 362 363 ut = (struct uthread *)get_bsdthread_info(current_thread()); 364again: 365 if (pti->pt_flags & PF_REMOTE) { 366 while (isbackground(p, tp)) { 367 if ((p->p_sigignore & sigmask(SIGTTIN)) || 368 (ut->uu_sigmask & sigmask(SIGTTIN)) || 369 p->p_lflag & P_LPPWAIT) { 370 error = EIO; 371 goto out; 372 } 373 374 375 pg = proc_pgrp(p); 376 if (pg == PGRP_NULL) { 377 error = EIO; 378 goto out; 379 } 380 /* 381 * SAFE: We about to drop the lock ourselves by 382 * SAFE: erroring out or sleeping anyway. 383 */ 384 tty_unlock(tp); 385 if (pg->pg_jobc == 0) { 386 pg_rele(pg); 387 tty_lock(tp); 388 error = EIO; 389 goto out; 390 } 391 pgsignal(pg, SIGTTIN, 1); 392 pg_rele(pg); 393 tty_lock(tp); 394 395 error = ttysleep(tp, &ptsread, TTIPRI | PCATCH | PTTYBLOCK, __FUNCTION__, hz); 396 if (error) 397 goto out; 398 } 399 if (tp->t_canq.c_cc == 0) { 400 if (flag & IO_NDELAY) { 401 error = EWOULDBLOCK; 402 goto out; 403 } 404 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH, __FUNCTION__, 0); 405 if (error) 406 goto out; 407 goto again; 408 } 409 while (tp->t_canq.c_cc > 1 && uio_resid(uio) > 0) { 410 int cc; 411 char buf[BUFSIZ]; 412 413 cc = MIN((int)uio_resid(uio), BUFSIZ); 414 // Don't copy the very last byte 415 cc = MIN(cc, tp->t_canq.c_cc - 1); 416 cc = q_to_b(&tp->t_canq, (u_char *)buf, cc); 417 error = uiomove(buf, cc, uio); 418 if (error) 419 break; 420 } 421 if (tp->t_canq.c_cc == 1) 422 (void) getc(&tp->t_canq); 423 if (tp->t_canq.c_cc) 424 goto out; 425 } else 426 if (tp->t_oproc) 427 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 428 ptcwakeup(tp, FWRITE); 429out: 430 tty_unlock(tp); 431 return (error); 432} 433 434/* 435 * Write to pseudo-tty. 436 * Wakeups of controlling tty will happen 437 * indirectly, when tty driver calls ptsstart. 438 */ 439__private_extern__ int 440ptswrite(dev_t dev, struct uio *uio, int flag) 441{ 442 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL); 443 struct tty *tp; 444 int error; 445 446 if (pti == NULL) 447 return (ENXIO); 448 tp = pti->pt_tty; 449 tty_lock(tp); 450 451 if (tp->t_oproc == 0) 452 error = EIO; 453 else 454 error = (*linesw[tp->t_line].l_write)(tp, uio, flag); 455 456 tty_unlock(tp); 457 458 return (error); 459} 460 461/* 462 * Start output on pseudo-tty. 463 * Wake up process selecting or sleeping for input from controlling tty. 464 * 465 * t_oproc for this driver; called from within the line discipline 466 * 467 * Locks: Assumes tp is locked on entry, remains locked on exit 468 */ 469static void 470ptsstart(struct tty *tp) 471{ 472 struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL); 473 if (pti == NULL) 474 goto out; 475 if (tp->t_state & TS_TTSTOP) 476 goto out; 477 if (pti->pt_flags & PF_STOPPED) { 478 pti->pt_flags &= ~PF_STOPPED; 479 pti->pt_send = TIOCPKT_START; 480 } 481 ptcwakeup(tp, FREAD); 482out: 483 return; 484} 485 486/* 487 * Locks: Assumes tty_lock() is held over this call. 488 */ 489static void 490ptcwakeup(struct tty *tp, int flag) 491{ 492 struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL); 493 if (pti == NULL) 494 return; 495 496 if (flag & FREAD) { 497 selwakeup(&pti->pt_selr); 498 wakeup(TSA_PTC_READ(tp)); 499 } 500 if (flag & FWRITE) { 501 selwakeup(&pti->pt_selw); 502 wakeup(TSA_PTC_WRITE(tp)); 503 } 504} 505 506__private_extern__ int 507ptcopen(dev_t dev, __unused int flag, __unused int devtype, __unused proc_t p) 508{ 509 struct tty_dev_t *driver; 510 struct ptmx_ioctl *pti = pty_get_ioctl(dev, PF_OPEN_M, &driver); 511 if (pti == NULL) { 512 return (ENXIO); 513 } else if (pti == (struct ptmx_ioctl*)-1) { 514 return (EREDRIVEOPEN); 515 } 516 517 struct tty *tp = pti->pt_tty; 518 tty_lock(tp); 519 520 /* If master is open OR slave is still draining, pty is still busy */ 521 if (tp->t_oproc || (tp->t_state & TS_ISOPEN)) { 522 tty_unlock(tp); 523 /* 524 * If master is closed, we are the only reference, so we 525 * need to clear the master open bit 526 */ 527 if (!tp->t_oproc) { 528 pty_free_ioctl(dev, PF_OPEN_M); 529 } 530 return EBUSY; 531 } 532 tp->t_oproc = ptsstart; 533 CLR(tp->t_state, TS_ZOMBIE); 534 SET(tp->t_state, TS_IOCTL_NOT_OK); 535#ifdef sun4c 536 tp->t_stop = ptsstop; 537#endif 538 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 539 tp->t_lflag &= ~EXTPROC; 540 541 if (driver->open_reset) { 542 pti->pt_flags = PF_UNLOCKED; 543 pti->pt_send = 0; 544 pti->pt_ucntl = 0; 545 } 546 547 tty_unlock(tp); 548 return 0; 549} 550 551__private_extern__ int 552ptcclose(dev_t dev, __unused int flags, __unused int fmt, __unused proc_t p) 553{ 554 struct tty_dev_t *driver; 555 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver); 556 struct tty *tp; 557 558 if (pti == NULL) 559 return (ENXIO); 560 tp = pti->pt_tty; 561 tty_lock(tp); 562 563 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 564 565 /* 566 * XXX MDMBUF makes no sense for ptys but would inhibit the above 567 * l_modem(). CLOCAL makes sense but isn't supported. Special 568 * l_modem()s that ignore carrier drop make no sense for ptys but 569 * may be in use because other parts of the line discipline make 570 * sense for ptys. Recover by doing everything that a normal 571 * ttymodem() would have done except for sending a SIGHUP. 572 */ 573 if (tp->t_state & TS_ISOPEN) { 574 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED); 575 tp->t_state |= TS_ZOMBIE; 576 ttyflush(tp, FREAD | FWRITE); 577 } 578 579 tp->t_oproc = 0; /* mark closed */ 580 581 tty_unlock(tp); 582 583 pty_free_ioctl(dev, PF_OPEN_M); 584#if CONFIG_MACF 585 if (driver->mac_notify) { 586 mac_pty_notify_close(p, tp, dev, NULL); 587 } 588#endif 589 590 return (0); 591} 592 593__private_extern__ int 594ptcread(dev_t dev, struct uio *uio, int flag) 595{ 596 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL); 597 struct tty *tp; 598 char buf[BUFSIZ]; 599 int error = 0, cc; 600 601 if (pti == NULL) 602 return (ENXIO); 603 tp = pti->pt_tty; 604 tty_lock(tp); 605 606 /* 607 * We want to block until the slave 608 * is open, and there's something to read; 609 * but if we lost the slave or we're NBIO, 610 * then return the appropriate error instead. 611 */ 612 for (;;) { 613 if (tp->t_state & TS_ISOPEN) { 614 if (pti->pt_flags & PF_PKT && pti->pt_send) { 615 error = ureadc((int)pti->pt_send, uio); 616 if (error) 617 goto out; 618 if (pti->pt_send & TIOCPKT_IOCTL) { 619 cc = MIN((int)uio_resid(uio), 620 (int)sizeof(tp->t_termios)); 621 uiomove((caddr_t)&tp->t_termios, cc, 622 uio); 623 } 624 pti->pt_send = 0; 625 goto out; 626 } 627 if (pti->pt_flags & PF_UCNTL && pti->pt_ucntl) { 628 error = ureadc((int)pti->pt_ucntl, uio); 629 if (error) 630 goto out; 631 pti->pt_ucntl = 0; 632 goto out; 633 } 634 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 635 break; 636 } 637 if ((tp->t_state & TS_CONNECTED) == 0) 638 goto out; /* EOF */ 639 if (flag & IO_NDELAY) { 640 error = EWOULDBLOCK; 641 goto out; 642 } 643 error = ttysleep(tp, TSA_PTC_READ(tp), TTIPRI | PCATCH, __FUNCTION__, 0); 644 if (error) 645 goto out; 646 } 647 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 648 error = ureadc(0, uio); 649 while (uio_resid(uio) > 0 && error == 0) { 650 cc = q_to_b(&tp->t_outq, (u_char *)buf, MIN((int)uio_resid(uio), BUFSIZ)); 651 if (cc <= 0) 652 break; 653 error = uiomove(buf, cc, uio); 654 } 655 (*linesw[tp->t_line].l_start)(tp); 656 657out: 658 tty_unlock(tp); 659 660 return (error); 661} 662 663/* 664 * Line discipline callback 665 * 666 * Locks: tty_lock() is assumed held on entry and exit. 667 */ 668__private_extern__ int 669ptsstop(struct tty* tp, int flush) 670{ 671 struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL); 672 int flag; 673 674 if (pti == NULL) 675 return (ENXIO); 676 677 /* note: FLUSHREAD and FLUSHWRITE already ok */ 678 if (flush == 0) { 679 flush = TIOCPKT_STOP; 680 pti->pt_flags |= PF_STOPPED; 681 } else 682 pti->pt_flags &= ~PF_STOPPED; 683 pti->pt_send |= flush; 684 /* change of perspective */ 685 flag = 0; 686 if (flush & FREAD) 687 flag |= FWRITE; 688 if (flush & FWRITE) 689 flag |= FREAD; 690 ptcwakeup(tp, flag); 691 return 0; 692} 693 694__private_extern__ int 695ptsreset(__unused int uban) 696{ 697 return (0); 698} 699 700int 701ptsselect(dev_t dev, int rw, void *wql, proc_t p) 702{ 703 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL); 704 struct tty *tp; 705 int retval = 0; 706 707 if (pti == NULL) 708 return (ENXIO); 709 tp = pti->pt_tty; 710 if (tp == NULL) 711 return (ENXIO); 712 713 tty_lock(tp); 714 715 switch (rw) { 716 case FREAD: 717 if (ISSET(tp->t_state, TS_ZOMBIE)) { 718 retval = 1; 719 break; 720 } 721 722 retval = ttnread(tp); 723 if (retval > 0) { 724 break; 725 } 726 727 selrecord(p, &tp->t_rsel, wql); 728 break; 729 case FWRITE: 730 if (ISSET(tp->t_state, TS_ZOMBIE)) { 731 retval = 1; 732 break; 733 } 734 735 if ((tp->t_outq.c_cc <= tp->t_lowat) && 736 ISSET(tp->t_state, TS_CONNECTED)) { 737 retval = tp->t_hiwat - tp->t_outq.c_cc; 738 break; 739 } 740 741 selrecord(p, &tp->t_wsel, wql); 742 break; 743 } 744 745 tty_unlock(tp); 746 return (retval); 747} 748 749__private_extern__ int 750ptcselect(dev_t dev, int rw, void *wql, proc_t p) 751{ 752 struct tty_dev_t *driver; 753 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver); 754 struct tty *tp; 755 int retval = 0; 756 757 if (pti == NULL) 758 return (ENXIO); 759 tp = pti->pt_tty; 760 tty_lock(tp); 761 762 if ((tp->t_state & TS_CONNECTED) == 0) { 763 retval = 1; 764 goto out; 765 } 766 switch (rw) { 767 768 case FREAD: 769 /* 770 * Need to block timeouts (ttrstart). 771 */ 772 if ((tp->t_state&TS_ISOPEN) && 773 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 774 retval = (driver->fix_7828447) ? tp->t_outq.c_cc : 1; 775 break; 776 } 777 /* FALLTHROUGH */ 778 779 case 0: /* exceptional */ 780 if ((tp->t_state&TS_ISOPEN) && 781 ((pti->pt_flags & PF_PKT && pti->pt_send) || 782 (pti->pt_flags & PF_UCNTL && pti->pt_ucntl))) { 783 retval = 1; 784 break; 785 } 786 selrecord(p, &pti->pt_selr, wql); 787 break; 788 789 790 case FWRITE: 791 if (tp->t_state&TS_ISOPEN) { 792 if (pti->pt_flags & PF_REMOTE) { 793 if (tp->t_canq.c_cc == 0) { 794 retval = (driver->fix_7828447) ? (TTYHOG - 1) : 1; 795 break; 796 } 797 } else { 798 retval = (TTYHOG - 2) - (tp->t_rawq.c_cc + tp->t_canq.c_cc); 799 if (retval > 0) { 800 retval = (driver->fix_7828447) ? retval : 1; 801 break; 802 } 803 if (tp->t_canq.c_cc == 0 && (tp->t_lflag&ICANON)) { 804 retval = 1; 805 break; 806 } 807 retval = 0; 808 } 809 } 810 selrecord(p, &pti->pt_selw, wql); 811 break; 812 813 } 814out: 815 tty_unlock(tp); 816 817 return (retval); 818} 819 820__private_extern__ int 821ptcstop(__unused struct tty *tp, __unused int flush) 822{ 823 return (0); 824} 825 826__private_extern__ int 827ptcreset(__unused int uban) 828{ 829 return (0); 830} 831 832__private_extern__ int 833ptcwrite(dev_t dev, struct uio *uio, int flag) 834{ 835 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL); 836 struct tty *tp; 837 u_char *cp = NULL; 838 int cc = 0; 839 u_char locbuf[BUFSIZ]; 840 int wcnt = 0; 841 int error = 0; 842 843 if (pti == NULL) 844 return (ENXIO); 845 tp = pti->pt_tty; 846 tty_lock(tp); 847 848again: 849 if ((tp->t_state & TS_ISOPEN) == 0) 850 goto block; 851 if (pti->pt_flags & PF_REMOTE) { 852 if (tp->t_canq.c_cc) 853 goto block; 854 while ((uio_resid(uio) > 0 || cc > 0) && 855 tp->t_canq.c_cc < TTYHOG - 1) { 856 if (cc == 0) { 857 cc = MIN((int)uio_resid(uio), BUFSIZ); 858 cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 859 cp = locbuf; 860 error = uiomove((caddr_t)cp, cc, uio); 861 if (error) 862 goto out; 863 /* check again for safety */ 864 if ((tp->t_state & TS_ISOPEN) == 0) { 865 /* adjust as usual */ 866 uio_setresid(uio, (uio_resid(uio) + cc)); 867 error = EIO; 868 goto out; 869 } 870 } 871 if (cc > 0) { 872 cc = b_to_q((u_char *)cp, cc, &tp->t_canq); 873 /* 874 * XXX we don't guarantee that the canq size 875 * is >= TTYHOG, so the above b_to_q() may 876 * leave some bytes uncopied. However, space 877 * is guaranteed for the null terminator if 878 * we don't fail here since (TTYHOG - 1) is 879 * not a multiple of CBSIZE. 880 */ 881 if (cc > 0) 882 break; 883 } 884 } 885 /* adjust for data copied in but not written */ 886 uio_setresid(uio, (uio_resid(uio) + cc)); 887 (void) putc(0, &tp->t_canq); 888 ttwakeup(tp); 889 wakeup(TSA_PTS_READ(tp)); 890 goto out; 891 } 892 while (uio_resid(uio) > 0 || cc > 0) { 893 if (cc == 0) { 894 cc = MIN((int)uio_resid(uio), BUFSIZ); 895 cp = locbuf; 896 error = uiomove((caddr_t)cp, cc, uio); 897 if (error) 898 goto out; 899 /* check again for safety */ 900 if ((tp->t_state & TS_ISOPEN) == 0) { 901 /* adjust for data copied in but not written */ 902 uio_setresid(uio, (uio_resid(uio) + cc)); 903 error = EIO; 904 goto out; 905 } 906 } 907 while (cc > 0) { 908 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 909 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) { 910 wakeup(TSA_HUP_OR_INPUT(tp)); 911 goto block; 912 } 913 (*linesw[tp->t_line].l_rint)(*cp++, tp); 914 wcnt++; 915 cc--; 916 } 917 cc = 0; 918 } 919out: 920 tty_unlock(tp); 921 922 return (error); 923 924block: 925 /* 926 * Come here to wait for slave to open, for space 927 * in outq, or space in rawq, or an empty canq. 928 */ 929 if ((tp->t_state & TS_CONNECTED) == 0) { 930 /* adjust for data copied in but not written */ 931 uio_setresid(uio, (uio_resid(uio) + cc)); 932 error = EIO; 933 goto out; 934 } 935 if (flag & IO_NDELAY) { 936 /* adjust for data copied in but not written */ 937 uio_setresid(uio, (uio_resid(uio) + cc)); 938 if (wcnt == 0) 939 error = EWOULDBLOCK; 940 goto out; 941 } 942 error = ttysleep(tp, TSA_PTC_WRITE(tp), TTOPRI | PCATCH, __FUNCTION__, 0); 943 if (error) { 944 /* adjust for data copied in but not written */ 945 uio_setresid(uio, (uio_resid(uio) + cc)); 946 goto out; 947 } 948 goto again; 949} 950 951__private_extern__ int 952ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 953{ 954 struct tty_dev_t *driver; 955 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver); 956 struct tty *tp; 957 int stop, error = 0; 958 int allow_ext_ioctl = 1; 959 960 if (pti == NULL) 961 return (ENXIO); 962 tp = pti->pt_tty; 963 tty_lock(tp); 964 965 u_char *cc = tp->t_cc; 966 967 /* 968 * Do not permit extended ioctls on the master side of the pty unless 969 * the slave side has been successfully opened and initialized. 970 */ 971 if (major(dev) == driver->master && 972 driver->fix_7070978 && 973 ISSET(tp->t_state, TS_IOCTL_NOT_OK)) { 974 allow_ext_ioctl = 0; 975 } 976 977 /* 978 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 979 * ttywflush(tp) will hang if there are characters in the outq. 980 */ 981 if (cmd == TIOCEXT && allow_ext_ioctl) { 982 /* 983 * When the EXTPROC bit is being toggled, we need 984 * to send an TIOCPKT_IOCTL if the packet driver 985 * is turned on. 986 */ 987 if (*(int *)data) { 988 if (pti->pt_flags & PF_PKT) { 989 pti->pt_send |= TIOCPKT_IOCTL; 990 ptcwakeup(tp, FREAD); 991 } 992 tp->t_lflag |= EXTPROC; 993 } else { 994 if ((tp->t_lflag & EXTPROC) && 995 (pti->pt_flags & PF_PKT)) { 996 pti->pt_send |= TIOCPKT_IOCTL; 997 ptcwakeup(tp, FREAD); 998 } 999 tp->t_lflag &= ~EXTPROC; 1000 } 1001 goto out; 1002 } else 1003 if (cdevsw[major(dev)].d_open == ptcopen) { 1004 switch (cmd) { 1005 1006 case TIOCGPGRP: 1007 /* 1008 * We aviod calling ttioctl on the controller since, 1009 * in that case, tp must be the controlling terminal. 1010 */ 1011 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 1012 goto out; 1013 1014 case TIOCPKT: 1015 if (*(int *)data) { 1016 if (pti->pt_flags & PF_UCNTL) { 1017 error = EINVAL; 1018 goto out; 1019 } 1020 pti->pt_flags |= PF_PKT; 1021 } else 1022 pti->pt_flags &= ~PF_PKT; 1023 goto out; 1024 1025 case TIOCUCNTL: 1026 if (*(int *)data) { 1027 if (pti->pt_flags & PF_PKT) { 1028 error = EINVAL; 1029 goto out; 1030 } 1031 pti->pt_flags |= PF_UCNTL; 1032 } else 1033 pti->pt_flags &= ~PF_UCNTL; 1034 goto out; 1035 1036 case TIOCREMOTE: 1037 if (*(int *)data) 1038 pti->pt_flags |= PF_REMOTE; 1039 else 1040 pti->pt_flags &= ~PF_REMOTE; 1041 ttyflush(tp, FREAD|FWRITE); 1042 goto out; 1043 1044 case TIOCSETP: 1045 case TIOCSETN: 1046 case TIOCSETD: 1047 case TIOCSETA_32: 1048 case TIOCSETAW_32: 1049 case TIOCSETAF_32: 1050 case TIOCSETA_64: 1051 case TIOCSETAW_64: 1052 case TIOCSETAF_64: 1053 ndflush(&tp->t_outq, tp->t_outq.c_cc); 1054 break; 1055 1056 case TIOCSIG: 1057 if (*(unsigned int *)data >= NSIG || 1058 *(unsigned int *)data == 0) { 1059 error = EINVAL; 1060 goto out; 1061 } 1062 if ((tp->t_lflag&NOFLSH) == 0) 1063 ttyflush(tp, FREAD|FWRITE); 1064 if ((*(unsigned int *)data == SIGINFO) && 1065 ((tp->t_lflag&NOKERNINFO) == 0)) 1066 ttyinfo_locked(tp); 1067 /* 1068 * SAFE: All callers drop the lock on return and 1069 * SAFE: the linesw[] will short circut this call 1070 * SAFE: if the ioctl() is eaten before the lower 1071 * SAFE: level code gets to see it. 1072 */ 1073 tty_unlock(tp); 1074 tty_pgsignal(tp, *(unsigned int *)data, 1); 1075 tty_lock(tp); 1076 goto out; 1077 1078 case TIOCPTYGRANT: /* grantpt(3) */ 1079 /* 1080 * Change the uid of the slave to that of the calling 1081 * thread, change the gid of the slave to GID_TTY, 1082 * change the mode to 0620 (rw--w----). 1083 */ 1084 { 1085 error = _devfs_setattr(pti->pt_devhandle, 0620, kauth_getuid(), GID_TTY); 1086 if (major(dev) == driver->master) { 1087 if (driver->mac_notify) { 1088#if CONFIG_MACF 1089 if (!error) { 1090 tty_unlock(tp); 1091 mac_pty_notify_grant(p, tp, dev, NULL); 1092 tty_lock(tp); 1093 } 1094#endif 1095 } else { 1096 error = 0; 1097 } 1098 } 1099 goto out; 1100 } 1101 1102 case TIOCPTYGNAME: /* ptsname(3) */ 1103 /* 1104 * Report the name of the slave device in *data 1105 * (128 bytes max.). Use the same template string 1106 * used for calling devfs_make_node() to create it. 1107 */ 1108 pty_get_name(dev, data, 128); 1109 error = 0; 1110 goto out; 1111 1112 case TIOCPTYUNLK: /* unlockpt(3) */ 1113 /* 1114 * Unlock the slave device so that it can be opened. 1115 */ 1116 if (major(dev) == driver->master) { 1117 pti->pt_flags |= PF_UNLOCKED; 1118 } 1119 error = 0; 1120 goto out; 1121 } 1122 1123 /* 1124 * Fail all other calls; pty masters are not serial devices; 1125 * we only pretend they are when the slave side of the pty is 1126 * already open. 1127 */ 1128 if (!allow_ext_ioctl) { 1129 error = ENOTTY; 1130 goto out; 1131 } 1132 } 1133 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1134 if (error == ENOTTY) { 1135 error = ttioctl_locked(tp, cmd, data, flag, p); 1136 if (error == ENOTTY) { 1137 if (pti->pt_flags & PF_UCNTL && (cmd & ~0xff) == UIOCCMD(0)) { 1138 /* Process the UIOCMD ioctl group */ 1139 if (cmd & 0xff) { 1140 pti->pt_ucntl = (u_char)cmd; 1141 ptcwakeup(tp, FREAD); 1142 } 1143 error = 0; 1144 goto out; 1145 } else if (cmd == TIOCSBRK || cmd == TIOCCBRK) { 1146 /* 1147 * POSIX conformance; rdar://3936338 1148 * 1149 * Clear ENOTTY in the case of setting or 1150 * clearing a break failing because pty's 1151 * don't support break like real serial 1152 * ports. 1153 */ 1154 error = 0; 1155 goto out; 1156 } 1157 } 1158 } 1159 1160 /* 1161 * If external processing and packet mode send ioctl packet. 1162 */ 1163 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 1164 switch(cmd) { 1165 case TIOCSETA_32: 1166 case TIOCSETAW_32: 1167 case TIOCSETAF_32: 1168 case TIOCSETA_64: 1169 case TIOCSETAW_64: 1170 case TIOCSETAF_64: 1171 case TIOCSETP: 1172 case TIOCSETN: 1173 case TIOCSETC: 1174 case TIOCSLTC: 1175 case TIOCLBIS: 1176 case TIOCLBIC: 1177 case TIOCLSET: 1178 pti->pt_send |= TIOCPKT_IOCTL; 1179 ptcwakeup(tp, FREAD); 1180 default: 1181 break; 1182 } 1183 } 1184 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 1185 && CCEQ(cc[VSTART], CTRL('q')); 1186 if (pti->pt_flags & PF_NOSTOP) { 1187 if (stop) { 1188 pti->pt_send &= ~TIOCPKT_NOSTOP; 1189 pti->pt_send |= TIOCPKT_DOSTOP; 1190 pti->pt_flags &= ~PF_NOSTOP; 1191 ptcwakeup(tp, FREAD); 1192 } 1193 } else { 1194 if (!stop) { 1195 pti->pt_send &= ~TIOCPKT_DOSTOP; 1196 pti->pt_send |= TIOCPKT_NOSTOP; 1197 pti->pt_flags |= PF_NOSTOP; 1198 ptcwakeup(tp, FREAD); 1199 } 1200 } 1201out: 1202 tty_unlock(tp); 1203 1204 return (error); 1205} 1206