1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  25 /*        All Rights Reserved   */
  26 
  27 
  28 #ifndef _SYS_PTMS_H
  29 #define _SYS_PTMS_H
  30 
  31 #pragma ident   "%Z%%M% %I%     %E% SMI"
  32 
  33 #ifdef  __cplusplus
  34 extern "C" {
  35 #endif
  36 
  37 #ifdef _KERNEL
  38 
  39 /*
  40  * Structures and definitions supporting the pseudo terminal
  41  * drivers. This structure is private and should not be used by any
  42  * applications.
  43  */
  44 struct pt_ttys {
  45         queue_t *ptm_rdq;       /* master's read queue pointer */
  46         queue_t *pts_rdq;       /* slave's read queue pointer */
  47         mblk_t  *pt_nullmsg;    /* 0-bytes message block for pts close */
  48         pid_t    pt_pid;        /* process id (for debugging) */
  49         minor_t  pt_minor;      /* Minor number of this pty */
  50         int      pt_refcnt;     /* reference count for ptm_rdq/pts_rdq uses */
  51         ushort_t pt_state;      /* state of master/slave pair */
  52         kcondvar_t pt_cv;       /* condition variable for exclusive access */
  53         kmutex_t pt_lock;       /* Per-element lock */
  54         zoneid_t pt_zoneid;     /* Zone membership for this pty */
  55         uid_t    pt_ruid;       /* Real owner of pty */
  56         gid_t    pt_rgid;       /* Real group owner of pty */
  57 };
  58 
  59 /*
  60  * pt_state values
  61  */
  62 #define PTLOCK          0x01    /* master/slave pair is locked */
  63 #define PTMOPEN         0x02    /* master side is open */
  64 #define PTSOPEN         0x04    /* slave side is open */
  65 #define PTSTTY          0x08    /* slave side is tty */
  66 
  67 /*
  68  * Multi-threading primitives.
  69  * Values of pt_refcnt: -1 if a writer is accessing the struct
  70  *                      0  if no one is reading or writing
  71  *                      > 0 equals to the number of readers accessing the struct
  72  */
  73 #define PT_ENTER_READ(p) {                      \
  74         mutex_enter(&(p)->pt_lock);              \
  75         while ((p)->pt_refcnt < 0)                \
  76                 cv_wait(&((p)->pt_cv), &(p)->pt_lock);    \
  77         (p)->pt_refcnt++;                    \
  78         mutex_exit(&(p)->pt_lock);               \
  79 }
  80 
  81 #define PT_ENTER_WRITE(p) {                     \
  82         mutex_enter(&(p)->pt_lock);              \
  83         while ((p)->pt_refcnt != 0)          \
  84                 cv_wait(&((p)->pt_cv), &(p)->pt_lock);    \
  85         (p)->pt_refcnt = -1;                 \
  86         mutex_exit(&(p)->pt_lock);               \
  87 }
  88 
  89 #define PT_EXIT_READ(p) {                       \
  90         mutex_enter(&(p)->pt_lock);              \
  91         ASSERT((p)->pt_refcnt > 0);               \
  92         if ((--((p)->pt_refcnt)) == 0)               \
  93                 cv_broadcast(&(p)->pt_cv);       \
  94         mutex_exit(&(p)->pt_lock);               \
  95 }
  96 
  97 #define PT_EXIT_WRITE(p) {                      \
  98         mutex_enter(&(p)->pt_lock);              \
  99         ASSERT((p)->pt_refcnt == -1);                \
 100         (p)->pt_refcnt = 0;                  \
 101         cv_broadcast(&(p)->pt_cv);               \
 102         mutex_exit(&(p)->pt_lock);               \
 103 }
 104 
 105 /*
 106  * ptms_lock and pt_cnt are defined in ptms_conf.c
 107  */
 108 extern kmutex_t         ptms_lock;
 109 extern dev_info_t       *pts_dip;       /* private copy of devinfo ptr */
 110 
 111 extern void ptms_init(void);
 112 extern struct pt_ttys *pt_ttys_alloc(void);
 113 extern void ptms_close(struct pt_ttys *, uint_t);
 114 extern struct pt_ttys *ptms_minor2ptty(minor_t);
 115 extern int ptms_attach_slave(void);
 116 extern int ptms_minor_valid(minor_t ptmin, uid_t *uid, gid_t *gid);
 117 extern int ptms_minor_exists(minor_t ptmin);
 118 extern void ptms_set_owner(minor_t ptmin, uid_t uid, gid_t gid);
 119 extern major_t ptms_slave_attached(void);
 120 
 121 #ifdef DEBUG
 122 extern void ptms_log(char *, uint_t);
 123 extern void ptms_logp(char *, uintptr_t);
 124 #define DDBG(a, b) ptms_log(a, b)
 125 #define DDBGP(a, b) ptms_logp(a, b)
 126 #else
 127 #define DDBG(a, b)
 128 #define DDBGP(a, b)
 129 #endif
 130 
 131 typedef struct __ptmptsopencb_arg *ptmptsopencb_arg_t;
 132 typedef struct ptmptsopencb {
 133         boolean_t               (*ppocb_func)(ptmptsopencb_arg_t);
 134         ptmptsopencb_arg_t      ppocb_arg;
 135 } ptmptsopencb_t;
 136 
 137 #endif /* _KERNEL */
 138 
 139 typedef struct pt_own {
 140         uid_t   pto_ruid;
 141         gid_t   pto_rgid;
 142 } pt_own_t;
 143 
 144 /*
 145  * ioctl commands
 146  *
 147  *  ISPTM: Determines whether the file descriptor is that of an open master
 148  *         device. Return code of zero indicates that the file descriptor
 149  *         represents master device.
 150  *
 151  * UNLKPT: Unlocks the master and slave devices.  It returns 0 on success. On
 152  *         failure, the errno is set to EINVAL indicating that the master
 153  *         device is not open.
 154  *
 155  *  ZONEPT: Sets the zoneid of the pair of master and slave devices.  It
 156  *          returns 0 upon success.  Used to force a pty 'into' a zone upon
 157  *          zone entry.
 158  *
 159  * PT_OWNER: Sets uid and gid for slave device.  It returns 0 on success.
 160  *
 161  */
 162 #define ISPTM           (('P'<<8)|1)      /* query for master */
 163 #define UNLKPT          (('P'<<8)|2)      /* unlock master/slave pair */
 164 #define PTSSTTY         (('P'<<8)|3)      /* set tty flag */
 165 #define ZONEPT          (('P'<<8)|4)      /* set zone of master/slave pair */
 166 #define OWNERPT         (('P'<<8)|5)      /* set owner/group for slave device */
 167 
 168 #ifdef _KERNEL
 169 /*
 170  * kernel ioctl commands
 171  *
 172  * PTMPTSOPENCB: Returns a callback function pointer and opaque argument.
 173  *            The return value of the callback function when it's invoked
 174  *            with the opaque argument passed to it will indicate if the
 175  *            pts slave device is currently open.
 176  */
 177 #define PTMPTSOPENCB    (('P'<<8)|6)      /* check if the slave is open */
 178 
 179 #endif /* _KERNEL */
 180 
 181 #ifdef  __cplusplus
 182 }
 183 #endif
 184 
 185 #endif  /* _SYS_PTMS_H */