]> git.saurik.com Git - apple/system_cmds.git/blob - mach_init.tproj/lists.c
system_cmds-175.tar.gz
[apple/system_cmds.git] / mach_init.tproj / lists.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
12 * this file.
13 *
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
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * bootstrap -- fundamental service initiator and port server
26 * Mike DeMoney, NeXT, Inc.
27 * Copyright, 1990. All rights reserved.
28 *
29 * lists.c -- implementation of list handling routines
30 */
31
32 #import <mach/boolean.h>
33 #import <mach/mach_error.h>
34
35 #import <stdlib.h>
36 #import <string.h>
37
38 #import "bootstrap_internal.h"
39 #import "lists.h"
40 #import "error_log.h"
41
42 /*
43 * Exports
44 */
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 */
49
50 #ifndef ASSERT
51 #define ASSERT(p)
52 #endif
53
54 /*
55 * Private macros
56 */
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])
61
62 void
63 init_lists(void)
64 {
65 bootstraps.next = bootstraps.prev = &bootstraps;
66 servers.next = servers.prev = &servers;
67 services.next = services.prev = &services;
68 nservices = 0;
69 }
70
71 server_t *
72 new_server(
73 servertype_t servertype,
74 const char *cmd,
75 int priority)
76 {
77 server_t *serverp;
78
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;
87
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';
93 }
94 return serverp;
95 }
96
97 service_t *
98 new_service(
99 bootstrap_info_t *bootstrap,
100 const char *name,
101 mach_port_t service_port,
102 boolean_t isActive,
103 servicetype_t servicetype,
104 server_t *serverp)
105 {
106 extern mach_port_t notify_port;
107 service_t *servicep;
108 mach_port_t pport;
109 kern_return_t result;
110
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;
118
119 nservices += 1;
120
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(),
127 service_port,
128 MACH_NOTIFY_DEAD_NAME,
129 0,
130 notify_port,
131 MACH_MSG_TYPE_MAKE_SEND_ONCE,
132 &pport);
133 if (result == KERN_SUCCESS) {
134 debug("added notification for %s\n", servicep->name);
135 } else {
136 error("couldn't add notification for %s: %s\n", servicep->name, mach_error_string(result));
137 }
138 servicep->isActive = isActive;
139 servicep->servicetype = servicetype;
140 }
141 return servicep;
142 }
143
144 bootstrap_info_t *
145 new_bootstrap(
146 bootstrap_info_t *parent,
147 mach_port_t bootstrap_port,
148 mach_port_t requestor_port)
149 {
150 extern mach_port_t notify_port;
151 bootstrap_info_t *bootstrap;
152 mach_port_t pport;
153 kern_return_t result;
154
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;
162
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(),
167 requestor_port,
168 MACH_NOTIFY_DEAD_NAME,
169 0,
170 notify_port,
171 MACH_MSG_TYPE_MAKE_SEND_ONCE, &pport);
172 if (result == KERN_SUCCESS) {
173 info("added notification for sub-bootstrap");
174 } else {
175 error("couldn't add notification for sub-bootstrap: %s\n", mach_error_string(result));
176 }
177
178 }
179 return bootstrap;
180 }
181
182 bootstrap_info_t *
183 lookup_bootstrap_by_port(mach_port_t port)
184 {
185 bootstrap_info_t *bootstrap;
186
187 for ( bootstrap = FIRST(bootstraps)
188 ; !IS_END(bootstrap, bootstraps)
189 ; bootstrap = NEXT(bootstrap))
190 {
191 if (bootstrap->bootstrap_port == port)
192 return bootstrap;
193 }
194
195 return &bootstraps;
196 }
197
198 bootstrap_info_t *
199 lookup_bootstrap_req_by_port(mach_port_t port)
200 {
201 bootstrap_info_t *bootstrap;
202
203 for ( bootstrap = FIRST(bootstraps)
204 ; !IS_END(bootstrap, bootstraps)
205 ; bootstrap = NEXT(bootstrap))
206 {
207 if (bootstrap->requestor_port == port)
208 return bootstrap;
209 }
210
211 return NULL;
212 }
213
214 service_t *
215 lookup_service_by_name(bootstrap_info_t *bootstrap, name_t name)
216 {
217 service_t *servicep;
218
219 while (bootstrap) {
220 for ( servicep = FIRST(services)
221 ; !IS_END(servicep, services)
222 ; servicep = NEXT(servicep))
223 {
224 if (!STREQ(name, servicep->name))
225 continue;
226 if (bootstrap && servicep->bootstrap != bootstrap)
227 continue;
228 return servicep;
229 }
230 bootstrap = bootstrap->parent;
231 }
232
233 return NULL;
234 }
235
236 void
237 unlink_service(service_t *servicep)
238 {
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
244 }
245
246 void
247 delete_service(service_t *servicep)
248 {
249 unlink_service(servicep);
250 free(servicep);
251 nservices -= 1;
252 }
253
254 void
255 destroy_services(bootstrap_info_t *bootstrap)
256 {
257 service_t *servicep;
258 service_t *next;
259
260 for ( servicep = FIRST(services)
261 ; !IS_END(servicep, services)
262 ; servicep = next)
263 {
264 next = NEXT(servicep);
265 if (bootstrap != servicep->bootstrap)
266 continue;
267 unlink_service(servicep);
268 switch (servicep->servicetype) {
269 case REGISTERED:
270 log("Service %s deleted - bootstrap deleted", servicep->name);
271 msg_destroy_port(servicep->port);
272 delete_service(servicep);
273 break;
274 case DECLARED: // don't alter status of (now unavailable) server
275 error("Declared service %s now unavailable", servicep->name);
276 delete_service(servicep);
277 break;
278 case SELF:
279 error("Self service %s now unavailable", servicep->name);
280 break;
281 default:
282 error("unknown service type %d\n", servicep->servicetype);
283 break;
284 }
285 }
286 }
287
288 service_t *
289 lookup_service_by_port(mach_port_t port)
290 {
291 service_t *servicep;
292
293 for ( servicep = FIRST(services)
294 ; !IS_END(servicep, services)
295 ; servicep = NEXT(servicep))
296 {
297 if (port == servicep->port)
298 return servicep;
299 }
300 return NULL;
301 }
302
303 server_t *
304 lookup_server_by_task_port(mach_port_t port)
305 {
306 server_t *serverp;
307
308 for ( serverp = FIRST(servers)
309 ; !IS_END(serverp, servers)
310 ; serverp = NEXT(serverp))
311 {
312 if (port == serverp->task_port)
313 return serverp;
314 }
315 return NULL;
316 }
317
318 void
319 delete_bootstrap(bootstrap_info_t *bootstrap)
320 {
321 bootstrap_info_t *child_bootstrap;
322
323 ASSERT(bootstrap->prev->next == bootstrap);
324 ASSERT(bootstrap->next->prev == bootstrap);
325
326 destroy_services(bootstrap);
327 for ( child_bootstrap = FIRST(bootstraps)
328 ; !IS_END(child_bootstrap, bootstraps)
329 ; child_bootstrap = NEXT(child_bootstrap))
330 {
331 if (child_bootstrap->parent == bootstrap)
332 delete_bootstrap(child_bootstrap);
333 }
334
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);
342 free(bootstrap);
343 }
344
345 server_t *
346 lookup_server_by_port(mach_port_t port)
347 {
348 server_t *serverp;
349
350 for ( serverp = FIRST(servers)
351 ; !IS_END(serverp, servers)
352 ; serverp = NEXT(serverp))
353 {
354 if (port == serverp->port)
355 return serverp;
356 }
357 return NULL;
358 }
359
360 server_t *
361 find_init_server(void)
362 {
363 server_t *serverp;
364
365 for ( serverp = FIRST(servers)
366 ; !IS_END(serverp, servers)
367 ; serverp = NEXT(serverp))
368 {
369 if (serverp->servertype == ETCINIT)
370 return serverp;
371 }
372 return NULL;
373 }
374
375 void *
376 ckmalloc(unsigned nbytes)
377 {
378 void *cp;
379
380 if ((cp = malloc(nbytes)) == NULL)
381 fatal("Out of memory");
382 return cp;
383 }
384
385