#include "configd.h"
#include "session.h"
SCDStatus
_SCDNotifierAdd(SCDSessionRef session, CFStringRef key, int regexOptions)
{
SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session;
SCDLog(LOG_DEBUG, CFSTR("_SCDNotifierAdd:"));
SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key);
SCDLog(LOG_DEBUG, CFSTR(" regexOptions = %0o"), regexOptions);
if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) {
return SCD_NOSESSION;
}
if (regexOptions & kSCDRegexKey) {
if (CFSetContainsValue(sessionPrivate->reKeys, key))
return SCD_EXISTS;
CFSetAddValue(sessionPrivate->reKeys, key);
} else {
if (CFSetContainsValue(sessionPrivate->keys, key))
return SCD_EXISTS;
CFSetAddValue(sessionPrivate->keys, key);
}
if (regexOptions & kSCDRegexKey) {
CFStringRef sessionKey;
int regexStrLen;
char *regexStr;
CFMutableDataRef regexData;
int reError;
char reErrBuf[256];
int reErrStrLen;
addContext context;
CFDictionaryRef info;
CFMutableDictionaryRef newInfo;
CFArrayRef rKeys;
CFMutableArrayRef newRKeys;
CFArrayRef rData;
CFMutableArrayRef newRData;
regexStrLen = CFStringGetLength(key) + 1;
regexStr = CFAllocatorAllocate(NULL, regexStrLen, 0);
if (!CFStringGetCString(key,
regexStr,
regexStrLen,
kCFStringEncodingMacRoman)) {
SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString: could not convert regex key to C string"));
CFAllocatorDeallocate(NULL, regexStr);
return SCD_FAILED;
}
regexData = CFDataCreateMutable(NULL, sizeof(regex_t));
CFDataSetLength(regexData, sizeof(regex_t));
reError = regcomp((regex_t *)CFDataGetBytePtr(regexData),
regexStr,
REG_EXTENDED);
CFAllocatorDeallocate(NULL, regexStr);
if (reError != 0) {
reErrStrLen = regerror(reError,
(regex_t *)CFDataGetBytePtr(regexData),
reErrBuf,
sizeof(reErrBuf));
SCDLog(LOG_DEBUG, CFSTR("regcomp() key: %s"), reErrBuf);
CFRelease(regexData);
return SCD_FAILED;
}
context.session = sessionPrivate;
context.preg = (regex_t *)CFDataGetBytePtr(regexData);
CFDictionaryApplyFunction(cacheData,
(CFDictionaryApplierFunction)_addRegexWatcherByKey,
&context);
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server);
info = CFDictionaryGetValue(sessionData, sessionKey);
if (info) {
newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info);
} else {
newInfo = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
rKeys = CFDictionaryGetValue(newInfo, kSCDRegexKeys);
if ((rKeys == NULL) ||
(CFArrayContainsValue(rKeys,
CFRangeMake(0, CFArrayGetCount(rKeys)),
key) == FALSE)) {
rData = CFDictionaryGetValue(newInfo, kSCDRegexData);
if (rKeys) {
newRKeys = CFArrayCreateMutableCopy(NULL, 0, rKeys);
newRData = CFArrayCreateMutableCopy(NULL, 0, rData);
} else {
newRKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
newRData = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
CFArrayAppendValue(newRKeys, key);
CFDictionarySetValue(newInfo, kSCDRegexKeys, newRKeys);
CFRelease(newRKeys);
CFArrayAppendValue(newRData, regexData);
CFDictionarySetValue(newInfo, kSCDRegexData, newRData);
CFRelease(newRData);
CFDictionarySetValue(sessionData, sessionKey, newInfo);
}
CFRelease(newInfo);
CFRelease(sessionKey);
} else {
CFNumberRef sessionNum;
sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionPrivate->server);
_addWatcher(sessionNum, key);
CFRelease(sessionNum);
}
return SCD_OK;
}
kern_return_t
_notifyadd(mach_port_t server,
xmlData_t keyRef,
mach_msg_type_number_t keyLen,
int regexOptions,
int *scd_status
)
{
kern_return_t status;
serverSessionRef mySession = getSession(server);
CFDataRef xmlKey;
CFStringRef key;
CFStringRef xmlError;
SCDLog(LOG_DEBUG, CFSTR("Add notification key for this session."));
SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server);
xmlKey = CFDataCreate(NULL, keyRef, keyLen);
status = vm_deallocate(mach_task_self(), (vm_address_t)keyRef, keyLen);
if (status != KERN_SUCCESS) {
SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
}
key = CFPropertyListCreateFromXMLData(NULL,
xmlKey,
kCFPropertyListImmutable,
&xmlError);
CFRelease(xmlKey);
if (xmlError) {
SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError);
*scd_status = SCD_FAILED;
return KERN_SUCCESS;
}
*scd_status = _SCDNotifierAdd(mySession->session, key, regexOptions);
CFRelease(key);
return KERN_SUCCESS;
}