1 /* 2 * Copyright (c) 2009 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "hi_locl.h" 37 #ifdef HAVE_GCD 38 #include <dispatch/dispatch.h> 39 #else 40 #include "heim_threads.h" 41 #endif 42 43 struct heim_icred { 44 uid_t uid; 45 gid_t gid; 46 pid_t pid; 47 pid_t session; 48 }; 49 50 void 51 heim_ipc_free_cred(heim_icred cred) 52 { 53 free(cred); 54 } 55 56 uid_t 57 heim_ipc_cred_get_uid(heim_icred cred) 58 { 59 return cred->uid; 60 } 61 62 gid_t 63 heim_ipc_cred_get_gid(heim_icred cred) 64 { 65 return cred->gid; 66 } 67 68 pid_t 69 heim_ipc_cred_get_pid(heim_icred cred) 70 { 71 return cred->pid; 72 } 73 74 pid_t 75 heim_ipc_cred_get_session(heim_icred cred) 76 { 77 return cred->session; 78 } 79 80 81 int 82 _heim_ipc_create_cred(uid_t uid, gid_t gid, pid_t pid, pid_t session, heim_icred *cred) 83 { 84 *cred = calloc(1, sizeof(**cred)); 85 if (*cred == NULL) 86 return ENOMEM; 87 (*cred)->uid = uid; 88 (*cred)->gid = gid; 89 (*cred)->pid = pid; 90 (*cred)->session = session; 91 return 0; 92 } 93 94 #ifndef HAVE_GCD 95 struct heim_isemaphore { 96 HEIMDAL_MUTEX mutex; 97 pthread_cond_t cond; 98 long counter; 99 }; 100 #endif 101 102 heim_isemaphore 103 heim_ipc_semaphore_create(long value) 104 { 105 #ifdef HAVE_GCD 106 return (heim_isemaphore)dispatch_semaphore_create(value); 107 #elif !defined(ENABLE_PTHREAD_SUPPORT) 108 heim_assert(0, "no semaphore support w/o pthreads"); 109 return NULL; 110 #else 111 heim_isemaphore s = malloc(sizeof(*s)); 112 if (s == NULL) 113 return NULL; 114 HEIMDAL_MUTEX_init(&s->mutex); 115 pthread_cond_init(&s->cond, NULL); 116 s->counter = value; 117 return s; 118 #endif 119 } 120 121 long 122 heim_ipc_semaphore_wait(heim_isemaphore s, time_t t) 123 { 124 #ifdef HAVE_GCD 125 uint64_t timeout; 126 if (t == HEIM_IPC_WAIT_FOREVER) 127 timeout = DISPATCH_TIME_FOREVER; 128 else 129 timeout = (uint64_t)t * NSEC_PER_SEC; 130 131 return dispatch_semaphore_wait((dispatch_semaphore_t)s, timeout); 132 #elif !defined(ENABLE_PTHREAD_SUPPORT) 133 heim_assert(0, "no semaphore support w/o pthreads"); 134 return 0; 135 #else 136 HEIMDAL_MUTEX_lock(&s->mutex); 137 /* if counter hits below zero, we get to wait */ 138 if (--s->counter < 0) { 139 int ret; 140 141 if (t == HEIM_IPC_WAIT_FOREVER) 142 ret = pthread_cond_wait(&s->cond, &s->mutex); 143 else { 144 struct timespec ts; 145 ts.tv_sec = t; 146 ts.tv_nsec = 0; 147 ret = pthread_cond_timedwait(&s->cond, &s->mutex, &ts); 148 } 149 if (ret) { 150 HEIMDAL_MUTEX_unlock(&s->mutex); 151 return errno; 152 } 153 } 154 HEIMDAL_MUTEX_unlock(&s->mutex); 155 156 return 0; 157 #endif 158 } 159 160 long 161 heim_ipc_semaphore_signal(heim_isemaphore s) 162 { 163 #ifdef HAVE_GCD 164 return dispatch_semaphore_signal((dispatch_semaphore_t)s); 165 #elif !defined(ENABLE_PTHREAD_SUPPORT) 166 heim_assert(0, "no semaphore support w/o pthreads"); 167 return EINVAL; 168 #else 169 int wakeup; 170 HEIMDAL_MUTEX_lock(&s->mutex); 171 wakeup = (++s->counter == 0) ; 172 HEIMDAL_MUTEX_unlock(&s->mutex); 173 if (wakeup) 174 pthread_cond_signal(&s->cond); 175 return 0; 176 #endif 177 } 178 179 void 180 heim_ipc_semaphore_release(heim_isemaphore s) 181 { 182 #ifdef HAVE_GCD 183 dispatch_release((dispatch_semaphore_t)s); 184 #elif !defined(ENABLE_PTHREAD_SUPPORT) 185 heim_assert(0, "no semaphore support w/o pthreads"); 186 #else 187 HEIMDAL_MUTEX_lock(&s->mutex); 188 if (s->counter != 0) 189 abort(); 190 HEIMDAL_MUTEX_unlock(&s->mutex); 191 HEIMDAL_MUTEX_destroy(&s->mutex); 192 pthread_cond_destroy(&s->cond); 193 free(s); 194 #endif 195 } 196 197 void 198 heim_ipc_free_data(heim_idata *data) 199 { 200 if (data->data) 201 free(data->data); 202 data->data = NULL; 203 data->length = 0; 204 } 205