2 * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
21 #include <mach/mach.h>
22 #include <mach/vm_map.h>
24 #include "bootstrap_public.h"
25 #include "bootstrap_private.h"
27 #include "launch_priv.h"
29 #define mig_external static
30 #include "bootstrap.h"
31 #include "bootstrapUser.c"
33 #include <sys/param.h>
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
)
42 return raw_bootstrap_transfer_subset(bp
, reqport
, rcvright
, service_names
, service_namesCnt
, ports
, portCnt
);
46 _spawn_via_launchd(const char *label
, const char *const *argv
, const struct spawn_via_launchd_attr
*spawn_attrs
, int struct_version
)
49 const char *const *tmpp
;
50 size_t len
, buf_len
= strlen(label
) + 1;
51 char *buf
= strdup(label
);
56 mode_t u_mask
= CMASK
;
57 mach_port_t obsvr_port
= MACH_PORT_NULL
;
59 for (tmpp
= argv
; *tmpp
; tmpp
++) {
61 len
= strlen(*tmpp
) + 1;
62 buf
= reallocf(buf
, buf_len
+ len
);
63 strcpy(buf
+ buf_len
, *tmpp
);
67 if (spawn_attrs
) switch (struct_version
) {
69 if (spawn_attrs
->spawn_flags
& SPAWN_VIA_LAUNCHD_STOPPED
) {
70 flags
|= SPAWN_WANTS_WAIT4DEBUGGER
;
72 if (spawn_attrs
->spawn_flags
& SPAWN_VIA_LAUNCHD_FORCE_PPC
) {
73 flags
|= SPAWN_WANTS_FORCE_PPC
;
76 if (spawn_attrs
->spawn_env
) {
77 for (tmpp
= spawn_attrs
->spawn_env
; *tmpp
; tmpp
++) {
79 len
= strlen(*tmpp
) + 1;
80 buf
= reallocf(buf
, buf_len
+ len
);
81 strcpy(buf
+ buf_len
, *tmpp
);
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
);
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
);
102 if (spawn_attrs
->spawn_umask
) {
103 flags
|= SPAWN_HAS_UMASK
;
104 u_mask
= *spawn_attrs
->spawn_umask
;
112 kr
= raw_mpm_spawn(bootstrap_port
, buf
, buf_len
, argc
, envc
, flags
, u_mask
, &p
, &obsvr_port
);
116 if (kr
== BOOTSTRAP_SUCCESS
) {
117 if (spawn_attrs
&& spawn_attrs
->spawn_observer_port
) {
118 *spawn_attrs
->spawn_observer_port
= obsvr_port
;
120 mach_port_deallocate(mach_task_self(), obsvr_port
);
126 case BOOTSTRAP_NOT_PRIVILEGED
:
127 errno
= EPERM
; break;
128 case BOOTSTRAP_NO_MEMORY
:
129 errno
= ENOMEM
; break;
131 errno
= EINVAL
; break;
137 mpm_wait(mach_port_t ajob
, int *wstatus
)
139 return raw_mpm_wait(ajob
, wstatus
);
143 mpm_uncork_fork(mach_port_t ajob
)
145 return raw_mpm_uncork_fork(ajob
);
149 bootstrap_create_server(mach_port_t bp
, cmd_t server_cmd
, uid_t server_uid
, boolean_t on_demand
, mach_port_t
*server_port
)
151 return raw_bootstrap_create_server(bp
, server_cmd
, server_uid
, on_demand
, server_port
);
155 bootstrap_subset(mach_port_t bp
, mach_port_t requestor_port
, mach_port_t
*subset_port
)
157 return raw_bootstrap_subset(bp
, requestor_port
, subset_port
);
161 bootstrap_unprivileged(mach_port_t bp
, mach_port_t
*unpriv_port
)
163 return raw_bootstrap_unprivileged(bp
, unpriv_port
);
167 bootstrap_getsocket(mach_port_t bp
, name_t sockpath
)
169 return raw_bootstrap_getsocket(bp
, sockpath
);
173 bootstrap_parent(mach_port_t bp
, mach_port_t
*parent_port
)
175 return raw_bootstrap_parent(bp
, parent_port
);
179 bootstrap_register(mach_port_t bp
, name_t service_name
, mach_port_t sp
)
181 return raw_bootstrap_register(bp
, service_name
, sp
);
185 bootstrap_create_service(mach_port_t bp
, name_t service_name
, mach_port_t
*sp
)
187 return raw_bootstrap_create_service(bp
, service_name
, sp
);
191 bootstrap_check_in(mach_port_t bp
, name_t service_name
, mach_port_t
*sp
)
193 return raw_bootstrap_check_in(bp
, service_name
, sp
);
197 bootstrap_look_up(mach_port_t bp
, name_t service_name
, mach_port_t
*sp
)
199 return raw_bootstrap_look_up(bp
, service_name
, sp
);
203 bootstrap_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
,
211 if (name_cnt
> BOOTSTRAP_MAX_LOOKUP_COUNT
)
212 return BOOTSTRAP_BAD_COUNT
;
214 *port_cnt
= name_cnt
;
216 r
= vm_allocate(mach_task_self(), (vm_address_t
*)&ports
, name_cnt
* sizeof(mach_port_t
), true);
218 if (r
!= KERN_SUCCESS
)
223 for (i
= 0; i
< name_cnt
; i
++) {
224 if (bootstrap_look_up(bp
, names
[i
], &((*ports
)[i
])) == BOOTSTRAP_SUCCESS
)
227 ports
[i
] = MACH_PORT_NULL
;
230 return BOOTSTRAP_SUCCESS
;
234 bootstrap_status(mach_port_t bp
, name_t service_name
, bootstrap_status_t
*service_active
)
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
) {
243 *service_active
= BOOTSTRAP_STATUS_INACTIVE
;
244 mach_port_deallocate(mach_task_self(), p
);
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
;
253 return BOOTSTRAP_UNKNOWN_SERVICE
;
257 bootstrap_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
)
261 return raw_bootstrap_info(bp
, service_names
, service_namesCnt
,
262 service_active
, service_activeCnt
);
266 bootstrap_strerror(kern_return_t r
)
269 case BOOTSTRAP_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";
283 return mach_error_string(r
);