]> git.saurik.com Git - apple/configd.git/blob - configd.tproj/_configopen.c
configd-24.tar.gz
[apple/configd.git] / configd.tproj / _configopen.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 #include "configd.h"
24 #include "configd_server.h"
25 #include "session.h"
26
27 SCDStatus
28 _SCDOpen(SCDSessionRef *session, CFStringRef name)
29 {
30 SCDSessionPrivateRef sessionPrivate;
31
32 SCDLog(LOG_DEBUG, CFSTR("_SCDOpen:"));
33 SCDLog(LOG_DEBUG, CFSTR(" name = %@"), name);
34
35 /*
36 * allocate and initialize a new session
37 */
38 sessionPrivate = (SCDSessionPrivateRef)_SCDSessionCreatePrivate();
39 *session = (SCDSessionRef)sessionPrivate;
40
41 /*
42 * If necessary, initialize the cache and session data dictionaries
43 */
44 if (cacheData == NULL) {
45 cacheData = CFDictionaryCreateMutable(NULL,
46 0,
47 &kCFTypeDictionaryKeyCallBacks,
48 &kCFTypeDictionaryValueCallBacks);
49 sessionData = CFDictionaryCreateMutable(NULL,
50 0,
51 &kCFTypeDictionaryKeyCallBacks,
52 &kCFTypeDictionaryValueCallBacks);
53 changedKeys = CFSetCreateMutable(NULL,
54 0,
55 &kCFTypeSetCallBacks);
56 deferredRemovals = CFSetCreateMutable(NULL,
57 0,
58 &kCFTypeSetCallBacks);
59 removedSessionKeys = CFSetCreateMutable(NULL,
60 0,
61 &kCFTypeSetCallBacks);
62 }
63
64 return SCD_OK;
65 }
66
67
68 kern_return_t
69 _configopen(mach_port_t server,
70 xmlData_t nameRef, /* raw XML bytes */
71 mach_msg_type_number_t nameLen,
72 mach_port_t *newServer,
73 int *scd_status)
74 {
75 kern_return_t status;
76 serverSessionRef mySession, newSession;
77 CFDataRef xmlName; /* name (XML serialized) */
78 CFStringRef name; /* name (un-serialized) */
79 CFStringRef xmlError;
80 mach_port_t oldNotify;
81 CFStringRef sessionKey;
82 CFDictionaryRef info;
83 CFMutableDictionaryRef newInfo;
84 CFMachPortRef mp;
85
86 SCDLog(LOG_DEBUG, CFSTR("Open new session."));
87 SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server);
88
89 /* un-serialize the name */
90 xmlName = CFDataCreate(NULL, nameRef, nameLen);
91 status = vm_deallocate(mach_task_self(), (vm_address_t)nameRef, nameLen);
92 if (status != KERN_SUCCESS) {
93 CFRelease(xmlName);
94 SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
95 /* non-fatal???, proceed */
96 }
97 name = CFPropertyListCreateFromXMLData(NULL,
98 xmlName,
99 kCFPropertyListImmutable,
100 &xmlError);
101 CFRelease(xmlName);
102 if (xmlError) {
103 SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() name: %s"), xmlError);
104 *scd_status = SCD_FAILED;
105 return KERN_SUCCESS;
106 }
107
108 mySession = getSession(server);
109 if (mySession->session) {
110 CFRelease(name);
111 SCDLog(LOG_DEBUG, CFSTR(" Sorry, this session is already open."));
112 *scd_status = SCD_FAILED; /* you can't re-open an "open" session */
113 return KERN_SUCCESS;
114 }
115
116 /* Create the server port for this session */
117 mp = CFMachPortCreate(NULL, configdCallback, NULL, NULL);
118
119 /* return the newly allocated port to be used for this session */
120 *newServer = CFMachPortGetPort(mp);
121
122 /*
123 * establish the new session
124 */
125 newSession = addSession(mp);
126
127 /* Create and add a run loop source for the port */
128 newSession->serverRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mp, 0);
129 CFRunLoopAddSource(CFRunLoopGetCurrent(),
130 newSession->serverRunLoopSource,
131 kCFRunLoopDefaultMode);
132
133 /*
134 * save the credentials associated with the caller.
135 */
136 newSession->callerEUID = mySession->callerEUID;
137 newSession->callerEGID = mySession->callerEGID;
138
139 *scd_status = _SCDOpen(&newSession->session, name);
140
141 /*
142 * Make the server port accessible to the framework routines.
143 */
144 ((SCDSessionPrivateRef)newSession->session)->server = *newServer;
145
146 /* Request a notification when/if the client dies */
147 status = mach_port_request_notification(mach_task_self(),
148 *newServer,
149 MACH_NOTIFY_NO_SENDERS,
150 1,
151 *newServer,
152 MACH_MSG_TYPE_MAKE_SEND_ONCE,
153 &oldNotify);
154 if (status != KERN_SUCCESS) {
155 SCDLog(LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
156 CFRelease(name);
157 cleanupSession(*newServer);
158 *newServer = MACH_PORT_NULL;
159 *scd_status = SCD_FAILED;
160 return KERN_SUCCESS;
161 }
162
163 #ifdef DEBUG
164 if (oldNotify != MACH_PORT_NULL) {
165 SCDLog(LOG_DEBUG, CFSTR("_configopen(): why is oldNotify != MACH_PORT_NULL?"));
166 }
167 #endif /* DEBUG */
168
169 /*
170 * Save the name of the calling application / plug-in with the session data.
171 */
172 sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), *newServer);
173 info = CFDictionaryGetValue(sessionData, sessionKey);
174 if (info) {
175 newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info);
176 } else {
177 newInfo = CFDictionaryCreateMutable(NULL,
178 0,
179 &kCFTypeDictionaryKeyCallBacks,
180 &kCFTypeDictionaryValueCallBacks);
181 }
182 CFDictionarySetValue(newInfo, kSCDName, name);
183 CFRelease(name);
184 CFDictionarySetValue(sessionData, sessionKey, newInfo);
185 CFRelease(newInfo);
186 CFRelease(sessionKey);
187
188 return KERN_SUCCESS;
189 }