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