]> git.saurik.com Git - apple/xnu.git/blame_incremental - bsd/kern/tty_ptmx.c
xnu-2422.115.4.tar.gz
[apple/xnu.git] / bsd / kern / tty_ptmx.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1997-2010 Apple Computer, 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/*
64 * Pseudo-teletype Driver
65 * (Actually two drivers, requiring two entries in 'cdevsw')
66 */
67#include "pty.h" /* XXX */
68
69#include <sys/param.h>
70#include <sys/systm.h>
71#include <sys/ioctl.h>
72#include <sys/proc_internal.h>
73#include <sys/kauth.h>
74#include <sys/tty.h>
75#include <sys/conf.h>
76#include <sys/file_internal.h>
77#include <sys/uio_internal.h>
78#include <sys/kernel.h>
79#include <sys/vnode.h>
80#include <sys/vnode_internal.h> /* _devfs_setattr() */
81#include <sys/stat.h> /* _devfs_setattr() */
82#include <sys/user.h>
83#include <sys/signalvar.h>
84#include <sys/sysctl.h>
85#include <miscfs/devfs/devfs.h>
86#include <miscfs/devfs/devfsdefs.h> /* DEVFS_LOCK()/DEVFS_UNLOCK() */
87
88#if CONFIG_MACF
89#include <security/mac_framework.h>
90#endif
91
92/* XXX belongs in devfs somewhere - LATER */
93int _devfs_setattr(void *, unsigned short, uid_t, gid_t);
94
95
96#define FREE_BSDSTATIC __private_extern__
97#define d_devtotty_t struct tty **
98
99/*
100 * Forward declarations
101 */
102int ptmx_init(int n_ptys);
103static void ptsd_start(struct tty *tp);
104static void ptmx_wakeup(struct tty *tp, int flag);
105__XNU_PRIVATE_EXTERN d_open_t ptsd_open;
106__XNU_PRIVATE_EXTERN d_close_t ptsd_close;
107__XNU_PRIVATE_EXTERN d_read_t ptsd_read;
108__XNU_PRIVATE_EXTERN d_write_t ptsd_write;
109__XNU_PRIVATE_EXTERN d_ioctl_t cptyioctl; /* common ioctl */
110__XNU_PRIVATE_EXTERN d_stop_t ptsd_stop;
111__XNU_PRIVATE_EXTERN d_reset_t ptsd_reset;
112__XNU_PRIVATE_EXTERN d_open_t ptmx_open;
113__XNU_PRIVATE_EXTERN d_close_t ptmx_close;
114__XNU_PRIVATE_EXTERN d_read_t ptmx_read;
115__XNU_PRIVATE_EXTERN d_write_t ptmx_write;
116__XNU_PRIVATE_EXTERN d_stop_t ptmx_stop; /* NO-OP */
117__XNU_PRIVATE_EXTERN d_reset_t ptmx_reset;
118__XNU_PRIVATE_EXTERN d_select_t ptmx_select;
119__XNU_PRIVATE_EXTERN d_select_t ptsd_select;
120
121extern d_devtotty_t ptydevtotty;
122
123static int ptmx_major; /* dynamically assigned major number */
124static struct cdevsw ptmx_cdev = {
125 ptmx_open, ptmx_close, ptmx_read, ptmx_write,
126 cptyioctl, ptmx_stop, ptmx_reset, 0,
127 ptmx_select, eno_mmap, eno_strat, eno_getc,
128 eno_putc, D_TTY
129};
130
131static int ptsd_major; /* dynamically assigned major number */
132static struct cdevsw ptsd_cdev = {
133 ptsd_open, ptsd_close, ptsd_read, ptsd_write,
134 cptyioctl, ptsd_stop, ptsd_reset, 0,
135 ptsd_select, eno_mmap, eno_strat, eno_getc,
136 eno_putc, D_TTY
137};
138
139/*
140 * XXX Should be devfs function... and use VATTR mechanisms, per
141 * XXX vnode_setattr2(); only we maybe can't really get back to the
142 * XXX vnode here for cloning devices (but it works for *cloned* devices
143 * XXX that are not themselves cloning).
144 *
145 * Returns: 0 Success
146 * namei:???
147 * vnode_setattr:???
148 */
149int
150_devfs_setattr(void * handle, unsigned short mode, uid_t uid, gid_t gid)
151{
152 devdirent_t *direntp = (devdirent_t *)handle;
153 devnode_t *devnodep;
154 int error = EACCES;
155 vfs_context_t ctx = vfs_context_current();;
156 struct vnode_attr va;
157
158 VATTR_INIT(&va);
159 VATTR_SET(&va, va_uid, uid);
160 VATTR_SET(&va, va_gid, gid);
161 VATTR_SET(&va, va_mode, mode & ALLPERMS);
162
163 /*
164 * If the TIOCPTYGRANT loses the race with the clone operation because
165 * this function is not part of devfs, and therefore can't take the
166 * devfs lock to protect the direntp update, then force user space to
167 * redrive the grant request.
168 */
169 if (direntp == NULL || (devnodep = direntp->de_dnp) == NULL) {
170 error = ERESTART;
171 goto out;
172 }
173
174 /*
175 * Only do this if we are operating on device that doesn't clone
176 * each time it's referenced. We perform a lookup on the device
177 * to insure we get the right instance. We can't just use the call
178 * to devfs_dntovn() to get the vp for the operation, because
179 * dn_dvm may not have been initialized.
180 */
181 if (devnodep->dn_clone == NULL) {
182 struct nameidata nd;
183 char name[128];
184
185 snprintf(name, sizeof(name), "/dev/%s", direntp->de_name);
186 NDINIT(&nd, LOOKUP, OP_SETATTR, FOLLOW, UIO_SYSSPACE, CAST_USER_ADDR_T(name), ctx);
187 error = namei(&nd);
188 if (error)
189 goto out;
190 error = vnode_setattr(nd.ni_vp, &va, ctx);
191 vnode_put(nd.ni_vp);
192 nameidone(&nd);
193 goto out;
194 }
195
196out:
197 return(error);
198}
199
200
201
202#define BUFSIZ 100 /* Chunk size iomoved to/from user */
203
204/*
205 * ptmx == /dev/ptmx
206 * ptsd == /dev/pts[0123456789]{3}
207 */
208#define PTMX_TEMPLATE "ptmx"
209#define PTSD_TEMPLATE "ttys%03d"
210
211/*
212 * System-wide limit on the max number of cloned ptys
213 */
214#define PTMX_MAX_DEFAULT 127 /* 128 entries */
215#define PTMX_MAX_HARD 999 /* 1000 entries, due to PTSD_TEMPLATE */
216
217static int ptmx_max = PTMX_MAX_DEFAULT; /* default # of clones we allow */
218
219/* Range enforcement for the sysctl */
220static int
221sysctl_ptmx_max(__unused struct sysctl_oid *oidp, __unused void *arg1,
222 __unused int arg2, struct sysctl_req *req)
223{
224 int new_value, changed;
225 int error = sysctl_io_number(req, ptmx_max, sizeof(int), &new_value, &changed);
226 if (changed) {
227 if (new_value > 0 && new_value <= PTMX_MAX_HARD)
228 ptmx_max = new_value;
229 else
230 error = EINVAL;
231 }
232 return(error);
233}
234
235SYSCTL_NODE(_kern, KERN_TTY, tty, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "TTY");
236SYSCTL_PROC(_kern_tty, OID_AUTO, ptmx_max,
237 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
238 &ptmx_max, 0, &sysctl_ptmx_max, "I", "ptmx_max");
239
240
241/*
242 * ptmx_ioctl is a pointer to a list of pointers to tty structures which is
243 * grown, as necessary, copied, and replaced, but never shrunk. The ioctl
244 * structures themselves pointed to from this list come and go as needed.
245 */
246struct ptmx_ioctl {
247 struct tty *pt_tty; /* pointer to ttymalloc()'ed data */
248 int pt_flags;
249 struct selinfo pt_selr;
250 struct selinfo pt_selw;
251 u_char pt_send;
252 u_char pt_ucntl;
253 void *pt_devhandle; /* cloned slave device handle */
254};
255
256#define PF_PKT 0x0008 /* packet mode */
257#define PF_STOPPED 0x0010 /* user told stopped */
258#define PF_REMOTE 0x0020 /* remote and flow controlled input */
259#define PF_NOSTOP 0x0040
260#define PF_UCNTL 0x0080 /* user control mode */
261#define PF_UNLOCKED 0x0100 /* slave unlock (master open resets) */
262#define PF_OPEN_M 0x0200 /* master is open */
263#define PF_OPEN_S 0x0400 /* slave is open */
264
265static int ptmx_clone(dev_t dev, int minor);
266
267/*
268 * Set of locks to keep the interaction between kevents and revoke
269 * from causing havoc.
270 */
271
272#define LOG2_PTSD_KE_NLCK 2
273#define PTSD_KE_NLCK (1l << LOG2_PTSD_KE_NLCK)
274#define PTSD_KE_LOCK_INDEX(x) ((x) & (PTSD_KE_NLCK - 1))
275
276static lck_mtx_t ptsd_kevent_lock[PTSD_KE_NLCK];
277
278static void
279ptsd_kevent_lock_init(void)
280{
281 int i;
282 lck_grp_t *lgrp = lck_grp_alloc_init("ptsd kevent", LCK_GRP_ATTR_NULL);
283
284 for (i = 0; i < PTSD_KE_NLCK; i++)
285 lck_mtx_init(&ptsd_kevent_lock[i], lgrp, LCK_ATTR_NULL);
286}
287
288static void
289ptsd_kevent_mtx_lock(int minor)
290{
291 lck_mtx_lock(&ptsd_kevent_lock[PTSD_KE_LOCK_INDEX(minor)]);
292}
293
294static void
295ptsd_kevent_mtx_unlock(int minor)
296{
297 lck_mtx_unlock(&ptsd_kevent_lock[PTSD_KE_LOCK_INDEX(minor)]);
298}
299
300int
301ptmx_init( __unused int config_count)
302{
303 /*
304 * We start looking at slot 10, since there are inits that will
305 * stomp explicit slots (e.g. vndevice stomps 1) below that.
306 */
307
308 /* Get a major number for /dev/ptmx */
309 if((ptmx_major = cdevsw_add(-15, &ptmx_cdev)) == -1) {
310 printf("ptmx_init: failed to obtain /dev/ptmx major number\n");
311 return (ENOENT);
312 }
313
314 if (cdevsw_setkqueueok(ptmx_major, &ptmx_cdev, 0) == -1) {
315 panic("Failed to set flags on ptmx cdevsw entry.");
316 }
317
318 /* Get a major number for /dev/pts/nnn */
319 if ((ptsd_major = cdevsw_add(-15, &ptsd_cdev)) == -1) {
320 (void)cdevsw_remove(ptmx_major, &ptmx_cdev);
321 printf("ptmx_init: failed to obtain /dev/ptmx major number\n");
322 return (ENOENT);
323 }
324
325 if (cdevsw_setkqueueok(ptsd_major, &ptsd_cdev, 0) == -1) {
326 panic("Failed to set flags on ptmx cdevsw entry.");
327 }
328
329 /*
330 * Locks to guard against races between revoke and kevents
331 */
332 ptsd_kevent_lock_init();
333
334 /* Create the /dev/ptmx device {<major>,0} */
335 (void)devfs_make_node_clone(makedev(ptmx_major, 0),
336 DEVFS_CHAR, UID_ROOT, GID_TTY, 0666,
337 ptmx_clone, PTMX_TEMPLATE);
338 return (0);
339}
340
341
342static struct _ptmx_ioctl_state {
343 struct ptmx_ioctl **pis_ioctl_list; /* pointer vector */
344 int pis_total; /* total slots */
345 int pis_free; /* free slots */
346} _state;
347#define PTMX_GROW_VECTOR 16 /* Grow by this many slots at a time */
348
349/*
350 * Given a minor number, return the corresponding structure for that minor
351 * number. If there isn't one, and the create flag is specified, we create
352 * one if possible.
353 *
354 * Parameters: minor Minor number of ptmx device
355 * open_flag PF_OPEN_M First open of master
356 * PF_OPEN_S First open of slave
357 * 0 Just want ioctl struct
358 *
359 * Returns: NULL Did not exist/could not create
360 * !NULL structure corresponding minor number
361 *
362 * Locks: tty_lock() on ptmx_ioctl->pt_tty NOT held on entry or exit.
363 */
364static struct ptmx_ioctl *
365ptmx_get_ioctl(int minor, int open_flag)
366{
367 struct ptmx_ioctl *new_ptmx_ioctl;
368
369 if (open_flag & PF_OPEN_M) {
370
371 /*
372 * If we are about to allocate more memory, but we have
373 * already hit the administrative limit, then fail the
374 * operation.
375 *
376 * Note: Subtract free from total when making this
377 * check to allow unit increments, rather than
378 * snapping to the nearest PTMX_GROW_VECTOR...
379 */
380 if ((_state.pis_total - _state.pis_free) >= ptmx_max) {
381 return (NULL);
382 }
383
384 MALLOC(new_ptmx_ioctl, struct ptmx_ioctl *, sizeof(struct ptmx_ioctl), M_TTYS, M_WAITOK|M_ZERO);
385 if (new_ptmx_ioctl == NULL) {
386 return (NULL);
387 }
388
389 if ((new_ptmx_ioctl->pt_tty = ttymalloc()) == NULL) {
390 FREE(new_ptmx_ioctl, M_TTYS);
391 return (NULL);
392 }
393
394 /*
395 * Hold the DEVFS_LOCK() over this whole operation; devfs
396 * itself does this over malloc/free as well, so this should
397 * be safe to do. We hold it longer than we want to, but
398 * doing so avoids a reallocation race on the minor number.
399 */
400 DEVFS_LOCK();
401 /* Need to allocate a larger vector? */
402 if (_state.pis_free == 0) {
403 struct ptmx_ioctl **new_pis_ioctl_list;
404 struct ptmx_ioctl **old_pis_ioctl_list = NULL;
405
406 /* Yes. */
407 MALLOC(new_pis_ioctl_list, struct ptmx_ioctl **, sizeof(struct ptmx_ioctl *) * (_state.pis_total + PTMX_GROW_VECTOR), M_TTYS, M_WAITOK|M_ZERO);
408 if (new_pis_ioctl_list == NULL) {
409 ttyfree(new_ptmx_ioctl->pt_tty);
410 DEVFS_UNLOCK();
411 FREE(new_ptmx_ioctl, M_TTYS);
412 return (NULL);
413 }
414
415 /* If this is not the first time, copy the old over */
416 bcopy(_state.pis_ioctl_list, new_pis_ioctl_list, sizeof(struct ptmx_ioctl *) * _state.pis_total);
417 old_pis_ioctl_list = _state.pis_ioctl_list;
418 _state.pis_ioctl_list = new_pis_ioctl_list;
419 _state.pis_free += PTMX_GROW_VECTOR;
420 _state.pis_total += PTMX_GROW_VECTOR;
421 if (old_pis_ioctl_list)
422 FREE(old_pis_ioctl_list, M_TTYS);
423 }
424
425 if (_state.pis_ioctl_list[minor] != NULL) {
426 ttyfree(new_ptmx_ioctl->pt_tty);
427 DEVFS_UNLOCK();
428 FREE(new_ptmx_ioctl, M_TTYS);
429
430 /* Special error value so we know to redrive the open, we've been raced */
431 return (struct ptmx_ioctl*)-1;
432
433 }
434
435 /* Vector is large enough; grab a new ptmx_ioctl */
436
437 /* Now grab a free slot... */
438 _state.pis_ioctl_list[minor] = new_ptmx_ioctl;
439
440 /* reduce free count */
441 _state.pis_free--;
442
443 _state.pis_ioctl_list[minor]->pt_flags |= PF_OPEN_M;
444 DEVFS_UNLOCK();
445
446 /* Create the /dev/ttysXXX device {<major>,XXX} */
447 _state.pis_ioctl_list[minor]->pt_devhandle = devfs_make_node(
448 makedev(ptsd_major, minor),
449 DEVFS_CHAR, UID_ROOT, GID_TTY, 0620,
450 PTSD_TEMPLATE, minor);
451 if (_state.pis_ioctl_list[minor]->pt_devhandle == NULL) {
452 printf("devfs_make_node() call failed for ptmx_get_ioctl()!!!!\n");
453 }
454 } else if (open_flag & PF_OPEN_S) {
455 DEVFS_LOCK();
456 _state.pis_ioctl_list[minor]->pt_flags |= PF_OPEN_S;
457 DEVFS_UNLOCK();
458 }
459 return (_state.pis_ioctl_list[minor]);
460}
461
462/*
463 * Locks: tty_lock() of old_ptmx_ioctl->pt_tty NOT held for this call.
464 */
465static int
466ptmx_free_ioctl(int minor, int open_flag)
467{
468 struct ptmx_ioctl *old_ptmx_ioctl = NULL;
469
470 DEVFS_LOCK();
471 _state.pis_ioctl_list[minor]->pt_flags &= ~(open_flag);
472
473 /*
474 * Was this the last close? We will recognize it because we only get
475 * a notification on the last close of a device, and we will have
476 * cleared both the master and the slave open bits in the flags.
477 */
478 if (!(_state.pis_ioctl_list[minor]->pt_flags & (PF_OPEN_M|PF_OPEN_S))) {
479 /* Mark as free so it can be reallocated later */
480 old_ptmx_ioctl = _state.pis_ioctl_list[ minor];
481 }
482 DEVFS_UNLOCK();
483
484 /* Free old after dropping lock */
485 if (old_ptmx_ioctl != NULL) {
486 /*
487 * XXX See <rdar://5348651> and <rdar://4854638>
488 *
489 * XXX Conditional to be removed when/if tty/pty reference
490 * XXX counting and mutex implemented.
491 */
492 if (old_ptmx_ioctl->pt_devhandle != NULL)
493 devfs_remove(old_ptmx_ioctl->pt_devhandle);
494 ttyfree(old_ptmx_ioctl->pt_tty);
495 FREE(old_ptmx_ioctl, M_TTYS);
496
497 /* Don't remove the entry until the devfs slot is free */
498 DEVFS_LOCK();
499 _state.pis_ioctl_list[ minor] = NULL;
500 _state.pis_free++;
501 DEVFS_UNLOCK();
502 }
503
504 return (0); /* Success */
505}
506
507
508
509
510/*
511 * Given the dev entry that's being opened, we clone the device. This driver
512 * doesn't actually use the dev entry, since we alreaqdy know who we are by
513 * being called from this code. This routine is a callback registered from
514 * devfs_make_node_clone() in ptmx_init(); it's purpose is to provide a new
515 * minor number, or to return -1, if one can't be provided.
516 *
517 * Parameters: dev The device we are cloning from
518 *
519 * Returns: >= 0 A new minor device number
520 * -1 Error: ENOMEM ("Can't alloc device")
521 *
522 * NOTE: Called with DEVFS_LOCK() held
523 */
524static int
525ptmx_clone(__unused dev_t dev, int action)
526{
527 int i;
528
529 if (action == DEVFS_CLONE_ALLOC) {
530 /* First one */
531 if (_state.pis_total == 0)
532 return (0);
533
534 /*
535 * Note: We can add hinting on free slots, if this linear search
536 * ends up being a performance bottleneck...
537 */
538 for(i = 0; i < _state.pis_total; i++) {
539 if (_state.pis_ioctl_list[ i] == NULL)
540 break;
541 }
542
543 /*
544 * XXX We fall off the end here; if we did this twice at the
545 * XXX same time, we could return the same minor to two
546 * XXX callers; we should probably exand the pointer vector
547 * XXX here, but I need more information on the MALLOC/FREE
548 * XXX locking to ensure against a deadlock. Maybe we can
549 * XXX just high watermark it at 1/2 of PTMX_GROW_VECTOR?
550 * XXX That would require returning &minor as implict return
551 * XXX and an error code ("EAGAIN/ERESTART") or 0 as our
552 * XXX explicit return.
553 */
554
555 return (i); /* empty slot or next slot */
556 }
557 return(-1);
558}
559
560FREE_BSDSTATIC int
561ptsd_open(dev_t dev, int flag, __unused int devtype, __unused proc_t p)
562{
563 struct tty *tp;
564 struct ptmx_ioctl *pti;
565 int error;
566
567 if ((pti = ptmx_get_ioctl(minor(dev), 0)) == NULL) {
568 return (ENXIO);
569 }
570
571 if (!(pti->pt_flags & PF_UNLOCKED)) {
572 return (EAGAIN);
573 }
574
575 tp = pti->pt_tty;
576 tty_lock(tp);
577
578 if ((tp->t_state & TS_ISOPEN) == 0) {
579 termioschars(&tp->t_termios); /* Set up default chars */
580 tp->t_iflag = TTYDEF_IFLAG;
581 tp->t_oflag = TTYDEF_OFLAG;
582 tp->t_lflag = TTYDEF_LFLAG;
583 tp->t_cflag = TTYDEF_CFLAG;
584 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
585 ttsetwater(tp); /* would be done in xxparam() */
586 } else if (tp->t_state&TS_XCLUDE && suser(kauth_cred_get(), NULL)) {
587 error = EBUSY;
588 goto out;
589 }
590 if (tp->t_oproc) /* Ctrlr still around. */
591 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
592 while ((tp->t_state & TS_CARR_ON) == 0) {
593 if (flag&FNONBLOCK)
594 break;
595 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
596 "ptsd_opn", 0);
597 if (error)
598 goto out;
599 }
600 error = (*linesw[tp->t_line].l_open)(dev, tp);
601 /* Successful open; mark as open by the slave */
602 pti->pt_flags |= PF_OPEN_S;
603 CLR(tp->t_state, TS_IOCTL_NOT_OK);
604 if (error == 0)
605 ptmx_wakeup(tp, FREAD|FWRITE);
606out:
607 tty_unlock(tp);
608 return (error);
609}
610
611static void ptsd_revoke_knotes(dev_t, struct tty *);
612
613FREE_BSDSTATIC int
614ptsd_close(dev_t dev, int flag, __unused int mode, __unused proc_t p)
615{
616 struct tty *tp;
617 struct ptmx_ioctl *pti;
618 int err;
619
620 /*
621 * This is temporary until the VSX conformance tests
622 * are fixed. They are hanging with a deadlock
623 * where close(ptsd) will not complete without t_timeout set
624 */
625#define FIX_VSX_HANG 1
626#ifdef FIX_VSX_HANG
627 int save_timeout;
628#endif
629 pti = ptmx_get_ioctl(minor(dev), 0);
630
631 tp = pti->pt_tty;
632 tty_lock(tp);
633
634#ifdef FIX_VSX_HANG
635 save_timeout = tp->t_timeout;
636 tp->t_timeout = 60;
637#endif
638 err = (*linesw[tp->t_line].l_close)(tp, flag);
639 ptsd_stop(tp, FREAD|FWRITE);
640 (void) ttyclose(tp);
641#ifdef FIX_VSX_HANG
642 tp->t_timeout = save_timeout;
643#endif
644 tty_unlock(tp);
645
646 if ((flag & IO_REVOKE) == IO_REVOKE)
647 ptsd_revoke_knotes(dev, tp);
648
649 /* unconditional, just like ttyclose() */
650 ptmx_free_ioctl(minor(dev), PF_OPEN_S);
651
652 return (err);
653}
654
655FREE_BSDSTATIC int
656ptsd_read(dev_t dev, struct uio *uio, int flag)
657{
658 proc_t p = current_proc();
659
660 struct tty *tp;
661 struct ptmx_ioctl *pti;
662 int error = 0;
663 struct uthread *ut;
664 struct pgrp * pg;
665
666 pti = ptmx_get_ioctl(minor(dev), 0);
667
668 tp = pti->pt_tty;
669 tty_lock(tp);
670
671 ut = (struct uthread *)get_bsdthread_info(current_thread());
672again:
673 if (pti->pt_flags & PF_REMOTE) {
674 while (isbackground(p, tp)) {
675 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
676 (ut->uu_sigmask & sigmask(SIGTTIN)) ||
677 p->p_lflag & P_LPPWAIT) {
678 error = EIO;
679 goto out;
680 }
681 pg = proc_pgrp(p);
682 if (pg == PGRP_NULL) {
683 error = EIO;
684 goto out;
685 }
686 /*
687 * SAFE: We about to drop the lock ourselves by
688 * SAFE: erroring out or sleeping anyway.
689 */
690 tty_unlock(tp);
691 if (pg->pg_jobc == 0) {
692 pg_rele(pg);
693 tty_lock(tp);
694 error = EIO;
695 goto out;
696 }
697 pgsignal(pg, SIGTTIN, 1);
698 pg_rele(pg);
699 tty_lock(tp);
700
701 error = ttysleep(tp, &ptsd_read, TTIPRI | PCATCH | PTTYBLOCK, "ptsd_bg",
702 hz);
703 if (error)
704 goto out;
705 }
706 if (tp->t_canq.c_cc == 0) {
707 if (flag & IO_NDELAY) {
708 error = EWOULDBLOCK;
709 goto out;
710 }
711 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
712 "ptsd_in", 0);
713 if (error)
714 goto out;
715 goto again;
716 }
717 while (tp->t_canq.c_cc > 1 && uio_resid(uio) > 0) {
718 int cc;
719 char buf[BUFSIZ];
720
721 cc = MIN(uio_resid(uio), BUFSIZ);
722 // Don't copy the very last byte
723 cc = MIN(cc, tp->t_canq.c_cc - 1);
724 cc = q_to_b(&tp->t_canq, (u_char *)buf, cc);
725 error = uiomove(buf, cc, uio);
726 if (error)
727 break;
728 }
729 if (tp->t_canq.c_cc == 1)
730 (void) getc(&tp->t_canq);
731 if (tp->t_canq.c_cc)
732 goto out;
733 } else
734 if (tp->t_oproc)
735 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
736 ptmx_wakeup(tp, FWRITE);
737out:
738 tty_unlock(tp);
739 return (error);
740}
741
742/*
743 * Write to pseudo-tty.
744 * Wakeups of controlling tty will happen
745 * indirectly, when tty driver calls ptsd_start.
746 */
747FREE_BSDSTATIC int
748ptsd_write(dev_t dev, struct uio *uio, int flag)
749{
750 struct tty *tp;
751 struct ptmx_ioctl *pti;
752 int error;
753
754 pti = ptmx_get_ioctl(minor(dev), 0);
755
756 tp = pti->pt_tty;
757 tty_lock(tp);
758
759 if (tp->t_oproc == 0)
760 error = EIO;
761 else
762 error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
763
764 tty_unlock(tp);
765 return (error);
766}
767
768/*
769 * Start output on pseudo-tty.
770 * Wake up process selecting or sleeping for input from controlling tty.
771 *
772 * t_oproc for this driver; called from within the line discipline
773 *
774 * Locks: Assumes tp is locked on entry, remains locked on exit
775 */
776static void
777ptsd_start(struct tty *tp)
778{
779 struct ptmx_ioctl *pti;
780
781 pti = ptmx_get_ioctl(minor(tp->t_dev), 0);
782
783 if (tp->t_state & TS_TTSTOP)
784 goto out;
785 if (pti->pt_flags & PF_STOPPED) {
786 pti->pt_flags &= ~PF_STOPPED;
787 pti->pt_send = TIOCPKT_START;
788 }
789 ptmx_wakeup(tp, FREAD);
790out:
791 return;
792}
793
794/*
795 * Locks: Assumes tty_lock() is held over this call.
796 */
797static void
798ptmx_wakeup(struct tty *tp, int flag)
799{
800 struct ptmx_ioctl *pti;
801
802 pti = ptmx_get_ioctl(minor(tp->t_dev), 0);
803
804 if (flag & FREAD) {
805 selwakeup(&pti->pt_selr);
806 wakeup(TSA_PTC_READ(tp));
807 }
808 if (flag & FWRITE) {
809 selwakeup(&pti->pt_selw);
810 wakeup(TSA_PTC_WRITE(tp));
811 }
812}
813
814FREE_BSDSTATIC int
815ptmx_open(dev_t dev, __unused int flag, __unused int devtype, __unused proc_t p)
816{
817 struct tty *tp;
818 struct ptmx_ioctl *pti;
819 int error = 0;
820
821 pti = ptmx_get_ioctl(minor(dev), PF_OPEN_M);
822 if (pti == NULL) {
823 return (ENXIO);
824 } else if (pti == (struct ptmx_ioctl*)-1) {
825 return (EREDRIVEOPEN);
826 }
827
828 tp = pti->pt_tty;
829 tty_lock(tp);
830
831 /* If master is open OR slave is still draining, pty is still busy */
832 if (tp->t_oproc || (tp->t_state & TS_ISOPEN)) {
833 tty_unlock(tp);
834 /*
835 * If master is closed, we are the only reference, so we
836 * need to clear the master open bit
837 */
838 if (!tp->t_oproc)
839 ptmx_free_ioctl(minor(dev), PF_OPEN_M);
840 error = EBUSY;
841 goto err;
842 }
843 tp->t_oproc = ptsd_start;
844 CLR(tp->t_state, TS_ZOMBIE);
845 SET(tp->t_state, TS_IOCTL_NOT_OK);
846#ifdef sun4c
847 tp->t_stop = ptsd_stop;
848#endif
849 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
850 tp->t_lflag &= ~EXTPROC;
851
852 tty_unlock(tp);
853err:
854 return (error);
855}
856
857FREE_BSDSTATIC int
858ptmx_close(dev_t dev, __unused int flags, __unused int fmt, __unused proc_t p)
859{
860 struct tty *tp;
861 struct ptmx_ioctl *pti;
862
863 pti = ptmx_get_ioctl(minor(dev), 0);
864
865 tp = pti->pt_tty;
866 tty_lock(tp);
867
868 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
869
870 /*
871 * XXX MDMBUF makes no sense for ptys but would inhibit the above
872 * l_modem(). CLOCAL makes sense but isn't supported. Special
873 * l_modem()s that ignore carrier drop make no sense for ptys but
874 * may be in use because other parts of the line discipline make
875 * sense for ptys. Recover by doing everything that a normal
876 * ttymodem() would have done except for sending a SIGHUP.
877 */
878 if (tp->t_state & TS_ISOPEN) {
879 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
880 tp->t_state |= TS_ZOMBIE;
881 ttyflush(tp, FREAD | FWRITE);
882 }
883
884 tp->t_oproc = 0; /* mark closed */
885
886 tty_unlock(tp);
887
888 ptmx_free_ioctl(minor(dev), PF_OPEN_M);
889
890#if CONFIG_MACF
891 mac_pty_notify_close(p, tp, dev, NULL);
892#endif
893
894 return (0);
895}
896
897FREE_BSDSTATIC int
898ptmx_read(dev_t dev, struct uio *uio, int flag)
899{
900 struct tty *tp;
901 struct ptmx_ioctl *pti;
902 char buf[BUFSIZ];
903 int error = 0, cc;
904
905 pti = ptmx_get_ioctl(minor(dev), 0);
906
907 tp = pti->pt_tty;
908 tty_lock(tp);
909
910 /*
911 * We want to block until the slave
912 * is open, and there's something to read;
913 * but if we lost the slave or we're NBIO,
914 * then return the appropriate error instead.
915 */
916 for (;;) {
917 if (tp->t_state&TS_ISOPEN) {
918 if (pti->pt_flags & PF_PKT && pti->pt_send) {
919 error = ureadc((int)pti->pt_send, uio);
920 if (error)
921 goto out;
922 if (pti->pt_send & TIOCPKT_IOCTL) {
923 cc = MIN(uio_resid(uio),
924 (user_ssize_t)sizeof(tp->t_termios));
925 uiomove((caddr_t)&tp->t_termios, cc,
926 uio);
927 }
928 pti->pt_send = 0;
929 goto out;
930 }
931 if (pti->pt_flags & PF_UCNTL && pti->pt_ucntl) {
932 error = ureadc((int)pti->pt_ucntl, uio);
933 if (error)
934 goto out;
935 pti->pt_ucntl = 0;
936 goto out;
937 }
938 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
939 break;
940 }
941 if ((tp->t_state & TS_CONNECTED) == 0)
942 goto out; /* EOF */
943 if (flag & IO_NDELAY) {
944 error = EWOULDBLOCK;
945 goto out;
946 }
947 error = ttysleep(tp, TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptmx_in", 0);
948 if (error)
949 goto out;
950 }
951 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
952 error = ureadc(0, uio);
953 while (uio_resid(uio) > 0 && error == 0) {
954 cc = q_to_b(&tp->t_outq, (u_char *)buf, MIN(uio_resid(uio), BUFSIZ));
955 if (cc <= 0)
956 break;
957 error = uiomove(buf, cc, uio);
958 }
959 (*linesw[tp->t_line].l_start)(tp);
960
961out:
962 tty_unlock(tp);
963 return (error);
964}
965
966/*
967 * Line discipline callback
968 *
969 * Locks: tty_lock() is assumed held on entry and exit.
970 */
971FREE_BSDSTATIC int
972ptsd_stop(struct tty *tp, int flush)
973{
974 struct ptmx_ioctl *pti;
975 int flag;
976
977 pti = ptmx_get_ioctl(minor(tp->t_dev), 0);
978
979 /* note: FLUSHREAD and FLUSHWRITE already ok */
980 if (flush == 0) {
981 flush = TIOCPKT_STOP;
982 pti->pt_flags |= PF_STOPPED;
983 } else
984 pti->pt_flags &= ~PF_STOPPED;
985 pti->pt_send |= flush;
986 /* change of perspective */
987 flag = 0;
988 if (flush & FREAD)
989 flag |= FWRITE;
990 if (flush & FWRITE)
991 flag |= FREAD;
992 ptmx_wakeup(tp, flag);
993
994 return (0);
995}
996
997FREE_BSDSTATIC int
998ptsd_reset(__unused int uban)
999{
1000 return (0);
1001}
1002
1003/*
1004 * Reinput pending characters after state switch
1005 * call at spltty().
1006 *
1007 * XXX Code duplication: static function, should be inlined
1008 */
1009static void
1010ttypend(struct tty *tp)
1011{
1012 struct clist tq;
1013 int c;
1014
1015 CLR(tp->t_lflag, PENDIN);
1016 SET(tp->t_state, TS_TYPEN);
1017 tq = tp->t_rawq;
1018 tp->t_rawq.c_cc = 0;
1019 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
1020 while ((c = getc(&tq)) >= 0)
1021 ttyinput(c, tp);
1022 CLR(tp->t_state, TS_TYPEN);
1023}
1024
1025/*
1026 * Must be called at spltty().
1027 *
1028 * XXX Code duplication: static function, should be inlined
1029 */
1030static int
1031ttnread(struct tty *tp)
1032{
1033 int nread;
1034
1035 if (ISSET(tp->t_lflag, PENDIN))
1036 ttypend(tp);
1037 nread = tp->t_canq.c_cc;
1038 if (!ISSET(tp->t_lflag, ICANON)) {
1039 nread += tp->t_rawq.c_cc;
1040 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
1041 nread = 0;
1042 }
1043 return (nread);
1044}
1045
1046int
1047ptsd_select(dev_t dev, int rw, void *wql, proc_t p)
1048{
1049 struct ptmx_ioctl *pti;
1050 struct tty *tp;
1051 int retval = 0;
1052
1053 pti = ptmx_get_ioctl(minor(dev), 0);
1054
1055 tp = pti->pt_tty;
1056
1057 if (tp == NULL)
1058 return (ENXIO);
1059
1060 tty_lock(tp);
1061
1062 switch (rw) {
1063 case FREAD:
1064 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1065 retval = 1;
1066 break;
1067 }
1068
1069 retval = ttnread(tp);
1070 if (retval > 0) {
1071 break;
1072 }
1073
1074 selrecord(p, &tp->t_rsel, wql);
1075 break;
1076 case FWRITE:
1077 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1078 retval = 1;
1079 break;
1080 }
1081
1082 if ((tp->t_outq.c_cc <= tp->t_lowat) &&
1083 ISSET(tp->t_state, TS_CONNECTED)) {
1084 retval = tp->t_hiwat - tp->t_outq.c_cc;
1085 break;
1086 }
1087
1088 selrecord(p, &tp->t_wsel, wql);
1089 break;
1090 }
1091
1092 tty_unlock(tp);
1093 return (retval);
1094}
1095
1096FREE_BSDSTATIC int
1097ptmx_select(dev_t dev, int rw, void *wql, proc_t p)
1098{
1099 struct tty *tp;
1100 struct ptmx_ioctl *pti;
1101 int retval = 0;
1102
1103 pti = ptmx_get_ioctl(minor(dev), 0);
1104
1105 tp = pti->pt_tty;
1106 tty_lock(tp);
1107
1108 if ((tp->t_state & TS_CONNECTED) == 0) {
1109 retval = 1;
1110 goto out;
1111 }
1112 switch (rw) {
1113 case FREAD:
1114 /*
1115 * Need to block timeouts (ttrstart).
1116 */
1117 if ((tp->t_state&TS_ISOPEN) &&
1118 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
1119 retval = tp->t_outq.c_cc;
1120 break;
1121 }
1122 /* FALLTHROUGH */
1123
1124 case 0: /* exceptional */
1125 if ((tp->t_state&TS_ISOPEN) &&
1126 ((pti->pt_flags & PF_PKT && pti->pt_send) ||
1127 (pti->pt_flags & PF_UCNTL && pti->pt_ucntl))) {
1128 retval = 1;
1129 break;
1130 }
1131 selrecord(p, &pti->pt_selr, wql);
1132 break;
1133
1134 case FWRITE:
1135 if (tp->t_state&TS_ISOPEN) {
1136 if (pti->pt_flags & PF_REMOTE) {
1137 if (tp->t_canq.c_cc == 0) {
1138 retval = (TTYHOG -1) ;
1139 break;
1140 }
1141 } else {
1142 retval = (TTYHOG - 2) - (tp->t_rawq.c_cc + tp->t_canq.c_cc);
1143 if (retval > 0) {
1144 break;
1145 }
1146 if (tp->t_canq.c_cc == 0 && (tp->t_lflag&ICANON)) {
1147 retval = 1;
1148 break;
1149 }
1150 retval = 0;
1151 }
1152 }
1153 selrecord(p, &pti->pt_selw, wql);
1154 break;
1155
1156 }
1157out:
1158 tty_unlock(tp);
1159 return (retval);
1160}
1161
1162FREE_BSDSTATIC int
1163ptmx_stop(__unused struct tty *tp, __unused int flush)
1164{
1165 return (0);
1166}
1167
1168FREE_BSDSTATIC int
1169ptmx_reset(__unused int uban)
1170{
1171 return (0);
1172}
1173
1174FREE_BSDSTATIC int
1175ptmx_write(dev_t dev, struct uio *uio, int flag)
1176{
1177 struct tty *tp;
1178 struct ptmx_ioctl *pti;
1179 u_char *cp = NULL;
1180 int cc = 0;
1181 u_char locbuf[BUFSIZ];
1182 int wcnt = 0;
1183 int error = 0;
1184
1185 pti = ptmx_get_ioctl(minor(dev), 0);
1186
1187 tp = pti->pt_tty;
1188 tty_lock(tp);
1189
1190again:
1191 if ((tp->t_state&TS_ISOPEN) == 0)
1192 goto block;
1193 if (pti->pt_flags & PF_REMOTE) {
1194 if (tp->t_canq.c_cc)
1195 goto block;
1196 while ((uio_resid(uio) > 0 || cc > 0) &&
1197 tp->t_canq.c_cc < TTYHOG - 1) {
1198 if (cc == 0) {
1199 cc = MIN(uio_resid(uio), BUFSIZ);
1200 cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc);
1201 cp = locbuf;
1202 error = uiomove((caddr_t)cp, cc, uio);
1203 if (error)
1204 goto out;
1205 /* check again for safety */
1206 if ((tp->t_state & TS_ISOPEN) == 0) {
1207 /* adjust as usual */
1208 uio_setresid(uio, (uio_resid(uio) + cc));
1209 error = EIO;
1210 goto out;
1211 }
1212 }
1213 if (cc > 0) {
1214 cc = b_to_q((u_char *)cp, cc, &tp->t_canq);
1215 /*
1216 * XXX we don't guarantee that the canq size
1217 * is >= TTYHOG, so the above b_to_q() may
1218 * leave some bytes uncopied. However, space
1219 * is guaranteed for the null terminator if
1220 * we don't fail here since (TTYHOG - 1) is
1221 * not a multiple of CBSIZE.
1222 */
1223 if (cc > 0)
1224 break;
1225 }
1226 }
1227 /* adjust for data copied in but not written */
1228 uio_setresid(uio, (uio_resid(uio) + cc));
1229 (void) putc(0, &tp->t_canq);
1230 ttwakeup(tp);
1231 wakeup(TSA_PTS_READ(tp));
1232 goto out;
1233 }
1234 while (uio_resid(uio) > 0 || cc > 0) {
1235 if (cc == 0) {
1236 cc = MIN(uio_resid(uio), BUFSIZ);
1237 cp = locbuf;
1238 error = uiomove((caddr_t)cp, cc, uio);
1239 if (error)
1240 goto out;
1241 /* check again for safety */
1242 if ((tp->t_state & TS_ISOPEN) == 0) {
1243 /* adjust for data copied in but not written */
1244 uio_setresid(uio, (uio_resid(uio) + cc));
1245 error = EIO;
1246 goto out;
1247 }
1248 }
1249 while (cc > 0) {
1250 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
1251 (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) {
1252 wakeup(TSA_HUP_OR_INPUT(tp));
1253 goto block;
1254 }
1255 (*linesw[tp->t_line].l_rint)(*cp++, tp);
1256 wcnt++;
1257 cc--;
1258 }
1259 cc = 0;
1260 }
1261
1262out:
1263 tty_unlock(tp);
1264 return (error);
1265
1266block:
1267 /*
1268 * Come here to wait for slave to open, for space
1269 * in outq, or space in rawq, or an empty canq.
1270 */
1271 if ((tp->t_state & TS_CONNECTED) == 0) {
1272 /* adjust for data copied in but not written */
1273 uio_setresid(uio, (uio_resid(uio) + cc));
1274 error = EIO;
1275 goto out;
1276 }
1277 if (flag & IO_NDELAY) {
1278 /* adjust for data copied in but not written */
1279 uio_setresid(uio, (uio_resid(uio) + cc));
1280 if (wcnt == 0)
1281 error = EWOULDBLOCK;
1282 goto out;
1283 }
1284 error = ttysleep(tp, TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptmx_out", 0);
1285 if (error) {
1286 /* adjust for data copied in but not written */
1287 uio_setresid(uio, (uio_resid(uio) + cc));
1288 goto out;
1289 }
1290 goto again;
1291}
1292
1293
1294FREE_BSDSTATIC int
1295cptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, proc_t p)
1296{
1297 struct tty *tp;
1298 struct ptmx_ioctl *pti;
1299 u_char *cc;
1300 int stop, error = 0;
1301 int allow_ext_ioctl = 1;
1302
1303 pti = ptmx_get_ioctl(minor(dev), 0);
1304
1305 tp = pti->pt_tty;
1306 tty_lock(tp);
1307
1308 cc = tp->t_cc;
1309
1310 /*
1311 * Do not permit extended ioctls on the master side of the pty unless
1312 * the slave side has been successfully opened and initialized.
1313 */
1314 if (cdevsw[major(dev)].d_open == ptmx_open && ISSET(tp->t_state, TS_IOCTL_NOT_OK))
1315 allow_ext_ioctl = 0;
1316
1317 /*
1318 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
1319 * ttywflush(tp) will hang if there are characters in the outq.
1320 */
1321 if (cmd == TIOCEXT && allow_ext_ioctl) {
1322 /*
1323 * When the EXTPROC bit is being toggled, we need
1324 * to send an TIOCPKT_IOCTL if the packet driver
1325 * is turned on.
1326 */
1327 if (*(int *)data) {
1328 if (pti->pt_flags & PF_PKT) {
1329 pti->pt_send |= TIOCPKT_IOCTL;
1330 ptmx_wakeup(tp, FREAD);
1331 }
1332 tp->t_lflag |= EXTPROC;
1333 } else {
1334 if ((tp->t_lflag & EXTPROC) &&
1335 (pti->pt_flags & PF_PKT)) {
1336 pti->pt_send |= TIOCPKT_IOCTL;
1337 ptmx_wakeup(tp, FREAD);
1338 }
1339 tp->t_lflag &= ~EXTPROC;
1340 }
1341 goto out;
1342 } else
1343 if (cdevsw[major(dev)].d_open == ptmx_open) {
1344 switch (cmd) {
1345
1346 case TIOCGPGRP:
1347 /*
1348 * We aviod calling ttioctl on the controller since,
1349 * in that case, tp must be the controlling terminal.
1350 */
1351 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
1352 goto out;
1353
1354 case TIOCPKT:
1355 if (*(int *)data) {
1356 if (pti->pt_flags & PF_UCNTL) {
1357 error = EINVAL;
1358 goto out;
1359 }
1360 pti->pt_flags |= PF_PKT;
1361 } else
1362 pti->pt_flags &= ~PF_PKT;
1363 goto out;
1364
1365 case TIOCUCNTL:
1366 if (*(int *)data) {
1367 if (pti->pt_flags & PF_PKT) {
1368 error = EINVAL;
1369 goto out;
1370 }
1371 pti->pt_flags |= PF_UCNTL;
1372 } else
1373 pti->pt_flags &= ~PF_UCNTL;
1374 goto out;
1375
1376 case TIOCREMOTE:
1377 if (*(int *)data)
1378 pti->pt_flags |= PF_REMOTE;
1379 else
1380 pti->pt_flags &= ~PF_REMOTE;
1381 ttyflush(tp, FREAD|FWRITE);
1382 goto out;
1383
1384 case TIOCSETP:
1385 case TIOCSETN:
1386 case TIOCSETD:
1387 case TIOCSETA_32:
1388 case TIOCSETAW_32:
1389 case TIOCSETAF_32:
1390 case TIOCSETA_64:
1391 case TIOCSETAW_64:
1392 case TIOCSETAF_64:
1393 ndflush(&tp->t_outq, tp->t_outq.c_cc);
1394 break;
1395
1396 case TIOCSIG:
1397 if (*(unsigned int *)data >= NSIG ||
1398 *(unsigned int *)data == 0) {
1399 error = EINVAL;
1400 goto out;
1401 }
1402 if ((tp->t_lflag&NOFLSH) == 0)
1403 ttyflush(tp, FREAD|FWRITE);
1404 if ((*(unsigned int *)data == SIGINFO) &&
1405 ((tp->t_lflag&NOKERNINFO) == 0))
1406 ttyinfo_locked(tp);
1407 /*
1408 * SAFE: All callers drop the lock on return and
1409 * SAFE: the linesw[] will short circut this call
1410 * SAFE: if the ioctl() is eaten before the lower
1411 * SAFE: level code gets to see it.
1412 */
1413 tty_unlock(tp);
1414 tty_pgsignal(tp, *(unsigned int *)data, 1);
1415 tty_lock(tp);
1416 goto out;
1417
1418 case TIOCPTYGRANT: /* grantpt(3) */
1419 /*
1420 * Change the uid of the slave to that of the calling
1421 * thread, change the gid of the slave to GID_TTY,
1422 * change the mode to 0620 (rw--w----).
1423 */
1424 {
1425 error = _devfs_setattr(pti->pt_devhandle, 0620, kauth_getuid(), GID_TTY);
1426#if CONFIG_MACF
1427 if (!error) {
1428 tty_unlock(tp);
1429 mac_pty_notify_grant(p, tp, dev, NULL);
1430 tty_lock(tp);
1431 }
1432#endif
1433 goto out;
1434 }
1435
1436 case TIOCPTYGNAME: /* ptsname(3) */
1437 /*
1438 * Report the name of the slave device in *data
1439 * (128 bytes max.). Use the same template string
1440 * used for calling devfs_make_node() to create it.
1441 */
1442 snprintf(data, 128, "/dev/" PTSD_TEMPLATE, minor(dev));
1443 error = 0;
1444 goto out;
1445
1446 case TIOCPTYUNLK: /* unlockpt(3) */
1447 /*
1448 * Unlock the slave device so that it can be opened.
1449 */
1450 pti->pt_flags |= PF_UNLOCKED;
1451 error = 0;
1452 goto out;
1453 }
1454
1455 /*
1456 * Fail all other calls; pty masters are not serial devices;
1457 * we only pretend they are when the slave side of the pty is
1458 * already open.
1459 */
1460 if (!allow_ext_ioctl) {
1461 error = ENOTTY;
1462 goto out;
1463 }
1464 }
1465 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1466 if (error == ENOTTY) {
1467 error = ttioctl_locked(tp, cmd, data, flag, p);
1468 if (error == ENOTTY) {
1469 if (pti->pt_flags & PF_UCNTL && (cmd & ~0xff) == UIOCCMD(0)) {
1470 /* Process the UIOCMD ioctl group */
1471 if (cmd & 0xff) {
1472 pti->pt_ucntl = (u_char)cmd;
1473 ptmx_wakeup(tp, FREAD);
1474 }
1475 error = 0;
1476 goto out;
1477 } else if (cmd == TIOCSBRK || cmd == TIOCCBRK) {
1478 /*
1479 * POSIX conformance; rdar://3936338
1480 *
1481 * Clear ENOTTY in the case of setting or
1482 * clearing a break failing because pty's
1483 * don't support break like real serial
1484 * ports.
1485 */
1486 error = 0;
1487 goto out;
1488 }
1489 }
1490 }
1491
1492 /*
1493 * If external processing and packet mode send ioctl packet.
1494 */
1495 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
1496 switch(cmd) {
1497 case TIOCSETA_32:
1498 case TIOCSETAW_32:
1499 case TIOCSETAF_32:
1500 case TIOCSETA_64:
1501 case TIOCSETAW_64:
1502 case TIOCSETAF_64:
1503 case TIOCSETP:
1504 case TIOCSETN:
1505 case TIOCSETC:
1506 case TIOCSLTC:
1507 case TIOCLBIS:
1508 case TIOCLBIC:
1509 case TIOCLSET:
1510 pti->pt_send |= TIOCPKT_IOCTL;
1511 ptmx_wakeup(tp, FREAD);
1512 default:
1513 break;
1514 }
1515 }
1516 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
1517 && CCEQ(cc[VSTART], CTRL('q'));
1518 if (pti->pt_flags & PF_NOSTOP) {
1519 if (stop) {
1520 pti->pt_send &= ~TIOCPKT_NOSTOP;
1521 pti->pt_send |= TIOCPKT_DOSTOP;
1522 pti->pt_flags &= ~PF_NOSTOP;
1523 ptmx_wakeup(tp, FREAD);
1524 }
1525 } else {
1526 if (!stop) {
1527 pti->pt_send &= ~TIOCPKT_DOSTOP;
1528 pti->pt_send |= TIOCPKT_NOSTOP;
1529 pti->pt_flags |= PF_NOSTOP;
1530 ptmx_wakeup(tp, FREAD);
1531 }
1532 }
1533out:
1534 tty_unlock(tp);
1535 return (error);
1536}
1537
1538/*
1539 * kqueue support.
1540 */
1541int ptsd_kqfilter(dev_t, struct knote *);
1542static void ptsd_kqops_detach(struct knote *);
1543static int ptsd_kqops_event(struct knote *, long);
1544
1545static struct filterops ptsd_kqops = {
1546 .f_isfd = 1,
1547 .f_detach = ptsd_kqops_detach,
1548 .f_event = ptsd_kqops_event,
1549};
1550
1551#define PTSD_KNOTE_VALID NULL
1552#define PTSD_KNOTE_REVOKED ((void *)-911l)
1553
1554/*
1555 * In the normal case, by the time the driver_close() routine is called
1556 * on the slave, all knotes have been detached. However in the revoke(2)
1557 * case, the driver's close routine is called while there are knotes active
1558 * that reference the handlers below. And we have no obvious means to
1559 * reach from the driver out to the kqueue's that reference them to get
1560 * them to stop.
1561 */
1562
1563static void
1564ptsd_kqops_detach(struct knote *kn)
1565{
1566 struct ptmx_ioctl *pti;
1567 struct tty *tp;
1568 dev_t dev, lockdev = (dev_t)kn->kn_hookid;
1569
1570 ptsd_kevent_mtx_lock(minor(lockdev));
1571
1572 if ((dev = (dev_t)kn->kn_hookid) != 0) {
1573 pti = ptmx_get_ioctl(minor(dev), 0);
1574 if (pti != NULL && (tp = pti->pt_tty) != NULL) {
1575 tty_lock(tp);
1576 if (kn->kn_filter == EVFILT_READ)
1577 KNOTE_DETACH(&tp->t_rsel.si_note, kn);
1578 else
1579 KNOTE_DETACH(&tp->t_wsel.si_note, kn);
1580 tty_unlock(tp);
1581 kn->kn_hookid = 0;
1582 }
1583 }
1584
1585 ptsd_kevent_mtx_unlock(minor(lockdev));
1586}
1587
1588static int
1589ptsd_kqops_event(struct knote *kn, long hint)
1590{
1591 struct ptmx_ioctl *pti;
1592 struct tty *tp;
1593 dev_t dev = (dev_t)kn->kn_hookid;
1594 int retval = 0;
1595
1596 ptsd_kevent_mtx_lock(minor(dev));
1597
1598 do {
1599 if (kn->kn_hook != PTSD_KNOTE_VALID ) {
1600 /* We were revoked */
1601 kn->kn_data = 0;
1602 kn->kn_flags |= EV_EOF;
1603 retval = 1;
1604 break;
1605 }
1606
1607 pti = ptmx_get_ioctl(minor(dev), 0);
1608 if (pti == NULL || (tp = pti->pt_tty) == NULL) {
1609 kn->kn_data = ENXIO;
1610 kn->kn_flags |= EV_ERROR;
1611 retval = 1;
1612 break;
1613 }
1614
1615 if (hint == 0)
1616 tty_lock(tp);
1617
1618 if (kn->kn_filter == EVFILT_READ) {
1619 kn->kn_data = ttnread(tp);
1620 if (kn->kn_data > 0)
1621 retval = 1;
1622 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1623 kn->kn_flags |= EV_EOF;
1624 retval = 1;
1625 }
1626 } else { /* EVFILT_WRITE */
1627 if ((tp->t_outq.c_cc <= tp->t_lowat) &&
1628 ISSET(tp->t_state, TS_CONNECTED)) {
1629 kn->kn_data = tp->t_outq.c_cn - tp->t_outq.c_cc;
1630 retval = 1;
1631 }
1632 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1633 kn->kn_flags |= EV_EOF;
1634 retval = 1;
1635 }
1636 }
1637
1638 if (hint == 0)
1639 tty_unlock(tp);
1640 } while (0);
1641
1642 ptsd_kevent_mtx_unlock(minor(dev));
1643
1644 return (retval);
1645}
1646int
1647ptsd_kqfilter(dev_t dev, struct knote *kn)
1648{
1649 struct tty *tp = NULL;
1650 struct ptmx_ioctl *pti = NULL;
1651 int retval = 0;
1652
1653 /* make sure we're talking about the right device type */
1654 if (cdevsw[major(dev)].d_open != ptsd_open) {
1655 return (EINVAL);
1656 }
1657
1658 if ((pti = ptmx_get_ioctl(minor(dev), 0)) == NULL) {
1659 return (ENXIO);
1660 }
1661
1662 tp = pti->pt_tty;
1663 tty_lock(tp);
1664
1665 kn->kn_hookid = dev;
1666 kn->kn_hook = PTSD_KNOTE_VALID;
1667 kn->kn_fop = &ptsd_kqops;
1668
1669 switch (kn->kn_filter) {
1670 case EVFILT_READ:
1671 KNOTE_ATTACH(&tp->t_rsel.si_note, kn);
1672 break;
1673 case EVFILT_WRITE:
1674 KNOTE_ATTACH(&tp->t_wsel.si_note, kn);
1675 break;
1676 default:
1677 retval = EINVAL;
1678 break;
1679 }
1680
1681 tty_unlock(tp);
1682 return (retval);
1683}
1684
1685/*
1686 * Support for revoke(2).
1687 *
1688 * Mark all the kn_hook fields so that future invocations of the
1689 * f_event op will just say "EOF" *without* looking at the
1690 * ptmx_ioctl structure (which may disappear or be recycled at
1691 * the end of ptsd_close). Issue wakeups to post that EOF to
1692 * anyone listening. And finally remove the knotes from the
1693 * tty's klists to keep ttyclose() happy, and set the hookid to
1694 * zero to make the final detach passively successful.
1695 */
1696static void
1697ptsd_revoke_knotes(dev_t dev, struct tty *tp)
1698{
1699 struct klist *list;
1700 struct knote *kn, *tkn;
1701
1702 /* (Hold and drop the right locks in the right order.) */
1703
1704 ptsd_kevent_mtx_lock(minor(dev));
1705 tty_lock(tp);
1706
1707 list = &tp->t_rsel.si_note;
1708 SLIST_FOREACH(kn, list, kn_selnext)
1709 kn->kn_hook = PTSD_KNOTE_REVOKED;
1710
1711 list = &tp->t_wsel.si_note;
1712 SLIST_FOREACH(kn, list, kn_selnext)
1713 kn->kn_hook = PTSD_KNOTE_REVOKED;
1714
1715 tty_unlock(tp);
1716 ptsd_kevent_mtx_unlock(minor(dev));
1717
1718 tty_lock(tp);
1719 ttwakeup(tp);
1720 ttwwakeup(tp);
1721 tty_unlock(tp);
1722
1723 ptsd_kevent_mtx_lock(minor(dev));
1724 tty_lock(tp);
1725
1726 list = &tp->t_rsel.si_note;
1727 SLIST_FOREACH_SAFE(kn, list, kn_selnext, tkn) {
1728 (void) KNOTE_DETACH(list, kn);
1729 kn->kn_hookid = 0;
1730 }
1731
1732 list = &tp->t_wsel.si_note;
1733 SLIST_FOREACH_SAFE(kn, list, kn_selnext, tkn) {
1734 (void) KNOTE_DETACH(list, kn);
1735 kn->kn_hookid = 0;
1736 }
1737
1738 tty_unlock(tp);
1739 ptsd_kevent_mtx_unlock(minor(dev));
1740}