#include <unistd.h>
#include "configd.h"
#include "session.h"
static boolean_t
isMySessionKey(CFStringRef sessionKey, CFStringRef key)
{
CFDictionaryRef dict;
CFStringRef cacheSessionKey;
dict = CFDictionaryGetValue(cacheData, key);
if (!dict) {
return FALSE;
}
cacheSessionKey = CFDictionaryGetValue(dict, kSCDSession);
if (!cacheSessionKey) {
return FALSE;
}
if (!CFEqual(sessionKey, cacheSessionKey)) {
return FALSE;
}
return TRUE;
}
SCDStatus
_SCDClose(SCDSessionRef *session)
{
SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)*session;
CFIndex keyCnt;
CFStringRef sessionKey;
CFDictionaryRef dict;
CFArrayRef keys;
serverSessionRef mySession;
SCDLog(LOG_DEBUG, CFSTR("_SCDClose:"));
if ((*session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) {
return SCD_NOSESSION;
}
if ((keyCnt = CFSetGetCount(sessionPrivate->keys)) > 0) {
void **watchedKeys;
CFArrayRef keysToRemove;
CFIndex i;
watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0);
CFSetGetValues(sessionPrivate->keys, watchedKeys);
keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks);
CFAllocatorDeallocate(NULL, watchedKeys);
for (i=0; i<keyCnt; i++) {
(void) _SCDNotifierRemove(*session,
CFArrayGetValueAtIndex(keysToRemove, i),
0);
}
CFRelease(keysToRemove);
}
if ((keyCnt = CFSetGetCount(sessionPrivate->reKeys)) > 0) {
void **watchedKeys;
CFArrayRef keysToRemove;
CFIndex i;
watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0);
CFSetGetValues(sessionPrivate->reKeys, watchedKeys);
keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks);
CFAllocatorDeallocate(NULL, watchedKeys);
for (i=0; i<keyCnt; i++) {
(void) _SCDNotifierRemove(*session,
CFArrayGetValueAtIndex(keysToRemove, i),
kSCDRegexKey);
}
CFRelease(keysToRemove);
}
(void) _SCDNotifierCancel(*session);
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server);
dict = CFDictionaryGetValue(sessionData, sessionKey);
keys = CFDictionaryGetValue(dict, kSCDSessionKeys);
if (keys && ((keyCnt = CFArrayGetCount(keys)) > 0)) {
boolean_t wasLocked;
CFIndex i;
wasLocked = SCDOptionGet(NULL, kSCDOptionIsLocked);
if (!wasLocked) {
(void) _SCDLock(*session);
}
for (i=0; i<keyCnt; i++) {
if (isMySessionKey(sessionKey, CFArrayGetValueAtIndex(keys, i)))
(void) _SCDRemove(*session, CFArrayGetValueAtIndex(keys, i));
}
if (wasLocked) {
_swapLockedCacheData();
for (i=0; i<keyCnt; i++) {
if (isMySessionKey(sessionKey, CFArrayGetValueAtIndex(keys, i)))
(void) _SCDRemove(*session, CFArrayGetValueAtIndex(keys, i));
}
_swapLockedCacheData();
}
}
CFRelease(sessionKey);
if (SCDOptionGet(*session, kSCDOptionIsLocked)) {
(void) _SCDUnlock(*session);
}
mySession = getSession(sessionPrivate->server);
if (mySession->serverRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
mySession->serverRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(mySession->serverRunLoopSource);
}
CFMachPortInvalidate(mySession->serverPort);
CFRelease(mySession->serverPort);
CFRelease(sessionPrivate->keys);
CFRelease(sessionPrivate->reKeys);
CFAllocatorDeallocate(NULL, sessionPrivate);
*session = NULL;
return SCD_OK;
}
kern_return_t
_configclose(mach_port_t server, int *scd_status)
{
serverSessionRef mySession = getSession(server);
SCDLog(LOG_DEBUG, CFSTR("Close session."));
SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server);
*scd_status = _SCDClose(&mySession->session);
if (*scd_status != SCD_OK) {
SCDLog(LOG_DEBUG, CFSTR(" _SCDClose(): %s"), SCDError(*scd_status));
return KERN_SUCCESS;
}
removeSession(server);
return KERN_SUCCESS;
}