#include "configd.h"
#include "session.h"
static __inline__ void
my_CFDictionaryApplyFunction(CFDictionaryRef theDict,
CFDictionaryApplierFunction applier,
void *context)
{
CFAllocatorRef myAllocator;
CFDictionaryRef myDict;
myAllocator = CFGetAllocator(theDict);
myDict = CFDictionaryCreateCopy(myAllocator, theDict);
CFDictionaryApplyFunction(myDict, applier, context);
CFRelease(myDict);
return;
}
int
__SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreAddWatchedKey:"));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key);
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE");
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession;
}
if (isRegex) {
if (CFSetContainsValue(storePrivate->reKeys, key))
return kSCStatusKeyExists;
CFSetAddValue(storePrivate->reKeys, key);
} else {
if (CFSetContainsValue(storePrivate->keys, key))
return kSCStatusKeyExists;
CFSetAddValue(storePrivate->keys, key);
}
if (isRegex) {
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)) {
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert regex key to C string"));
CFAllocatorDeallocate(NULL, regexStr);
return kSCStatusFailed;
}
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));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regcomp() key: %s"), reErrBuf);
CFRelease(regexData);
return kSCStatusFailed;
}
context.store = storePrivate;
context.preg = (regex_t *)CFDataGetBytePtr(regexData);
my_CFDictionaryApplyFunction(storeData,
(CFDictionaryApplierFunction)_addRegexWatcherByKey,
&context);
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->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(regexData);
CFRelease(newInfo);
CFRelease(sessionKey);
} else {
CFNumberRef sessionNum;
sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
_addWatcher(sessionNum, key);
CFRelease(sessionNum);
}
return kSCStatusOK;
}
kern_return_t
_notifyadd(mach_port_t server,
xmlData_t keyRef,
mach_msg_type_number_t keyLen,
int isRegex,
int *sc_status
)
{
serverSessionRef mySession = getSession(server);
CFStringRef key;
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Add notification key for this session."));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server);
if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
return KERN_SUCCESS;
}
if (!isA_CFString(key)) {
CFRelease(key);
*sc_status = kSCStatusInvalidArgument;
return KERN_SUCCESS;
}
*sc_status = __SCDynamicStoreAddWatchedKey(mySession->store, key, isRegex);
CFRelease(key);
return KERN_SUCCESS;
}