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