]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCDOpen.c
configd-84.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCDOpen.c
1 /*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26 /*
27 * Modification History
28 *
29 * June 1, 2001 Allan Nathanson <ajn@apple.com>
30 * - public API conversion
31 *
32 * March 24, 2000 Allan Nathanson <ajn@apple.com>
33 * - initial revision
34 */
35
36 #include <stdlib.h>
37 #include <mach/mach.h>
38 #include <mach/mach_error.h>
39 #include <servers/bootstrap.h>
40
41 #include <SystemConfiguration/SystemConfiguration.h>
42 #include <SystemConfiguration/SCPrivate.h>
43 #include "SCDynamicStoreInternal.h"
44 #include "config.h" /* MiG generated file */
45
46 static CFStringRef
47 __SCDynamicStoreCopyDescription(CFTypeRef cf) {
48 CFAllocatorRef allocator = CFGetAllocator(cf);
49 CFMutableStringRef result;
50
51 result = CFStringCreateMutable(allocator, 0);
52 CFStringAppendFormat(result, NULL, CFSTR("<SCDynamicStore %p [%p]> {\n"), cf, allocator);
53 CFStringAppendFormat(result, NULL, CFSTR("}"));
54
55 return result;
56 }
57
58
59 static void
60 __SCDynamicStoreDeallocate(CFTypeRef cf)
61 {
62 int oldThreadState;
63 int sc_status;
64 kern_return_t status;
65 SCDynamicStoreRef store = (SCDynamicStoreRef)cf;
66 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
67
68 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreDeallocate:"));
69
70 (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldThreadState);
71
72 /* Remove/cancel any outstanding notification requests. */
73 (void) SCDynamicStoreNotifyCancel(store);
74
75 if (storePrivate->server && storePrivate->locked) {
76 (void) SCDynamicStoreUnlock(store); /* release the lock */
77 }
78
79 if (storePrivate->server != MACH_PORT_NULL) {
80 status = configclose(storePrivate->server, (int *)&sc_status);
81 if (status != KERN_SUCCESS) {
82 if (status != MACH_SEND_INVALID_DEST)
83 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configclose(): %s"), mach_error_string(status));
84 }
85
86 (void) mach_port_destroy(mach_task_self(), storePrivate->server);
87 storePrivate->server = MACH_PORT_NULL;
88 }
89
90 (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldThreadState);
91 pthread_testcancel();
92
93 /* release any callback context info */
94 if (storePrivate->rlsContext.release) {
95 storePrivate->rlsContext.release(storePrivate->rlsContext.info);
96 }
97
98 /* release any keys being watched */
99 CFRelease(storePrivate->keys);
100 CFRelease(storePrivate->patterns);
101
102 return;
103 }
104
105
106 static CFTypeID __kSCDynamicStoreTypeID = _kCFRuntimeNotATypeID;
107
108
109 static const CFRuntimeClass __SCDynamicStoreClass = {
110 0, // version
111 "SCDynamicStore", // className
112 NULL, // init
113 NULL, // copy
114 __SCDynamicStoreDeallocate, // dealloc
115 NULL, // equal
116 NULL, // hash
117 NULL, // copyFormattingDesc
118 __SCDynamicStoreCopyDescription // copyDebugDesc
119 };
120
121
122 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
123
124 static void
125 __SCDynamicStoreInitialize(void) {
126 __kSCDynamicStoreTypeID = _CFRuntimeRegisterClass(&__SCDynamicStoreClass);
127 return;
128 }
129
130
131 SCDynamicStorePrivateRef
132 __SCDynamicStoreCreatePrivate(CFAllocatorRef allocator,
133 const CFStringRef name,
134 SCDynamicStoreCallBack callout,
135 SCDynamicStoreContext *context)
136 {
137 uint32_t size;
138 SCDynamicStorePrivateRef storePrivate;
139
140 /* initialize runtime */
141 pthread_once(&initialized, __SCDynamicStoreInitialize);
142
143 /* allocate session */
144 size = sizeof(SCDynamicStorePrivate) - sizeof(CFRuntimeBase);
145 storePrivate = (SCDynamicStorePrivateRef)_CFRuntimeCreateInstance(allocator,
146 __kSCDynamicStoreTypeID,
147 size,
148 NULL);
149 if (!storePrivate) {
150 return NULL;
151 }
152
153 /* server side of the "configd" session */
154 storePrivate->server = MACH_PORT_NULL;
155
156 /* flags */
157 storePrivate->locked = FALSE;
158
159 /* Notification status */
160 storePrivate->notifyStatus = NotifierNotRegistered;
161
162 /* "client" information associated with SCDynamicStoreCreateRunLoopSource() */
163 storePrivate->rlsRefs = 0;
164 storePrivate->rls = NULL;
165 storePrivate->rlsFunction = callout;
166 storePrivate->rlsContext.info = NULL;
167 storePrivate->rlsContext.retain = NULL;
168 storePrivate->rlsContext.release = NULL;
169 storePrivate->rlsContext.copyDescription = NULL;
170 if (context) {
171 bcopy(context, &storePrivate->rlsContext, sizeof(SCDynamicStoreContext));
172 if (context->retain) {
173 storePrivate->rlsContext.info = (void *)context->retain(context->info);
174 }
175 }
176
177 /* "client" information associated with SCDynamicStoreNotifyCallback() */
178 storePrivate->callbackFunction = NULL;
179 storePrivate->callbackArgument = NULL;
180 storePrivate->callbackPort = NULL;
181 storePrivate->callbackRunLoop = NULL;
182 storePrivate->callbackRunLoopSource = NULL;
183
184 /* "server" information associated with SCDynamicStoreSetNotificationKeys() */
185 storePrivate->keys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
186 storePrivate->patterns = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
187
188 /* "server" information associated with SCDynamicStoreNotifyMachPort(); */
189 storePrivate->notifyPort = MACH_PORT_NULL;
190 storePrivate->notifyPortIdentifier = 0;
191
192 /* "server" information associated with SCDynamicStoreNotifyFileDescriptor(); */
193 storePrivate->notifyFile = -1;
194 storePrivate->notifyFileIdentifier = 0;
195
196 /* "server" information associated with SCDynamicStoreNotifySignal(); */
197 storePrivate->notifySignal = 0;
198 storePrivate->notifySignalTask = TASK_NULL;
199
200 return storePrivate;
201 }
202
203
204 SCDynamicStoreRef
205 SCDynamicStoreCreate(CFAllocatorRef allocator,
206 CFStringRef name,
207 SCDynamicStoreCallBack callout,
208 SCDynamicStoreContext *context)
209 {
210 SCDynamicStorePrivateRef storePrivate;
211 kern_return_t status;
212 mach_port_t bootstrap_port;
213 CFBundleRef bundle;
214 CFStringRef bundleID = NULL;
215 mach_port_t server;
216 char *server_name;
217 CFDataRef utfName; /* serialized name */
218 xmlData_t myNameRef;
219 CFIndex myNameLen;
220 int sc_status;
221
222 if (_sc_verbose) {
223 SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCreate:"));
224 SCLog(TRUE, LOG_DEBUG, CFSTR(" name = %@"), name);
225 }
226
227 /*
228 * allocate and initialize a new session
229 */
230 storePrivate = __SCDynamicStoreCreatePrivate(allocator, name, callout, context);
231
232 status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
233 if (status != KERN_SUCCESS) {
234 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status));
235 CFRelease(storePrivate);
236 _SCErrorSet(status);
237 return NULL;
238 }
239
240 server_name = getenv("SCD_SERVER");
241 if (!server_name) {
242 server_name = SCD_SERVER;
243 }
244
245 status = bootstrap_look_up(bootstrap_port, server_name, &server);
246 switch (status) {
247 case BOOTSTRAP_SUCCESS :
248 /* service currently registered, "a good thing" (tm) */
249 break;
250 case BOOTSTRAP_UNKNOWN_SERVICE :
251 /* service not currently registered, try again later */
252 CFRelease(storePrivate);
253 _SCErrorSet(status);
254 return NULL;
255 break;
256 default :
257 #ifdef DEBUG
258 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("bootstrap_look_up() failed: status=%d"), status);
259 #endif /* DEBUG */
260 CFRelease(storePrivate);
261 _SCErrorSet(status);
262 return NULL;
263 }
264
265 /* serialize the name */
266 bundle = CFBundleGetMainBundle();
267 if (bundle) {
268 bundleID = CFBundleGetIdentifier(bundle);
269 if (bundleID) {
270 CFRetain(bundleID);
271 } else {
272 CFURLRef url;
273
274 url = CFBundleCopyExecutableURL(bundle);
275 if (url) {
276 bundleID = CFURLCopyPath(url);
277 CFRelease(url);
278 }
279 }
280 }
281
282 if (bundleID) {
283 CFStringRef fullName;
284
285 if (CFEqual(bundleID, CFSTR("/"))) {
286 CFRelease(bundleID);
287 bundleID = CFStringCreateWithFormat(NULL, NULL, CFSTR("(%d)"), getpid());
288 }
289
290 fullName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"), bundleID, name);
291 name = fullName;
292 CFRelease(bundleID);
293 } else {
294 CFRetain(name);
295 }
296
297 if (!_SCSerializeString(name, &utfName, (void **)&myNameRef, &myNameLen)) {
298 CFRelease(name);
299 _SCErrorSet(kSCStatusFailed);
300 return NULL;
301 }
302 CFRelease(name);
303
304 /* open a new session with the server */
305 status = configopen(server, myNameRef, myNameLen, &storePrivate->server, (int *)&sc_status);
306
307 /* clean up */
308 CFRelease(utfName);
309
310 if (status != KERN_SUCCESS) {
311 if (status != MACH_SEND_INVALID_DEST)
312 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configopen(): %s"), mach_error_string(status));
313 CFRelease(storePrivate);
314 _SCErrorSet(status);
315 return NULL;
316 }
317
318 if (sc_status != kSCStatusOK) {
319 CFRelease(storePrivate);
320 _SCErrorSet(sc_status);
321 return NULL;
322 }
323
324 SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" server port = %d"), storePrivate->server);
325 return (SCDynamicStoreRef)storePrivate;
326 }
327
328
329 CFTypeID
330 SCDynamicStoreGetTypeID(void) {
331 pthread_once(&initialized, __SCDynamicStoreInitialize); /* initialize runtime */
332 return __kSCDynamicStoreTypeID;
333 }