]> git.saurik.com Git - apple/launchd.git/blame - launchd/src/bootstrap_public.c
launchd-152.tar.gz
[apple/launchd.git] / launchd / src / bootstrap_public.c
CommitLineData
ed34e3c3
A
1/*
2 * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21#include <mach/mach.h>
22#include <mach/vm_map.h>
23
24#include "bootstrap_public.h"
25#include "bootstrap_private.h"
26#include "launch.h"
27#include "launch_priv.h"
28
29#define mig_external static
30#include "bootstrap.h"
31#include "bootstrapUser.c"
32
33#include <sys/param.h>
34#include <stdlib.h>
35#include <errno.h>
36
37kern_return_t
38_launchd_to_launchd(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright,
39 name_array_t *service_names, mach_msg_type_number_t *service_namesCnt,
40 mach_port_array_t *ports, mach_msg_type_number_t *portCnt)
41{
42 return raw_bootstrap_transfer_subset(bp, reqport, rcvright, service_names, service_namesCnt, ports, portCnt);
43}
44
45pid_t
46_spawn_via_launchd(const char *label, const char *const *argv, const struct spawn_via_launchd_attr *spawn_attrs, int struct_version)
47{
48 kern_return_t kr;
49 const char *const *tmpp;
50 size_t len, buf_len = strlen(label) + 1;
51 char *buf = strdup(label);
52 uint64_t flags = 0;
53 uint32_t argc = 0;
54 uint32_t envc = 0;
55 pid_t p = -1;
56 mode_t u_mask = CMASK;
57 mach_port_t obsvr_port = MACH_PORT_NULL;
58
59 for (tmpp = argv; *tmpp; tmpp++) {
60 argc++;
61 len = strlen(*tmpp) + 1;
62 buf = reallocf(buf, buf_len + len);
63 strcpy(buf + buf_len, *tmpp);
64 buf_len += len;
65 }
66
67 if (spawn_attrs) switch (struct_version) {
68 case 0:
69 if (spawn_attrs->spawn_flags & SPAWN_VIA_LAUNCHD_STOPPED) {
70 flags |= SPAWN_WANTS_WAIT4DEBUGGER;
71 }
72 if (spawn_attrs->spawn_flags & SPAWN_VIA_LAUNCHD_FORCE_PPC) {
73 flags |= SPAWN_WANTS_FORCE_PPC;
74 }
75
76 if (spawn_attrs->spawn_env) {
77 for (tmpp = spawn_attrs->spawn_env; *tmpp; tmpp++) {
78 envc++;
79 len = strlen(*tmpp) + 1;
80 buf = reallocf(buf, buf_len + len);
81 strcpy(buf + buf_len, *tmpp);
82 buf_len += len;
83 }
84 }
85
86 if (spawn_attrs->spawn_path) {
87 flags |= SPAWN_HAS_PATH;
88 len = strlen(spawn_attrs->spawn_path) + 1;
89 buf = reallocf(buf, buf_len + len);
90 strcpy(buf + buf_len, spawn_attrs->spawn_path);
91 buf_len += len;
92 }
93
94 if (spawn_attrs->spawn_chdir) {
95 flags |= SPAWN_HAS_WDIR;
96 len = strlen(spawn_attrs->spawn_chdir) + 1;
97 buf = reallocf(buf, buf_len + len);
98 strcpy(buf + buf_len, spawn_attrs->spawn_chdir);
99 buf_len += len;
100 }
101
102 if (spawn_attrs->spawn_umask) {
103 flags |= SPAWN_HAS_UMASK;
104 u_mask = *spawn_attrs->spawn_umask;
105 }
106
107 break;
108 default:
109 break;
110 }
111
112 kr = raw_mpm_spawn(bootstrap_port, buf, buf_len, argc, envc, flags, u_mask, &p, &obsvr_port);
113
114 free(buf);
115
116 if (kr == BOOTSTRAP_SUCCESS) {
117 if (spawn_attrs && spawn_attrs->spawn_observer_port) {
118 *spawn_attrs->spawn_observer_port = obsvr_port;
119 } else {
120 mach_port_deallocate(mach_task_self(), obsvr_port);
121 }
122 return p;
123 }
124
125 switch (kr) {
126 case BOOTSTRAP_NOT_PRIVILEGED:
127 errno = EPERM; break;
128 case BOOTSTRAP_NO_MEMORY:
129 errno = ENOMEM; break;
130 default:
131 errno = EINVAL; break;
132 }
133 return -1;
134}
135
136kern_return_t
137mpm_wait(mach_port_t ajob, int *wstatus)
138{
139 return raw_mpm_wait(ajob, wstatus);
140}
141
142kern_return_t
143mpm_uncork_fork(mach_port_t ajob)
144{
145 return raw_mpm_uncork_fork(ajob);
146}
147
148kern_return_t
149bootstrap_create_server(mach_port_t bp, cmd_t server_cmd, uid_t server_uid, boolean_t on_demand, mach_port_t *server_port)
150{
151 return raw_bootstrap_create_server(bp, server_cmd, server_uid, on_demand, server_port);
152}
153
154kern_return_t
155bootstrap_subset(mach_port_t bp, mach_port_t requestor_port, mach_port_t *subset_port)
156{
157 return raw_bootstrap_subset(bp, requestor_port, subset_port);
158}
159
160kern_return_t
161bootstrap_unprivileged(mach_port_t bp, mach_port_t *unpriv_port)
162{
163 return raw_bootstrap_unprivileged(bp, unpriv_port);
164}
165
166kern_return_t
167bootstrap_getsocket(mach_port_t bp, name_t sockpath)
168{
169 return raw_bootstrap_getsocket(bp, sockpath);
170}
171
172kern_return_t
173bootstrap_parent(mach_port_t bp, mach_port_t *parent_port)
174{
175 return raw_bootstrap_parent(bp, parent_port);
176}
177
178kern_return_t
179bootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp)
180{
181 return raw_bootstrap_register(bp, service_name, sp);
182}
183
184kern_return_t
185bootstrap_create_service(mach_port_t bp, name_t service_name, mach_port_t *sp)
186{
187 return raw_bootstrap_create_service(bp, service_name, sp);
188}
189
190kern_return_t
191bootstrap_check_in(mach_port_t bp, name_t service_name, mach_port_t *sp)
192{
193 return raw_bootstrap_check_in(bp, service_name, sp);
194}
195
196kern_return_t
197bootstrap_look_up(mach_port_t bp, name_t service_name, mach_port_t *sp)
198{
199 return raw_bootstrap_look_up(bp, service_name, sp);
200}
201
202kern_return_t
203bootstrap_look_up_array(mach_port_t bp,
204 name_array_t names, mach_msg_type_number_t name_cnt,
205 mach_port_array_t *ports, mach_msg_type_number_t *port_cnt,
206 boolean_t *all)
207{
208 unsigned int i;
209 kern_return_t r;
210
211 if (name_cnt > BOOTSTRAP_MAX_LOOKUP_COUNT)
212 return BOOTSTRAP_BAD_COUNT;
213
214 *port_cnt = name_cnt;
215
216 r = vm_allocate(mach_task_self(), (vm_address_t *)&ports, name_cnt * sizeof(mach_port_t), true);
217
218 if (r != KERN_SUCCESS)
219 return r;
220
221 *all = true;
222
223 for (i = 0; i < name_cnt; i++) {
224 if (bootstrap_look_up(bp, names[i], &((*ports)[i])) == BOOTSTRAP_SUCCESS)
225 continue;
226 *all = false;
227 ports[i] = MACH_PORT_NULL;
228 }
229
230 return BOOTSTRAP_SUCCESS;
231}
232
233kern_return_t
234bootstrap_status(mach_port_t bp, name_t service_name, bootstrap_status_t *service_active)
235{
236 mach_port_t p;
237
238 if (bootstrap_check_in(bp, service_name, &p) == BOOTSTRAP_SUCCESS) {
239 mach_port_mod_refs(mach_task_self(), p, MACH_PORT_RIGHT_RECEIVE, -1);
240 *service_active = BOOTSTRAP_STATUS_ON_DEMAND;
241 if (raw_bootstrap_unprivileged(bp, &p) == BOOTSTRAP_SUCCESS) {
242 if (bp == p)
243 *service_active = BOOTSTRAP_STATUS_INACTIVE;
244 mach_port_deallocate(mach_task_self(), p);
245 }
246 return BOOTSTRAP_SUCCESS;
247 } else if (bootstrap_look_up(bp, service_name, &p) == BOOTSTRAP_SUCCESS) {
248 mach_port_deallocate(mach_task_self(), p);
249 *service_active = BOOTSTRAP_STATUS_ACTIVE;
250 return BOOTSTRAP_SUCCESS;
251 }
252
253 return BOOTSTRAP_UNKNOWN_SERVICE;
254}
255
256kern_return_t
257bootstrap_info(mach_port_t bp,
258 name_array_t *service_names, mach_msg_type_number_t *service_namesCnt,
259 bootstrap_status_array_t *service_active, mach_msg_type_number_t *service_activeCnt)
260{
261 return raw_bootstrap_info(bp, service_names, service_namesCnt,
262 service_active, service_activeCnt);
263}
264
265const char *
266bootstrap_strerror(kern_return_t r)
267{
268 switch (r) {
269 case BOOTSTRAP_SUCCESS:
270 return "Success";
271 case BOOTSTRAP_NOT_PRIVILEGED:
272 return "Permission denied";
273 case BOOTSTRAP_NAME_IN_USE:
274 case BOOTSTRAP_SERVICE_ACTIVE:
275 return "Service name already exists";
276 case BOOTSTRAP_UNKNOWN_SERVICE:
277 return "Unknown service name";
278 case BOOTSTRAP_BAD_COUNT:
279 return "Too many lookups were requested in one request";
280 case BOOTSTRAP_NO_MEMORY:
281 return "Out of memory";
282 default:
283 return mach_error_string(r);
284 }
285}