2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * bootstrap -- fundamental service initiator and port server
26 * Mike DeMoney, NeXT, Inc.
27 * Copyright, 1990. All rights reserved.
29 * lists.c -- implementation of list handling routines
32 #import <mach/boolean.h>
33 #import <mach/mach_error.h>
38 #import "bootstrap_internal.h"
45 bootstrap_info_t bootstraps
; /* head of list of all bootstrap ports */
46 server_t servers
; /* head of list of all servers */
47 service_t services
; /* head of list of all services */
48 unsigned nservices
; /* number of services in list */
57 #define NEW(type, num) ((type *)ckmalloc(sizeof(type) * num))
58 #define STREQ(a, b) (strcmp(a, b) == 0)
59 #define NELEM(x) (sizeof(x)/sizeof((x)[0]))
60 #define LAST_ELEMENT(x) ((x)[NELEM(x)-1])
65 bootstraps
.next
= bootstraps
.prev
= &bootstraps
;
66 servers
.next
= servers
.prev
= &servers
;
67 services
.next
= services
.prev
= &services
;
73 servertype_t servertype
,
79 debug("adding new server \"%s\" with priority %d\n", cmd
, priority
);
80 serverp
= NEW(server_t
, 1);
81 if (serverp
!= NULL
) {
82 /* Doubly linked list */
83 servers
.prev
->next
= serverp
;
84 serverp
->prev
= servers
.prev
;
85 serverp
->next
= &servers
;
86 servers
.prev
= serverp
;
88 serverp
->port
= MACH_PORT_NULL
;
89 serverp
->servertype
= servertype
;
90 serverp
->priority
= priority
;
91 strncpy(serverp
->cmd
, cmd
, sizeof serverp
->cmd
);
92 LAST_ELEMENT(serverp
->cmd
) = '\0';
99 bootstrap_info_t
*bootstrap
,
101 mach_port_t service_port
,
103 servicetype_t servicetype
,
106 extern mach_port_t notify_port
;
109 kern_return_t result
;
111 servicep
= NEW(service_t
, 1);
112 if (servicep
!= NULL
) {
113 /* Doubly linked list */
114 services
.prev
->next
= servicep
;
115 servicep
->prev
= services
.prev
;
116 servicep
->next
= &services
;
117 services
.prev
= servicep
;
121 strncpy(servicep
->name
, name
, sizeof servicep
->name
);
122 LAST_ELEMENT(servicep
->name
) = '\0';
123 servicep
->bootstrap
= bootstrap
;
124 servicep
->server
= serverp
;
125 servicep
->port
= service_port
;
126 result
= mach_port_request_notification(mach_task_self(),
128 MACH_NOTIFY_DEAD_NAME
,
131 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
133 if (result
== KERN_SUCCESS
) {
134 debug("added notification for %s\n", servicep
->name
);
136 error("couldn't add notification for %s: %s\n", servicep
->name
, mach_error_string(result
));
138 servicep
->isActive
= isActive
;
139 servicep
->servicetype
= servicetype
;
146 bootstrap_info_t
*parent
,
147 mach_port_t bootstrap_port
,
148 mach_port_t requestor_port
)
150 extern mach_port_t notify_port
;
151 bootstrap_info_t
*bootstrap
;
153 kern_return_t result
;
155 bootstrap
= NEW(bootstrap_info_t
, 1);
156 if (bootstrap
!= NULL
) {
157 /* Doubly linked list */
158 bootstraps
.prev
->next
= bootstrap
;
159 bootstrap
->prev
= bootstraps
.prev
;
160 bootstrap
->next
= &bootstraps
;
161 bootstraps
.prev
= bootstrap
;
163 bootstrap
->bootstrap_port
= bootstrap_port
;
164 bootstrap
->requestor_port
= requestor_port
;
165 bootstrap
->parent
= parent
;
166 result
= mach_port_request_notification(mach_task_self(),
168 MACH_NOTIFY_DEAD_NAME
,
171 MACH_MSG_TYPE_MAKE_SEND_ONCE
, &pport
);
172 if (result
== KERN_SUCCESS
) {
173 info("added notification for sub-bootstrap");
175 error("couldn't add notification for sub-bootstrap: %s\n", mach_error_string(result
));
183 lookup_bootstrap_by_port(mach_port_t port
)
185 bootstrap_info_t
*bootstrap
;
187 for ( bootstrap
= FIRST(bootstraps
)
188 ; !IS_END(bootstrap
, bootstraps
)
189 ; bootstrap
= NEXT(bootstrap
))
191 if (bootstrap
->bootstrap_port
== port
)
199 lookup_bootstrap_req_by_port(mach_port_t port
)
201 bootstrap_info_t
*bootstrap
;
203 for ( bootstrap
= FIRST(bootstraps
)
204 ; !IS_END(bootstrap
, bootstraps
)
205 ; bootstrap
= NEXT(bootstrap
))
207 if (bootstrap
->requestor_port
== port
)
215 lookup_service_by_name(bootstrap_info_t
*bootstrap
, name_t name
)
220 for ( servicep
= FIRST(services
)
221 ; !IS_END(servicep
, services
)
222 ; servicep
= NEXT(servicep
))
224 if (!STREQ(name
, servicep
->name
))
226 if (bootstrap
&& servicep
->bootstrap
!= bootstrap
)
230 bootstrap
= bootstrap
->parent
;
237 unlink_service(service_t
*servicep
)
239 ASSERT(servicep
->prev
->next
== servicep
);
240 ASSERT(servicep
->next
->prev
== servicep
);
241 servicep
->prev
->next
= servicep
->next
;
242 servicep
->next
->prev
= servicep
->prev
;
243 servicep
->prev
= servicep
->next
= servicep
; // idempotent
247 delete_service(service_t
*servicep
)
249 unlink_service(servicep
);
255 destroy_services(bootstrap_info_t
*bootstrap
)
260 for ( servicep
= FIRST(services
)
261 ; !IS_END(servicep
, services
)
264 next
= NEXT(servicep
);
265 if (bootstrap
!= servicep
->bootstrap
)
267 unlink_service(servicep
);
268 switch (servicep
->servicetype
) {
270 log("Service %s deleted - bootstrap deleted", servicep
->name
);
271 msg_destroy_port(servicep
->port
);
272 delete_service(servicep
);
274 case DECLARED
: // don't alter status of (now unavailable) server
275 error("Declared service %s now unavailable", servicep
->name
);
276 delete_service(servicep
);
279 error("Self service %s now unavailable", servicep
->name
);
282 error("unknown service type %d\n", servicep
->servicetype
);
289 lookup_service_by_port(mach_port_t port
)
293 for ( servicep
= FIRST(services
)
294 ; !IS_END(servicep
, services
)
295 ; servicep
= NEXT(servicep
))
297 if (port
== servicep
->port
)
304 lookup_server_by_task_port(mach_port_t port
)
308 for ( serverp
= FIRST(servers
)
309 ; !IS_END(serverp
, servers
)
310 ; serverp
= NEXT(serverp
))
312 if (port
== serverp
->task_port
)
319 delete_bootstrap(bootstrap_info_t
*bootstrap
)
321 bootstrap_info_t
*child_bootstrap
;
323 ASSERT(bootstrap
->prev
->next
== bootstrap
);
324 ASSERT(bootstrap
->next
->prev
== bootstrap
);
326 destroy_services(bootstrap
);
327 for ( child_bootstrap
= FIRST(bootstraps
)
328 ; !IS_END(child_bootstrap
, bootstraps
)
329 ; child_bootstrap
= NEXT(child_bootstrap
))
331 if (child_bootstrap
->parent
== bootstrap
)
332 delete_bootstrap(child_bootstrap
);
335 debug("deleting bootstrap %d, requestor %d",
336 bootstrap
->bootstrap_port
,
337 bootstrap
->requestor_port
);
338 bootstrap
->prev
->next
= bootstrap
->next
;
339 bootstrap
->next
->prev
= bootstrap
->prev
;
340 mach_port_destroy(mach_task_self(), bootstrap
->bootstrap_port
);
341 mach_port_deallocate(mach_task_self(), bootstrap
->requestor_port
);
346 lookup_server_by_port(mach_port_t port
)
350 for ( serverp
= FIRST(servers
)
351 ; !IS_END(serverp
, servers
)
352 ; serverp
= NEXT(serverp
))
354 if (port
== serverp
->port
)
361 find_init_server(void)
365 for ( serverp
= FIRST(servers
)
366 ; !IS_END(serverp
, servers
)
367 ; serverp
= NEXT(serverp
))
369 if (serverp
->servertype
== ETCINIT
)
376 ckmalloc(unsigned nbytes
)
380 if ((cp
= malloc(nbytes
)) == NULL
)
381 fatal("Out of memory");