#include "configd.h"
#include "configd_server.h"
#include "session.h"
SCDStatus
_SCDOpen(SCDSessionRef *session, CFStringRef name)
{
SCDSessionPrivateRef sessionPrivate;
SCDLog(LOG_DEBUG, CFSTR("_SCDOpen:"));
SCDLog(LOG_DEBUG, CFSTR(" name = %@"), name);
sessionPrivate = (SCDSessionPrivateRef)_SCDSessionCreatePrivate();
*session = (SCDSessionRef)sessionPrivate;
if (cacheData == NULL) {
cacheData = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
sessionData = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
changedKeys = CFSetCreateMutable(NULL,
0,
&kCFTypeSetCallBacks);
deferredRemovals = CFSetCreateMutable(NULL,
0,
&kCFTypeSetCallBacks);
removedSessionKeys = CFSetCreateMutable(NULL,
0,
&kCFTypeSetCallBacks);
}
return SCD_OK;
}
kern_return_t
_configopen(mach_port_t server,
xmlData_t nameRef,
mach_msg_type_number_t nameLen,
mach_port_t *newServer,
int *scd_status)
{
kern_return_t status;
serverSessionRef mySession, newSession;
CFDataRef xmlName;
CFStringRef name;
CFStringRef xmlError;
mach_port_t oldNotify;
CFStringRef sessionKey;
CFDictionaryRef info;
CFMutableDictionaryRef newInfo;
CFMachPortRef mp;
SCDLog(LOG_DEBUG, CFSTR("Open new session."));
SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server);
xmlName = CFDataCreate(NULL, nameRef, nameLen);
status = vm_deallocate(mach_task_self(), (vm_address_t)nameRef, nameLen);
if (status != KERN_SUCCESS) {
CFRelease(xmlName);
SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
}
name = CFPropertyListCreateFromXMLData(NULL,
xmlName,
kCFPropertyListImmutable,
&xmlError);
CFRelease(xmlName);
if (xmlError) {
SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() name: %s"), xmlError);
*scd_status = SCD_FAILED;
return KERN_SUCCESS;
}
mySession = getSession(server);
if (mySession->session) {
CFRelease(name);
SCDLog(LOG_DEBUG, CFSTR(" Sorry, this session is already open."));
*scd_status = SCD_FAILED;
return KERN_SUCCESS;
}
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;
*scd_status = _SCDOpen(&newSession->session, name);
((SCDSessionPrivateRef)newSession->session)->server = *newServer;
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) {
SCDLog(LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
CFRelease(name);
cleanupSession(*newServer);
*newServer = MACH_PORT_NULL;
*scd_status = SCD_FAILED;
return KERN_SUCCESS;
}
#ifdef DEBUG
if (oldNotify != MACH_PORT_NULL) {
SCDLog(LOG_DEBUG, 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);
CFRelease(name);
CFDictionarySetValue(sessionData, sessionKey, newInfo);
CFRelease(newInfo);
CFRelease(sessionKey);
return KERN_SUCCESS;
}