]> git.saurik.com Git - apple/configd.git/blob - configd.tproj/_configopen.c
facaf7e27372a4ab6e9660872f168070e370c48a
[apple/configd.git] / configd.tproj / _configopen.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 "configd.h"
35 #include "configd_server.h"
36 #include "session.h"
37
38 __private_extern__
39 int
40 __SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name)
41 {
42 /*
43 * allocate and initialize a new session
44 */
45 *store = (SCDynamicStoreRef)__SCDynamicStoreCreatePrivate(NULL, name, NULL, NULL);
46
47 /*
48 * If necessary, initialize the store and session data dictionaries
49 */
50 if (storeData == NULL) {
51 sessionData = CFDictionaryCreateMutable(NULL,
52 0,
53 &kCFTypeDictionaryKeyCallBacks,
54 &kCFTypeDictionaryValueCallBacks);
55 storeData = CFDictionaryCreateMutable(NULL,
56 0,
57 &kCFTypeDictionaryKeyCallBacks,
58 &kCFTypeDictionaryValueCallBacks);
59 patternData = CFDictionaryCreateMutable(NULL,
60 0,
61 &kCFTypeDictionaryKeyCallBacks,
62 &kCFTypeDictionaryValueCallBacks);
63 changedKeys = CFSetCreateMutable(NULL,
64 0,
65 &kCFTypeSetCallBacks);
66 deferredRemovals = CFSetCreateMutable(NULL,
67 0,
68 &kCFTypeSetCallBacks);
69 removedSessionKeys = CFSetCreateMutable(NULL,
70 0,
71 &kCFTypeSetCallBacks);
72 }
73
74 return kSCStatusOK;
75 }
76
77
78 __private_extern__
79 kern_return_t
80 _configopen(mach_port_t server,
81 xmlData_t nameRef, /* raw XML bytes */
82 mach_msg_type_number_t nameLen,
83 xmlData_t optionsRef, /* raw XML bytes */
84 mach_msg_type_number_t optionsLen,
85 mach_port_t *newServer,
86 int *sc_status)
87 {
88 CFDictionaryRef info;
89 CFMachPortRef mp;
90 serverSessionRef mySession;
91 CFStringRef name = NULL; /* name (un-serialized) */
92 CFMutableDictionaryRef newInfo;
93 serverSessionRef newSession;
94 mach_port_t oldNotify;
95 CFDictionaryRef options = NULL; /* options (un-serialized) */
96 CFStringRef sessionKey;
97 kern_return_t status;
98 SCDynamicStorePrivateRef storePrivate;
99 CFBooleanRef useSessionKeys = NULL;
100
101 /* un-serialize the name */
102 if (!_SCUnserializeString(&name, NULL, (void *)nameRef, nameLen)) {
103 *sc_status = kSCStatusFailed;
104 goto done;
105 }
106
107 if (!isA_CFString(name)) {
108 *sc_status = kSCStatusInvalidArgument;
109 goto done;
110 }
111
112 if (optionsRef && (optionsLen > 0)) {
113 /* un-serialize the [session] options */
114 if (!_SCUnserialize((CFPropertyListRef *)&options, NULL, (void *)optionsRef, optionsLen)) {
115 *sc_status = kSCStatusFailed;
116 goto done;
117 }
118
119 if (!isA_CFDictionary(options)) {
120 *sc_status = kSCStatusInvalidArgument;
121 goto done;
122 }
123
124 /*
125 * [pre-]process any provided options
126 */
127 useSessionKeys = CFDictionaryGetValue(options, kSCDynamicStoreUseSessionKeys);
128 if (useSessionKeys != NULL) {
129 if (!isA_CFBoolean(useSessionKeys)) {
130 *sc_status = kSCStatusInvalidArgument;
131 goto done;
132 }
133 }
134 }
135
136 mySession = getSession(server);
137 if (mySession->store) {
138 #ifdef DEBUG
139 SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen(): session is already open."));
140 #endif /* DEBUG */
141 *sc_status = kSCStatusFailed; /* you can't re-open an "open" session */
142 goto done;
143 }
144
145 /* Create the server port for this session */
146 mp = CFMachPortCreate(NULL, configdCallback, NULL, NULL);
147
148 /* return the newly allocated port to be used for this session */
149 *newServer = CFMachPortGetPort(mp);
150
151 /*
152 * establish the new session
153 */
154 newSession = addSession(mp);
155
156 /* Create and add a run loop source for the port */
157 newSession->serverRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mp, 0);
158 CFRunLoopAddSource(CFRunLoopGetCurrent(),
159 newSession->serverRunLoopSource,
160 kCFRunLoopDefaultMode);
161
162 /*
163 * save the credentials associated with the caller.
164 */
165 newSession->callerEUID = mySession->callerEUID;
166 newSession->callerEGID = mySession->callerEGID;
167
168 if (_configd_trace) {
169 SCTrace(TRUE, _configd_trace, CFSTR("open : %5d : %@\n"), *newServer, name);
170 }
171
172 *sc_status = __SCDynamicStoreOpen(&newSession->store, name);
173 storePrivate = (SCDynamicStorePrivateRef)newSession->store;
174
175 /*
176 * Make the server port accessible to the framework routines.
177 */
178 storePrivate->server = *newServer;
179
180 /*
181 * Process any provided [session] options
182 */
183 if (useSessionKeys != NULL) {
184 storePrivate->useSessionKeys = CFBooleanGetValue(useSessionKeys);
185 }
186
187 /* Request a notification when/if the client dies */
188 status = mach_port_request_notification(mach_task_self(),
189 *newServer,
190 MACH_NOTIFY_NO_SENDERS,
191 1,
192 *newServer,
193 MACH_MSG_TYPE_MAKE_SEND_ONCE,
194 &oldNotify);
195 if (status != KERN_SUCCESS) {
196 SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen() mach_port_request_notification() failed: %s"), mach_error_string(status));
197 cleanupSession(*newServer);
198 *newServer = MACH_PORT_NULL;
199 *sc_status = kSCStatusFailed;
200 goto done;
201 }
202
203 #ifdef DEBUG
204 if (oldNotify != MACH_PORT_NULL) {
205 SCLog(TRUE, LOG_ERR, CFSTR("_configopen(): why is oldNotify != MACH_PORT_NULL?"));
206 }
207 #endif /* DEBUG */
208
209 /*
210 * Save the name of the calling application / plug-in with the session data.
211 */
212 sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), *newServer);
213 info = CFDictionaryGetValue(sessionData, sessionKey);
214 if (info) {
215 newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info);
216 } else {
217 newInfo = CFDictionaryCreateMutable(NULL,
218 0,
219 &kCFTypeDictionaryKeyCallBacks,
220 &kCFTypeDictionaryValueCallBacks);
221 }
222 CFDictionarySetValue(newInfo, kSCDName, name);
223 CFDictionarySetValue(sessionData, sessionKey, newInfo);
224 CFRelease(newInfo);
225 CFRelease(sessionKey);
226
227 done :
228
229 if (name) CFRelease(name);
230 if (options) CFRelease(options);
231 return KERN_SUCCESS;
232 }