#include "configd.h"
#include "configd_server.h"
#include "session.h"
__private_extern__
int
__SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name)
{
*store = (SCDynamicStoreRef)__SCDynamicStoreCreatePrivate(NULL, name, NULL, NULL);
if (storeData == NULL) {
sessionData = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
storeData = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
patternData = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
changedKeys = CFSetCreateMutable(NULL,
0,
&kCFTypeSetCallBacks);
deferredRemovals = CFSetCreateMutable(NULL,
0,
&kCFTypeSetCallBacks);
removedSessionKeys = CFSetCreateMutable(NULL,
0,
&kCFTypeSetCallBacks);
}
return kSCStatusOK;
}
__private_extern__
kern_return_t
_configopen(mach_port_t server,
xmlData_t nameRef,
mach_msg_type_number_t nameLen,
xmlData_t optionsRef,
mach_msg_type_number_t optionsLen,
mach_port_t *newServer,
int *sc_status)
{
CFDictionaryRef info;
CFMachPortRef mp;
serverSessionRef mySession;
CFStringRef name = NULL;
CFMutableDictionaryRef newInfo;
serverSessionRef newSession;
mach_port_t oldNotify;
CFDictionaryRef options = NULL;
CFStringRef sessionKey;
kern_return_t status;
SCDynamicStorePrivateRef storePrivate;
CFBooleanRef useSessionKeys = NULL;
if (!_SCUnserializeString(&name, NULL, (void *)nameRef, nameLen)) {
*sc_status = kSCStatusFailed;
goto done;
}
if (!isA_CFString(name)) {
*sc_status = kSCStatusInvalidArgument;
goto done;
}
if (optionsRef && (optionsLen > 0)) {
if (!_SCUnserialize((CFPropertyListRef *)&options, NULL, (void *)optionsRef, optionsLen)) {
*sc_status = kSCStatusFailed;
goto done;
}
if (!isA_CFDictionary(options)) {
*sc_status = kSCStatusInvalidArgument;
goto done;
}
useSessionKeys = CFDictionaryGetValue(options, kSCDynamicStoreUseSessionKeys);
if (useSessionKeys != NULL) {
if (!isA_CFBoolean(useSessionKeys)) {
*sc_status = kSCStatusInvalidArgument;
goto done;
}
}
}
mySession = getSession(server);
if (mySession->store) {
#ifdef DEBUG
SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen(): session is already open."));
#endif
*sc_status = kSCStatusFailed;
goto done;
}
mp = CFMachPortCreate(NULL, configdCallback, NULL, NULL);
*newServer = CFMachPortGetPort(mp);
newSession = addSession(mp);
newSession->serverRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mp, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(),
newSession->serverRunLoopSource,
kCFRunLoopDefaultMode);
newSession->callerEUID = mySession->callerEUID;
newSession->callerEGID = mySession->callerEGID;
if (_configd_trace) {
SCTrace(TRUE, _configd_trace, CFSTR("open : %5d : %@\n"), *newServer, name);
}
*sc_status = __SCDynamicStoreOpen(&newSession->store, name);
storePrivate = (SCDynamicStorePrivateRef)newSession->store;
storePrivate->server = *newServer;
if (useSessionKeys != NULL) {
storePrivate->useSessionKeys = CFBooleanGetValue(useSessionKeys);
}
status = mach_port_request_notification(mach_task_self(),
*newServer,
MACH_NOTIFY_NO_SENDERS,
1,
*newServer,
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen() mach_port_request_notification() failed: %s"), mach_error_string(status));
cleanupSession(*newServer);
*newServer = MACH_PORT_NULL;
*sc_status = kSCStatusFailed;
goto done;
}
#ifdef DEBUG
if (oldNotify != MACH_PORT_NULL) {
SCLog(TRUE, LOG_ERR, CFSTR("_configopen(): why is oldNotify != MACH_PORT_NULL?"));
}
#endif
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), *newServer);
info = CFDictionaryGetValue(sessionData, sessionKey);
if (info) {
newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info);
} else {
newInfo = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
CFDictionarySetValue(newInfo, kSCDName, name);
CFDictionarySetValue(sessionData, sessionKey, newInfo);
CFRelease(newInfo);
CFRelease(sessionKey);
done :
if (name) CFRelease(name);
if (options) CFRelease(options);
return KERN_SUCCESS;
}