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