From 0fae82ee9e32dcee00597b75650c675a75eab32e Mon Sep 17 00:00:00 2001 From: Apple Date: Sun, 26 Aug 2001 18:38:45 +0000 Subject: [PATCH] configd-42.tar.gz --- PB.project | 5 +- SystemConfiguration.fproj/CustomInfo.plist | 2 +- SystemConfiguration.fproj/DHCP.c | 628 +++++++ .../DHCPClientPreferences.h | 73 + SystemConfiguration.fproj/Makefile | 52 +- SystemConfiguration.fproj/Makefile.postamble | 11 +- SystemConfiguration.fproj/Makefile.preamble | 35 +- SystemConfiguration.fproj/PB.project | 73 +- SystemConfiguration.fproj/SCD.c | 518 +++-- SystemConfiguration.fproj/SCD.h | 613 +----- SystemConfiguration.fproj/SCDAdd.c | 82 +- SystemConfiguration.fproj/SCDAddSession.c | 82 +- SystemConfiguration.fproj/SCDClose.c | 118 -- SystemConfiguration.fproj/SCDConsoleUser.c | 159 +- SystemConfiguration.fproj/SCDConsoleUser.h | 79 +- SystemConfiguration.fproj/SCDGet.c | 221 ++- SystemConfiguration.fproj/SCDHandle.c | 102 - SystemConfiguration.fproj/SCDHostName.c | 130 +- SystemConfiguration.fproj/SCDHostName.h | 53 +- SystemConfiguration.fproj/SCDKeys.c | 57 +- SystemConfiguration.fproj/SCDKeys.h | 46 +- SystemConfiguration.fproj/SCDList.c | 136 +- SystemConfiguration.fproj/SCDLock.c | 58 +- SystemConfiguration.fproj/SCDNotifierAdd.c | 93 +- SystemConfiguration.fproj/SCDNotifierCancel.c | 118 +- .../SCDNotifierGetChanges.c | 105 +- .../SCDNotifierInformViaCallback.c | 488 +++-- .../SCDNotifierInformViaFD.c | 105 +- .../SCDNotifierInformViaMachPort.c | 87 +- .../SCDNotifierInformViaSignal.c | 78 +- SystemConfiguration.fproj/SCDNotifierList.c | 64 +- SystemConfiguration.fproj/SCDNotifierRemove.c | 97 +- .../SCDNotifierSetKeys.c | 170 ++ SystemConfiguration.fproj/SCDNotifierWait.c | 160 +- SystemConfiguration.fproj/SCDNotify.c | 93 + SystemConfiguration.fproj/SCDOpen.c | 310 ++- SystemConfiguration.fproj/SCDPlugin.h | 89 + SystemConfiguration.fproj/SCDPrivate.c | 72 +- SystemConfiguration.fproj/SCDPrivate.h | 130 -- SystemConfiguration.fproj/SCDRemove.c | 68 +- SystemConfiguration.fproj/SCDSet.c | 175 +- SystemConfiguration.fproj/SCDSnapshot.c | 58 +- SystemConfiguration.fproj/SCDTouch.c | 68 +- SystemConfiguration.fproj/SCDUnlock.c | 65 +- SystemConfiguration.fproj/SCDynamicStore.h | 339 ++++ .../SCDynamicStoreCopyDHCPInfo.h | 92 + .../SCDynamicStoreCopySpecific.h | 101 + .../SCDynamicStoreInternal.h | 118 ++ SystemConfiguration.fproj/SCDynamicStoreKey.h | 132 ++ .../SCDynamicStorePrivate.h | 246 +++ .../SCDynamicStoreSetSpecificPrivate.h | 56 + SystemConfiguration.fproj/SCNetwork.c | 1673 +++++++++-------- SystemConfiguration.fproj/SCNetwork.h | 192 +- SystemConfiguration.fproj/SCP.c | 151 +- SystemConfiguration.fproj/SCP.h | 387 +--- SystemConfiguration.fproj/SCPAdd.c | 44 +- SystemConfiguration.fproj/SCPApply.c | 73 +- SystemConfiguration.fproj/SCPClose.c | 66 - SystemConfiguration.fproj/SCPCommit.c | 103 +- SystemConfiguration.fproj/SCPGet.c | 41 +- SystemConfiguration.fproj/SCPList.c | 60 +- SystemConfiguration.fproj/SCPLock.c | 197 +- SystemConfiguration.fproj/SCPOpen.c | 311 ++- SystemConfiguration.fproj/SCPPath.c | 235 +-- SystemConfiguration.fproj/SCPPath.h | 158 +- SystemConfiguration.fproj/SCPRemove.c | 41 +- SystemConfiguration.fproj/SCPSet.c | 40 +- SystemConfiguration.fproj/SCPUnlock.c | 49 +- SystemConfiguration.fproj/SCPreferences.h | 277 +++ .../{SCPPrivate.h => SCPreferencesInternal.h} | 70 +- SystemConfiguration.fproj/SCPreferencesPath.h | 181 ++ .../SCPreferencesPrivate.h | 81 + .../SCPreferencesSetSpecific.h | 61 + SystemConfiguration.fproj/SCPrivate.h | 79 + SystemConfiguration.fproj/SCProxies.c | 77 + SystemConfiguration.fproj/SCValidation.h | 110 ++ .../SystemConfiguration.h | 118 +- SystemConfiguration.fproj/config.defs | 36 +- SystemConfiguration.fproj/genSCPreferences.c | 564 +++--- SystemConfiguration.fproj/ppp.c | 156 +- SystemConfiguration.fproj/ppp.h | 24 +- SystemConfiguration.fproj/ppp_msg.h | 3 +- SystemConfiguration.fproj/v1Compatibility.c | 816 ++++++++ SystemConfiguration.fproj/v1Compatibility.h | 378 ++++ configd.tproj/Makefile | 18 +- configd.tproj/PB.project | 146 +- configd.tproj/_SCD.c | 144 +- configd.tproj/_SCD.h | 232 ++- configd.tproj/_configadd.c | 127 +- configd.tproj/_configadd_s.c | 113 +- configd.tproj/_configclose.c | 129 +- configd.tproj/_configget.c | 272 ++- configd.tproj/_configlist.c | 207 +- configd.tproj/_configlock.c | 71 +- configd.tproj/_confignotify.c | 131 ++ configd.tproj/_configopen.c | 76 +- configd.tproj/_configremove.c | 91 +- configd.tproj/_configset.c | 385 +++- configd.tproj/_configtouch.c | 117 +- configd.tproj/_configunlock.c | 74 +- configd.tproj/_notifyadd.c | 115 +- configd.tproj/_notifycancel.c | 62 +- configd.tproj/_notifychanges.c | 48 +- configd.tproj/_notifyremove.c | 103 +- configd.tproj/_notifyviafd.c | 96 +- configd.tproj/_notifyviaport.c | 70 +- configd.tproj/_notifyviasignal.c | 97 +- configd.tproj/_snapshot.c | 55 +- configd.tproj/configd.h | 23 +- configd.tproj/configd.m | 132 +- configd.tproj/configd_server.c | 51 +- configd.tproj/configd_server.h | 252 +-- configd.tproj/notify.c | 99 +- configd.tproj/notify.h | 9 +- configd.tproj/notify_server.c | 14 +- configd.tproj/notify_server.h | 12 +- configd.tproj/plugin_support.c | 610 +++--- configd.tproj/plugin_support.h | 11 +- configd.tproj/session.c | 36 +- configd.tproj/session.h | 24 +- scselect.tproj/Makefile | 3 +- scselect.tproj/PB.project | 3 +- scselect.tproj/scselect.c | 131 +- scutil.tproj/Makefile | 11 +- scutil.tproj/PB.project | 54 +- scutil.tproj/cache.c | 147 +- scutil.tproj/cache.h | 24 +- scutil.tproj/commands.c | 247 +-- scutil.tproj/commands.h | 18 +- scutil.tproj/dictionary.c | 102 +- scutil.tproj/dictionary.h | 15 +- scutil.tproj/notify.c | 231 ++- scutil.tproj/notify.h | 33 +- scutil.tproj/scutil.c | 176 +- scutil.tproj/scutil.h | 32 +- scutil.tproj/session.c | 61 +- scutil.tproj/session.h | 15 +- scutil.tproj/tests.c | 185 +- scutil.tproj/tests.h | 21 +- 139 files changed, 12807 insertions(+), 6916 deletions(-) create mode 100644 SystemConfiguration.fproj/DHCP.c create mode 100644 SystemConfiguration.fproj/DHCPClientPreferences.h delete mode 100644 SystemConfiguration.fproj/SCDClose.c delete mode 100644 SystemConfiguration.fproj/SCDHandle.c create mode 100644 SystemConfiguration.fproj/SCDNotifierSetKeys.c create mode 100644 SystemConfiguration.fproj/SCDNotify.c create mode 100644 SystemConfiguration.fproj/SCDPlugin.h delete mode 100644 SystemConfiguration.fproj/SCDPrivate.h create mode 100644 SystemConfiguration.fproj/SCDynamicStore.h create mode 100644 SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h create mode 100644 SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h create mode 100644 SystemConfiguration.fproj/SCDynamicStoreInternal.h create mode 100644 SystemConfiguration.fproj/SCDynamicStoreKey.h create mode 100644 SystemConfiguration.fproj/SCDynamicStorePrivate.h create mode 100644 SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h delete mode 100644 SystemConfiguration.fproj/SCPClose.c create mode 100644 SystemConfiguration.fproj/SCPreferences.h rename SystemConfiguration.fproj/{SCPPrivate.h => SCPreferencesInternal.h} (59%) create mode 100644 SystemConfiguration.fproj/SCPreferencesPath.h create mode 100644 SystemConfiguration.fproj/SCPreferencesPrivate.h create mode 100644 SystemConfiguration.fproj/SCPreferencesSetSpecific.h create mode 100644 SystemConfiguration.fproj/SCPrivate.h create mode 100644 SystemConfiguration.fproj/SCProxies.c create mode 100644 SystemConfiguration.fproj/SCValidation.h create mode 100644 SystemConfiguration.fproj/v1Compatibility.c create mode 100644 SystemConfiguration.fproj/v1Compatibility.h create mode 100644 configd.tproj/_confignotify.c diff --git a/PB.project b/PB.project index 3af9f55..5726c0d 100644 --- a/PB.project +++ b/PB.project @@ -3,11 +3,14 @@ FILESTABLE = { H_FILES = (); OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); SUBPROJECTS = (SystemConfiguration.fproj, configd.tproj, scselect.tproj, scutil.tproj); }; LANGUAGE = English; MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; diff --git a/SystemConfiguration.fproj/CustomInfo.plist b/SystemConfiguration.fproj/CustomInfo.plist index 9fe5a3d..8be4e1f 100644 --- a/SystemConfiguration.fproj/CustomInfo.plist +++ b/SystemConfiguration.fproj/CustomInfo.plist @@ -1,5 +1,5 @@ { CFBundleName = "SystemConfiguration"; CFBundleIdentifier = "com.apple.SystemConfiguration"; - CFBundleShortVersionString = "1.0.1"; + CFBundleShortVersionString = "1.1.0"; } diff --git a/SystemConfiguration.fproj/DHCP.c b/SystemConfiguration.fproj/DHCP.c new file mode 100644 index 0000000..f4b7a24 --- /dev/null +++ b/SystemConfiguration.fproj/DHCP.c @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include + + +#include "SystemConfiguration.h" +#include "SCValidation.h" +#include "SCDynamicStoreCopyDHCPInfo.h" +#include "DHCPClientPreferences.h" + +#define DHCPCLIENT_PREFERENCES_ID "DHCPClient.xml" +#define DHCPCLIENT_APPLICATION_PREF "Application" + +#define DHCP_REQUESTED_PARAMETER_LIST "DHCPRequestedParameterList" + +/** + ** DHCPClientPreferences{Set,Get}ApplicationOptions() + **/ +static UInt8 * +S_get_char_array(CFArrayRef arr, CFIndex * len) +{ + UInt8 * buf = NULL; + int count = 0; + int i; + int real_count; + + if (arr) { + count = CFArrayGetCount(arr); + } + if (count == 0) { + goto done; + } + buf = malloc(count); + if (buf == NULL) { + goto done; + } + for (i = 0, real_count = 0; i < count; i++) { + CFNumberRef n = isA_CFNumber(CFArrayGetValueAtIndex(arr, i)); + int val; + + if (n && CFNumberGetValue(n, kCFNumberIntType, &val)) { + buf[real_count++] = (UInt8) val; + } + } + count = real_count; + done: + *len = count; + if (count == 0 && buf) { + free(buf); + buf = NULL; + } + return (buf); +} + +static void +my_CFArrayAppendUniqueValue(CFMutableArrayRef arr, CFTypeRef new) +{ + int i; + + for (i = 0; i < CFArrayGetCount(arr); i++) { + CFStringRef element = CFArrayGetValueAtIndex(arr, i); + if (CFEqual(element, new)) { + return; + } + } + CFArrayAppendValue(arr, new); + return; +} + +static __inline__ CFStringRef +S_application_path(CFStringRef applicationID) +{ + return (CFStringCreateWithFormat(NULL, NULL, + CFSTR("/" DHCPCLIENT_APPLICATION_PREF + "/%@"), + applicationID)); +} + +Boolean +DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID, + UInt8 * options, + CFIndex count) +{ + CFMutableDictionaryRef dict = NULL; + CFStringRef path = NULL; + SCPreferencesRef session = NULL; + Boolean success = FALSE; + + if (applicationID == NULL) { + goto done; + } + path = S_application_path(applicationID); + if (path == NULL) { + goto done; + } + session = SCPreferencesCreate(NULL, CFSTR("DHCPClientSetAppReqParams"), + CFSTR(DHCPCLIENT_PREFERENCES_ID)); + if (session == NULL) { + goto done; + } + dict = (CFMutableDictionaryRef)SCPreferencesPathGetValue(session, path); + if (dict == NULL) { + dict = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + else { + dict = CFDictionaryCreateMutableCopy(NULL, 0, dict); + } + if (dict == NULL) { + goto done; + } + if (options && count > 0) { + int i; + CFMutableArrayRef array; + + array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + if (array == NULL) { + goto done; + } + for (i = 0; i < count; i++) { + int val; + CFNumberRef number; + + if (options[i] == 0 || options[i] == 255) { + /* ignore pads and end */ + continue; + } + val = options[i]; + number = CFNumberCreate(NULL, kCFNumberIntType, &val); + if (number == NULL) { + CFRelease(array); + goto done; + } + my_CFArrayAppendUniqueValue(array, number); + CFRelease(number); + } + CFDictionarySetValue(dict, CFSTR(DHCP_REQUESTED_PARAMETER_LIST), + array); + CFRelease(array); + } + else { + CFDictionaryRemoveValue(dict, CFSTR(DHCP_REQUESTED_PARAMETER_LIST)); + } + if (SCPreferencesLock(session, TRUE)) { + success = SCPreferencesPathSetValue(session, path, dict); + if (success) { + success = SCPreferencesCommitChanges(session); + if (success) { + (void)SCPreferencesApplyChanges(session); + } + } + (void)SCPreferencesUnlock(session); + } + done: + if (session) { + CFRelease(session); + } + if (path) { + CFRelease(path); + } + if (dict) { + CFRelease(dict); + } + return (success); +} + +UInt8 * +DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID, + CFIndex * count) +{ + CFDictionaryRef dict = NULL; + UInt8 * options = NULL; + CFArrayRef parms; + CFStringRef path = NULL; + SCPreferencesRef session = NULL; + + if (applicationID == NULL) { + goto done; + } + path = S_application_path(applicationID); + if (path == NULL) { + goto done; + } + session = SCPreferencesCreate(NULL, CFSTR("DHCPClientCopyAppReqParams"), + CFSTR(DHCPCLIENT_PREFERENCES_ID)); + if (session == NULL) { + goto done; + } + dict = SCPreferencesPathGetValue(session, path); + if (dict == NULL) { + goto done; + } + parms = CFDictionaryGetValue(dict, + CFSTR(DHCP_REQUESTED_PARAMETER_LIST)); + if (isA_CFArray(parms) == NULL) { + goto done; + } + options = S_get_char_array(parms, count); + + done: + if (session) { + CFRelease(session); + } + if (path) { + CFRelease(path); + } + return (options); +} + +/** + ** DHCPClientInfo*() + **/ + +CFDictionaryRef +SCDynamicStoreCopyDHCPInfo(SCDynamicStoreRef store, CFStringRef serviceID) +{ + CFDictionaryRef dhcp_dict = NULL; + CFStringRef key = NULL; + boolean_t needs_close = FALSE; + CFDictionaryRef primary_dict = NULL; + + if (store == NULL) { + needs_close = TRUE; + store = SCDynamicStoreCreate(NULL, + CFSTR("SCDynamicStoreCopyDHCPInfo"), + NULL, NULL); + if (store == NULL) { + goto done; + } + } + + if (serviceID == NULL) { + /* get the primary service name */ + key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, + kSCDynamicStoreDomainState, + kSCEntNetIPv4); + if (key) { + primary_dict = SCDynamicStoreCopyValue(store, key); + if (primary_dict) { + serviceID = CFDictionaryGetValue(primary_dict, + kSCDynamicStorePropNetPrimaryService); + } + CFRelease(key); + } + } + if (serviceID == NULL) { + goto done; + } + key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainState, + serviceID, + kSCEntNetDHCP); + if (key) { + dhcp_dict = SCDynamicStoreCopyValue(store, key); + if (dhcp_dict != NULL + && isA_CFDictionary(dhcp_dict) == NULL) { + CFRelease(dhcp_dict); + dhcp_dict = NULL; + } + CFRelease(key); + } + done: + if (primary_dict) { + CFRelease(primary_dict); + } + if (needs_close == TRUE && store != NULL) { + CFRelease(store); + } + return (dhcp_dict); +} + +CFDataRef +DHCPInfoGetOptionData(CFDictionaryRef dhcp_dict, UInt8 code) +{ + CFDataRef data = NULL; + CFStringRef option_code_str = NULL; + + option_code_str = CFStringCreateWithFormat(NULL, NULL, + CFSTR("Option_%d"), code); + if (option_code_str == NULL) { + goto done; + } + + data = CFDictionaryGetValue(dhcp_dict, option_code_str); + data = isA_CFData(data); + done: + if (option_code_str) + CFRelease(option_code_str); + return (data); +} + +CFDateRef +DHCPInfoGetLeaseStartTime(CFDictionaryRef dhcp_dict) +{ + return (CFDictionaryGetValue(dhcp_dict, CFSTR("LeaseStartTime"))); +} + +#ifdef TEST_DHCPCLIENT_PREFERENCES +void +print_data(u_char * data_p, int n_bytes) +{ +#define CHARS_PER_LINE 16 + char line_buf[CHARS_PER_LINE + 1]; + int line_pos; + int offset; + + for (line_pos = 0, offset = 0; offset < n_bytes; offset++, data_p++) { + if (line_pos == 0) + printf("%04x ", offset); + + line_buf[line_pos] = isprint(*data_p) ? *data_p : '.'; + printf(" %02x", *data_p); + line_pos++; + if (line_pos == CHARS_PER_LINE) { + line_buf[CHARS_PER_LINE] = '\0'; + printf(" %s\n", line_buf); + line_pos = 0; + } + else if (line_pos == (CHARS_PER_LINE / 2)) + printf(" "); + } + if (line_pos) { /* need to finish up the line */ + for (; line_pos < CHARS_PER_LINE; line_pos++) { + printf(" "); + line_buf[line_pos] = ' '; + } + line_buf[CHARS_PER_LINE] = '\0'; + printf(" %s\n", line_buf); + } +} + +#define CMDSTR_GETOPTION "getoption" +#define CMDSTR_LEASE "leaseinfo" +#define CMDSTR_GETPARAMS "getparams" +#define CMDSTR_SETPARAMS "setparams" + +static __inline__ void +S_print_char_array(UInt8 * params, int n_params) +{ + int i; + + for (i = 0; i < n_params; i++) { + if (i == 0) + printf("%d", params[i]); + else + printf(", %d", params[i]); + } + return; +} + +void +usage(char * prog) +{ + printf("%s " CMDSTR_GETOPTION " [ ]\n" + "%s " CMDSTR_LEASE " \n" + "%s " CMDSTR_GETPARAMS " \n" + "%s " CMDSTR_SETPARAMS " [ [ ] ... [ ] ] ]\n" + "where:\n" + " : service ID string | \"\"\n" + " : DHCP/BOOTP option code\n" + " (e.g. 1 == subnet mask, 3 == router, 6 = dns, 15 = domain)\n" + " : type of option: string, ip\n" + " : application id (e.g. com.apple.ntpd, com.thursby.Dave)\n", + prog, prog, prog, prog); + exit(0); +} + +static void +dump_gregorian_date(CFGregorianDate d) +{ + printf("%d/%d/%d %02d:%02d:%02d\n", + (int)d.year, d.month, d.day, d.hour, d.minute, (int)d.second); + return; +} + +static void +show_date(CFAbsoluteTime t) +{ + CFGregorianDate d; + static CFTimeZoneRef tz = NULL; + + if (tz == NULL) { + tz = CFTimeZoneCopySystem(); + } + + d = CFAbsoluteTimeGetGregorianDate(t, tz); + dump_gregorian_date(d); + return; +} + +#define IP_FORMAT "%d.%d.%d.%d" +#define IP_CH(ip, i) (((u_char *)(ip))[i]) +#define IP_LIST(ip) IP_CH(ip,0),IP_CH(ip,1),IP_CH(ip,2),IP_CH(ip,3) + +typedef enum { + command_none_e, + command_getoption_e, + command_lease_e, + command_setparams_e, + command_getparams_e, +} command_t; + +int +main(int argc, char * argv[]) +{ + CFStringRef app_id; + command_t command = command_none_e; + char * command_str; + CFIndex count; + CFDictionaryRef info; + UInt8 * params; + CFStringRef serviceID = NULL; + + command_str = argv[1]; + if (argc < 2) + usage(argv[0]); + if (strcmp(command_str, CMDSTR_GETOPTION) == 0) { + if (argc < 4 || argc > 5) { + usage(argv[0]); + } + command = command_getoption_e; + } + else if (strcmp(command_str, CMDSTR_LEASE) == 0) { + if (argc != 3) { + usage(argv[0]); + } + command = command_lease_e; + } + else if (strcmp(command_str, CMDSTR_SETPARAMS) == 0) { + command = command_setparams_e; + if (argc < 3) { + usage(argv[0]); + } + } + else if (strcmp(command_str, CMDSTR_GETPARAMS) == 0) { + command = command_getparams_e; + if (argc != 3) { + usage(argv[0]); + } + } + else { + usage(argv[0]); + } + + switch (command) { + case command_getoption_e: { + UInt8 code; + char * code_str; + CFDataRef option; + boolean_t printed = FALSE; + CFIndex len; + char * type = NULL; + + if (argv[2][0]) { + serviceID = CFStringCreateWithFormat(NULL, NULL, + CFSTR("%s"), argv[2]); + } + + info = SCDynamicStoreCopyDHCPInfo(NULL, serviceID); + if (info == NULL) { + exit(1); + } + + code_str = argv[3]; + if (argc > 4) { + type = argv[4]; + } + code = atoi(code_str); + + option = DHCPInfoGetOptionData(info, code); + if (option == NULL) { + exit(1); + } + len = CFDataGetLength(option); + if (type) { + printed = TRUE; + if (strcmp(type, "ip") == 0) { + int i = 0; + const void * ptr = CFDataGetBytePtr(option); + + while (len >= 4) { + if (i == 0) { + printf(IP_FORMAT, IP_LIST(ptr)); + } + else { + printf(" " IP_FORMAT, IP_LIST(ptr)); + } + i++; + len -= 4; + ptr += 4; + } + printf("\n"); + } + else if (strcmp(type, "string") == 0) { + printf("%.*s\n", (int)len, (char *)CFDataGetBytePtr(option)); + } + else { + printed = FALSE; + } + } + if (printed == FALSE) { + print_data((void *)CFDataGetBytePtr(option), len); + } + if (serviceID) + CFRelease(serviceID); + CFRelease(info); + break; + } + case command_lease_e: { + CFDateRef start; + + if (argv[2][0]) { + serviceID = CFStringCreateWithFormat(NULL, NULL, + CFSTR("%s"), argv[2]); + } + + info = SCDynamicStoreCopyDHCPInfo(NULL, serviceID); + if (info == NULL) { + exit(1); + } + start = DHCPInfoGetLeaseStartTime(info); + + if (start) { + CFDataRef option; + int32_t lease; + +#define OPTION_LEASE_TIME 51 +#define SERVER_ID 54 + option = DHCPInfoGetOptionData(info, OPTION_LEASE_TIME); + if (option == NULL) { + fprintf(stderr, "what, no lease time?\n"); + exit(1); + } + printf("Lease start: "); + show_date(CFDateGetAbsoluteTime(start)); + lease = ntohl(*((int32_t *)CFDataGetBytePtr(option))); + if (lease == 0xffffffff) { + printf("Lease is infinite\n"); + } + else { + printf("Lease expires: "); + show_date(lease + CFDateGetAbsoluteTime(start)); + } + option = DHCPInfoGetOptionData(info, SERVER_ID); + if (option) { + printf("Server IP: " IP_FORMAT "\n", + IP_LIST(CFDataGetBytePtr(option))); + } + } + else { + printf("no lease\n"); + } + if (serviceID) + CFRelease(serviceID); + CFRelease(info); + break; + } + case command_getparams_e: { + app_id = CFStringCreateWithFormat(NULL, NULL, + CFSTR("%s"), argv[2]); + params = DHCPClientPreferencesCopyApplicationOptions(app_id, &count); + if (params) { + printf("%s params = {", argv[2]); + S_print_char_array(params, count); + printf("}\n"); + free(params); + } + break; + } + case command_setparams_e: { + int count = 0; + UInt8 * options = NULL; + + if (argc > 3) { + int i; + + count = argc - 3; + options = malloc(count); + if (options == NULL) { + fprintf(stderr, "malloc failed %s\n", + strerror(errno)); + exit(1); + } + for (i = 0; i < count; i++) { + options[i] = atoi(argv[3 + i]); + } + } + app_id = CFStringCreateWithFormat(NULL, NULL, + CFSTR("%s"), argv[2]); + if (DHCPClientPreferencesSetApplicationOptions(app_id, options, + count) == FALSE) { + printf("operation failed\n"); + } + if (options) { + free(options); + } + break; + } + default: + break; + } + exit(0); + return(0); +} +#endif TEST_DHCPCLIENT_PREFERENCES + diff --git a/SystemConfiguration.fproj/DHCPClientPreferences.h b/SystemConfiguration.fproj/DHCPClientPreferences.h new file mode 100644 index 0000000..725f4d3 --- /dev/null +++ b/SystemConfiguration.fproj/DHCPClientPreferences.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _DHCPCLIENTPREFERENCES_H +#define _DHCPCLIENTPREFERENCES_H + +#include +#include + +/*! + @header DHCPClientPreferences.h + */ + +__BEGIN_DECLS + +/*! + @function DHCPClientPreferencesSetApplicationOptions + @discussion Updates the DHCP client preferences to include the + given list of options for the given "applicationID". + @param applicationID The application's preference ID, for example: + "com.apple.SystemPreferences". + @param options An array of 8-bit values containing the + DHCP option codes (see RFC 2132) for this applicationID. + A NULL value will clear the list of options for this + application ID. + @param count The number of elements in "options". + @result TRUE if the operation succeeded, FALSE otherwise. + */ + +Boolean +DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID, + UInt8 * options, + CFIndex count); + +/*! + @function DHCPClientPreferencesCopyApplicationOptions + @discussion Copies the requested DHCP options for the + given "applicationID". + @param applicationID The application's preference ID, for example + "com.apple.SystemPreferences". + @param count The number of elements in the returned array. + @result The list of options for the given "applicationID", or + NULL if no options are defined or an error occurred. + + When done, use free() to release a non-NULL return value. + */ + +UInt8 * +DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID, + CFIndex * count); + +__END_DECLS + +#endif /* _DHCPCLIENTPREFERENCES_H */ diff --git a/SystemConfiguration.fproj/Makefile b/SystemConfiguration.fproj/Makefile index 20f1e2c..7235655 100644 --- a/SystemConfiguration.fproj/Makefile +++ b/SystemConfiguration.fproj/Makefile @@ -12,21 +12,28 @@ NAME = SystemConfiguration PROJECTVERSION = 2.8 PROJECT_TYPE = Framework -HFILES = SystemConfiguration.h config_types.h SCD.h SCDKeys.h\ - SCDPrivate.h SCP.h SCPPrivate.h SCPPath.h SCDConsoleUser.h\ - SCDHostName.h SCNetwork.h ppp_msg.h ppp.h - -CFILES = SCD.c SCDKeys.c SCDPrivate.c SCDHandle.c SCDOpen.c\ - SCDClose.c SCDLock.c SCDUnlock.c SCDList.c SCDAdd.c\ - SCDAddSession.c SCDGet.c SCDSet.c SCDRemove.c SCDTouch.c\ +HFILES = SystemConfiguration.h SCPrivate.h SCDPlugin.h config_types.h\ + SCDynamicStoreInternal.h SCDynamicStore.h\ + SCDynamicStorePrivate.h SCDynamicStoreKey.h\ + SCDynamicStoreCopySpecific.h SCDynamicStoreSetSpecificPrivate.h\ + SCPreferencesInternal.h SCPreferences.h SCPreferencesPrivate.h\ + SCPreferencesPath.h SCPreferencesSetSpecific.h SCNetwork.h\ + SCValidation.h ppp_msg.h ppp.h v1Compatibility.h SCD.h\ + SCDKeys.h SCP.h SCPPath.h SCDConsoleUser.h SCDHostName.h\ + DHCPClientPreferences.h SCDynamicStoreCopyDHCPInfo.h + +CFILES = SCD.c SCDKeys.c SCDPrivate.c SCDOpen.c SCDLock.c SCDUnlock.c\ + SCDList.c SCDAdd.c SCDAddSession.c SCDGet.c SCDSet.c\ + SCDRemove.c SCDTouch.c SCDNotify.c SCDNotifierSetKeys.c\ SCDNotifierList.c SCDNotifierAdd.c SCDNotifierRemove.c\ SCDNotifierGetChanges.c SCDNotifierWait.c\ SCDNotifierInformViaCallback.c SCDNotifierInformViaMachPort.c\ SCDNotifierInformViaFD.c SCDNotifierInformViaSignal.c\ - SCDNotifierCancel.c SCDSnapshot.c SCP.c SCPOpen.c SCPClose.c\ - SCPLock.c SCPUnlock.c SCPList.c SCPGet.c SCPAdd.c SCPSet.c\ - SCPRemove.c SCPCommit.c SCPApply.c SCPPath.c SCDConsoleUser.c\ - SCDHostName.c SCNetwork.c ppp.c + SCDNotifierCancel.c SCDSnapshot.c SCP.c SCPOpen.c SCPLock.c\ + SCPUnlock.c SCPList.c SCPGet.c SCPAdd.c SCPSet.c SCPRemove.c\ + SCPCommit.c SCPApply.c SCPPath.c SCDConsoleUser.c\ + SCDHostName.c SCNetwork.c SCProxies.c ppp.c v1Compatibility.c\ + DHCP.c OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\ h.template config.defs genSCPreferences.c CustomInfo.plist @@ -37,7 +44,7 @@ CURRENTLY_ACTIVE_VERSION = YES DEPLOY_WITH_VERSION_NAME = A CODE_GEN_STYLE = DYNAMIC MAKEFILE = framework.make -NEXTSTEP_INSTALLDIR = $(SYSTEM_LIBRARY_DIR)/PrivateFrameworks +NEXTSTEP_INSTALLDIR = $(SYSTEM_LIBRARY_DIR)/Frameworks WINDOWS_INSTALLDIR = /Library/Frameworks PDO_UNIX_INSTALLDIR = /Library/Frameworks LIBS = @@ -45,13 +52,22 @@ DEBUG_LIBS = $(LIBS) PROF_LIBS = $(LIBS) +NEXTSTEP_PB_CFLAGS = -DUSE_SYSTEMCONFIGURATION_PUBLIC_APIS FRAMEWORKS = -framework CoreFoundation -PUBLIC_HEADERS = SystemConfiguration.h SCD.h SCDKeys.h SCP.h SCPPath.h\ - SCDConsoleUser.h SCDHostName.h SCNetwork.h - -PROJECT_HEADERS = SystemConfiguration.h config_types.h SCD.h\ - SCDPrivate.h SCP.h SCPPrivate.h SCPPath.h\ - SCDConsoleUser.h SCDHostName.h SCNetwork.h +PUBLIC_HEADERS = SystemConfiguration.h SCDynamicStore.h\ + SCDynamicStoreKey.h SCDynamicStoreCopySpecific.h\ + SCPreferences.h SCPreferencesPath.h\ + SCPreferencesSetSpecific.h SCNetwork.h + +PROJECT_HEADERS = SystemConfiguration.h SCPrivate.h config_types.h\ + SCDynamicStoreInternal.h SCDynamicStore.h\ + SCDynamicStorePrivate.h SCDynamicStoreKey.h\ + SCDynamicStoreCopySpecific.h\ + SCDynamicStoreSetSpecificPrivate.h\ + SCPreferencesInternal.h SCPreferences.h\ + SCPreferencesPrivate.h SCPreferencesPath.h\ + SCPreferencesSetSpecific.h SCNetwork.h SCValidation.h\ + v1Compatibility.h diff --git a/SystemConfiguration.fproj/Makefile.postamble b/SystemConfiguration.fproj/Makefile.postamble index 888849f..575e099 100644 --- a/SystemConfiguration.fproj/Makefile.postamble +++ b/SystemConfiguration.fproj/Makefile.postamble @@ -107,13 +107,16 @@ before_installhdrs: $(OFILE_DIR) $(OFILE_DIR)/genSCPreferences: genSCPreferences.o $(CC) -o $@ $(ARCHITECTURE_FLAGS) $< -SCPreferences.h: $(OFILE_DIR)/genSCPreferences +SCSchemaDefinitions.h: $(OFILE_DIR)/genSCPreferences $(CD) $(SFILE_DIR) && $(OFILE_DIR)/genSCPreferences header > $@ -SCPreferences.c: $(OFILE_DIR)/genSCPreferences +SCSchemaDefinitions.c: $(OFILE_DIR)/genSCPreferences $(CD) $(SFILE_DIR) && $(OFILE_DIR)/genSCPreferences cfile > $@ genSCFiles: cc -o /tmp/genSCFiles genSCPreferences.c -framework CoreFoundation - /tmp/genSCFiles header > /tmp/SCPreferences.h - /tmp/genSCFiles cfile > /tmp/SCPreferences.c + /tmp/genSCFiles header > /tmp/SCSchemaDefinitions.h + /tmp/genSCFiles cfile > /tmp/SCSchemaDefinitions.c + +dhcp: DHCP.c + cc -Wall -DUSE_SYSTEMCONFIGURATION_PUBLIC_APIS -DTEST_DHCPCLIENT_PREFERENCES -g -o dhcp DHCP.c -framework CoreFoundation -framework SystemConfiguration diff --git a/SystemConfiguration.fproj/Makefile.preamble b/SystemConfiguration.fproj/Makefile.preamble index cb94833..ac3fc04 100644 --- a/SystemConfiguration.fproj/Makefile.preamble +++ b/SystemConfiguration.fproj/Makefile.preamble @@ -138,22 +138,45 @@ OTHER_GENERATED_OFILES = $(VERS_OFILE) # Additional flags for MiG generated files OTHER_PROJECT_HEADERS += config.defs config.h + +OTHER_PRIVATE_HEADERS += SCPrivate.h +OTHER_PRIVATE_HEADERS += SCDynamicStorePrivate.h +OTHER_PRIVATE_HEADERS += SCDynamicStoreSetSpecificPrivate.h +OTHER_PRIVATE_HEADERS += SCPreferencesPrivate.h +OTHER_PRIVATE_HEADERS += SCValidation.h +OTHER_PRIVATE_HEADERS += SCDPlugin.h +OTHER_PRIVATE_HEADERS += SCDynamicStoreCopyDHCPInfo.h +OTHER_PRIVATE_HEADERS += DHCPClientPreferences.h + +# +# XXX INSTALL V1 COMPATIBILITY HEADERS XXX +# +OTHER_PRIVATE_HEADERS += v1Compatibility.h +OTHER_PRIVATE_HEADERS += SCD.h +OTHER_PRIVATE_HEADERS += SCDKeys.h +OTHER_PRIVATE_HEADERS += SCP.h +OTHER_PRIVATE_HEADERS += SCPPath.h +OTHER_PRIVATE_HEADERS += SCDConsoleUser.h +OTHER_PRIVATE_HEADERS += SCDHostName.h + +# +# MiG generated files +# OTHER_OFILES += configUser.o # Additional options to create generated headers, source BEFORE_INSTALLHDRS = before_installhdrs OTHER_SOURCEFILES += genSCPreferences.c -OTHER_GENERATED_SRCFILES += SCPreferences.h SCPreferences.c -OTHER_PUBLIC_HEADERS += SCPreferences.h -OTHER_OFILES += SCPreferences.o - -# Specify framework initialization code -OTHER_LDFLAGS += -Wl,-init,___Initialize +OTHER_GENERATED_SRCFILES += SCSchemaDefinitions.h SCSchemaDefinitions.c +OTHER_PUBLIC_HEADERS += SCSchemaDefinitions.h +OTHER_OFILES += SCSchemaDefinitions.o # Additional build flags ifeq "$(PLATFORM_OS)" "macos" +ifneq "$(RC_RELEASE)" "Darwin" APPLE_INTERNAL_DIR ?= /AppleInternal APPLE_INTERNAL_DEVELOPER_DIR ?= /AppleInternal/Developer OTHER_LDFLAGS += -seg_addr_table $(APPLE_INTERNAL_DEVELOPER_DIR)/seg_addr_table SECTORDER_FLAGS = -sectorder __TEXT __text $(APPLE_INTERNAL_DIR)/OrderFiles/SystemConfiguration.order endif +endif diff --git a/SystemConfiguration.fproj/PB.project b/SystemConfiguration.fproj/PB.project index f132d48..8c1c394 100644 --- a/SystemConfiguration.fproj/PB.project +++ b/SystemConfiguration.fproj/PB.project @@ -7,26 +7,39 @@ FRAMEWORKSEARCH = (); H_FILES = ( SystemConfiguration.h, + SCPrivate.h, + SCDPlugin.h, config_types.h, + SCDynamicStoreInternal.h, + SCDynamicStore.h, + SCDynamicStorePrivate.h, + SCDynamicStoreKey.h, + SCDynamicStoreCopySpecific.h, + SCDynamicStoreSetSpecificPrivate.h, + SCPreferencesInternal.h, + SCPreferences.h, + SCPreferencesPrivate.h, + SCPreferencesPath.h, + SCPreferencesSetSpecific.h, + SCNetwork.h, + SCValidation.h, + ppp_msg.h, + ppp.h, + v1Compatibility.h, SCD.h, SCDKeys.h, - SCDPrivate.h, SCP.h, - SCPPrivate.h, SCPPath.h, SCDConsoleUser.h, SCDHostName.h, - SCNetwork.h, - ppp_msg.h, - ppp.h + DHCPClientPreferences.h, + SCDynamicStoreCopyDHCPInfo.h ); OTHER_LINKED = ( SCD.c, SCDKeys.c, SCDPrivate.c, - SCDHandle.c, SCDOpen.c, - SCDClose.c, SCDLock.c, SCDUnlock.c, SCDList.c, @@ -36,6 +49,8 @@ SCDSet.c, SCDRemove.c, SCDTouch.c, + SCDNotify.c, + SCDNotifierSetKeys.c, SCDNotifierList.c, SCDNotifierAdd.c, SCDNotifierRemove.c, @@ -49,7 +64,6 @@ SCDSnapshot.c, SCP.c, SCPOpen.c, - SCPClose.c, SCPLock.c, SCPUnlock.c, SCPList.c, @@ -63,7 +77,10 @@ SCDConsoleUser.c, SCDHostName.c, SCNetwork.c, - ppp.c + SCProxies.c, + ppp.c, + v1Compatibility.c, + DHCP.c ); OTHER_SOURCES = ( Makefile.preamble, @@ -78,24 +95,31 @@ PRECOMPILED_HEADERS = (); PROJECT_HEADERS = ( SystemConfiguration.h, + SCPrivate.h, config_types.h, - SCD.h, - SCDPrivate.h, - SCP.h, - SCPPrivate.h, - SCPPath.h, - SCDConsoleUser.h, - SCDHostName.h, - SCNetwork.h + SCDynamicStoreInternal.h, + SCDynamicStore.h, + SCDynamicStorePrivate.h, + SCDynamicStoreKey.h, + SCDynamicStoreCopySpecific.h, + SCDynamicStoreSetSpecificPrivate.h, + SCPreferencesInternal.h, + SCPreferences.h, + SCPreferencesPrivate.h, + SCPreferencesPath.h, + SCPreferencesSetSpecific.h, + SCNetwork.h, + SCValidation.h, + v1Compatibility.h ); PUBLIC_HEADERS = ( SystemConfiguration.h, - SCD.h, - SCDKeys.h, - SCP.h, - SCPPath.h, - SCDConsoleUser.h, - SCDHostName.h, + SCDynamicStore.h, + SCDynamicStoreKey.h, + SCDynamicStoreCopySpecific.h, + SCPreferences.h, + SCPreferencesPath.h, + SCPreferencesSetSpecific.h, SCNetwork.h ); SUBPROJECTS = (); @@ -103,7 +127,8 @@ LANGUAGE = English; MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; - NEXTSTEP_INSTALLDIR = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + NEXTSTEP_COMPILEROPTIONS = "-DUSE_SYSTEMCONFIGURATION_PUBLIC_APIS"; + NEXTSTEP_INSTALLDIR = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; diff --git a/SystemConfiguration.fproj/SCD.c b/SystemConfiguration.fproj/SCD.c index 169af6b..4a480dc 100644 --- a/SystemConfiguration.fproj/SCD.c +++ b/SystemConfiguration.fproj/SCD.c @@ -20,211 +20,471 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ +#include +#include +#include -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +#include +#include +#include "SCDynamicStoreInternal.h" +#include "config.h" /* MiG generated file */ -static _SCDFlags globalFlags = { - FALSE /* debug */, - FALSE /* verbose */, - FALSE /* useSyslog */, - FALSE /* isLocked */, - TRUE /* useCFRunLoop */, +/* framework variables */ +Boolean _sc_debug = FALSE; /* TRUE if debugging enabled */ +Boolean _sc_verbose = FALSE; /* TRUE if verbose logging enabled */ +Boolean _sc_log = TRUE; /* TRUE if SCLog() output goes to syslog */ + +static const struct sc_errmsg { + int status; + char *message; +} sc_errmsgs[] = { + { kSCStatusAccessError, "Permission denied" }, + { kSCStatusFailed, "Failed!" }, + { kSCStatusInvalidArgument, "Invalid argument" }, + { kSCStatusKeyExists, "Key already defined" }, + { kSCStatusLocked, "Lock already held" }, + { kSCStatusNeedLock, "Lock required for this operation" }, + { kSCStatusNoStoreServer, "Configuration daemon not (no longer) available" }, + { kSCStatusNoStoreSession, "Configuration daemon session not active" }, + { kSCStatusNoConfigFile, "Configuration file not found" }, + { kSCStatusNoKey, "No such key" }, + { kSCStatusNoLink, "No such link" }, + { kSCStatusNoPrefsSession, "Preference session not active" }, + { kSCStatusNotifierActive, "Notifier is currently active" }, + { kSCStatusOK, "Success!" }, + { kSCStatusPrefsBusy, "Configuration daemon busy" }, + { kSCStatusReachabilityUnknown, "Network reachability cannot be determined" }, + { kSCStatusStale, "Write attempted on stale version of object" }, }; +#define nSC_ERRMSGS (sizeof(sc_errmsgs)/sizeof(struct sc_errmsg)) -static boolean_t isSCDServer = FALSE; - -static const struct scd_errmsg { - SCDStatus status; - char *message; -} scd_errmsgs[] = { - { SCD_OK, "Success!" }, - { SCD_NOSESSION, "Configuration daemon session not active" }, - { SCD_NOSERVER, "Configuration daemon not (no longer) available" }, - { SCD_LOCKED, "Lock already held" }, - { SCD_NEEDLOCK, "Lock required for this operation" }, - { SCD_EACCESS, "Permission denied (must be root to obtain lock)" }, - { SCD_NOKEY, "No such key" }, - { SCD_EXISTS, "Data associated with key already defined" }, - { SCD_STALE, "Write attempted on stale version of object" }, - { SCD_INVALIDARGUMENT, "Invalid argument" }, - { SCD_NOTIFIERACTIVE, "Notifier is currently active" }, - { SCD_FAILED, "Failed!" } -}; -#define nSCD_ERRMSGS (sizeof(scd_errmsgs)/sizeof(struct scd_errmsg)) +#define USE_SCCOPYDESCRIPTION +#ifdef USE_SCCOPYDESCRIPTION -int -SCDOptionGet(SCDSessionRef session, const int option) -{ - _SCDFlags *theFlags = &globalFlags; - int value = 0; +// from +extern CFStringRef _CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc, CFStringRef (*copyDescFunc)(void *, CFDictionaryRef), CFDictionaryRef formatOptions, CFStringRef format, va_list arguments); - if (session != NULL) { - theFlags = &((SCDSessionPrivateRef)session)->flags; +static CFStringRef +_SCCopyDescription(void *info, CFDictionaryRef formatOptions) +{ + CFMutableDictionaryRef nFormatOptions; + CFStringRef prefix1; + CFStringRef prefix2; + CFTypeID type = CFGetTypeID(info); + + if (!formatOptions || + !CFDictionaryGetValueIfPresent(formatOptions, CFSTR("PREFIX1"), (void **)&prefix1)) { + prefix1 = CFSTR(""); } - switch (option) { - - /* session dependent flags */ + if (type == CFStringGetTypeID()) { + return CFStringCreateWithFormat(NULL, + formatOptions, + CFSTR("%@%@"), + prefix1, + info); + } - case kSCDOptionDebug : - value = theFlags->debug; - break; + if (type == CFBooleanGetTypeID()) { + return CFStringCreateWithFormat(NULL, + formatOptions, + CFSTR("%@%s"), + prefix1, + CFBooleanGetValue(info) ? "TRUE" : "FALSE"); + } - case kSCDOptionVerbose : - value = theFlags->verbose; - break; + if (type == CFDataGetTypeID()) { + const u_int8_t *data; + CFIndex dataLen; + CFIndex i; + CFMutableStringRef str; - case kSCDOptionIsLocked : - value = theFlags->isLocked; - break; + str = CFStringCreateMutable(NULL, 0); + CFStringAppendFormat(str, formatOptions, CFSTR("%@ 0x"), prefix1); - case kSCDOptionUseSyslog : - value = theFlags->useSyslog; - break; + data = CFDataGetBytePtr(info); + dataLen = CFDataGetLength(info); + for (i = 0; i < dataLen; i++) { + CFStringAppendFormat(str, NULL, CFSTR("%02x"), data[i]); + } - case kSCDOptionUseCFRunLoop : - value = theFlags->useCFRunLoop; - break; + return str; + } - /* session independent flags */ + if (type == CFNumberGetTypeID()) { + return CFStringCreateWithFormat(NULL, + formatOptions, + CFSTR("%@%@"), + prefix1, + info); + } - case kSCDOptionIsServer : - value = isSCDServer; - break; + if (type == CFDateGetTypeID()) { + CFGregorianDate gDate; + CFStringRef str; + CFTimeZoneRef tZone; + + tZone = CFTimeZoneCopySystem(); + gDate = CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime(info), tZone); + str = CFStringCreateWithFormat(NULL, + formatOptions, + CFSTR("%@%02d/%02d/%04d %02d:%02d:%02.0f %@"), + prefix1, + gDate.month, + gDate.day, + gDate.year, + gDate.hour, + gDate.minute, + gDate.second, + CFTimeZoneGetName(tZone)); + CFRelease(tZone); + return str; } - return value; -} + if (!formatOptions || + !CFDictionaryGetValueIfPresent(formatOptions, CFSTR("PREFIX2"), (void **)&prefix2)) { + prefix2 = CFStringCreateCopy(NULL, prefix1); + } + if (formatOptions) { + nFormatOptions = CFDictionaryCreateMutableCopy(NULL, 0, formatOptions); + } else { + nFormatOptions = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } -void -SCDOptionSet(SCDSessionRef session, int option, const int value) -{ - _SCDFlags *theFlags = &globalFlags; + if (type == CFArrayGetTypeID()) { + void **elements; + CFIndex i; + CFIndex nElements; + CFMutableStringRef str; + + str = CFStringCreateMutable(NULL, 0); + CFStringAppendFormat(str, formatOptions, CFSTR("%@ {"), prefix1); + + nElements = CFArrayGetCount(info); + elements = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + CFArrayGetValues(info, CFRangeMake(0, nElements), elements); + for (i=0; iflags; + CFRelease(nFormatOptions); + return str; } - switch (option) { + if (type == CFDictionaryGetTypeID()) { + void **keys; + CFIndex i; + CFIndex nElements; + CFMutableStringRef nPrefix1; + CFMutableStringRef nPrefix2; + CFMutableStringRef str; + void **values; + + str = CFStringCreateMutable(NULL, 0); + CFStringAppendFormat(str, formatOptions, CFSTR("%@ {"), prefix1); + + nElements = CFDictionaryGetCount(info); + keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + CFDictionaryGetKeysAndValues(info, keys, values); + for (i=0; idebug = value; - break; + { + CFStringRef cfStr; + CFStringRef str; + + cfStr = CFCopyDescription(info); + str = CFStringCreateWithFormat(NULL, + formatOptions, + CFSTR("%@%@"), + prefix1, + cfStr); + CFRelease(cfStr); + return str; + } +} - case kSCDOptionVerbose : - theFlags->verbose = value; - break; +#endif /* USE_SCCOPYDESCRIPTION */ - case kSCDOptionIsLocked : - theFlags->isLocked = value; - break; - case kSCDOptionUseSyslog : - theFlags->useSyslog = value; - break; +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - case kSCDOptionUseCFRunLoop : - theFlags->useCFRunLoop = value; - break; - /* session independent flags */ +__private_extern__ void +__SCLog(int level, CFStringRef str) +{ + CFArrayRef lines; - case kSCDOptionIsServer : - isSCDServer = value; - break; + lines = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR("\n")); + if (lines) { + int i; + + pthread_mutex_lock(&lock); + for (i=0; i LOG_NOTICE) ? stderr : stdout; CFDataRef line; - int i; - - if ((LOG_PRI(level) == LOG_DEBUG) && !SCDOptionGet(session, kSCDOptionVerbose)) { - /* it's a debug message and we haven't requested verbose logging */ - return; - } - - pthread_mutex_lock(&lock); - for (i=0; i LOG_NOTICE) ? stderr : stdout; + CFStringRef newString; + + /* add a new-line */ + newString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@\n"), resultString); + __SCPrint(f, newString); + CFRelease(newString); + } CFRelease(resultString); + return; } void -SCDLog(int level, CFStringRef formatString, ...) +SCPrint(Boolean condition, FILE *stream, CFStringRef formatString, ...) { va_list argList; CFStringRef resultString; - CFArrayRef lines; + + if (!condition) { + return; + } va_start(argList, formatString); +#ifdef USE_SCCOPYDESCRIPTION + resultString = _CFStringCreateWithFormatAndArgumentsAux(NULL, + _SCCopyDescription, + NULL, + formatString, + argList); +#else /* USE_SCCOPYDESCRIPTION */ resultString = CFStringCreateWithFormatAndArguments(NULL, NULL, formatString, argList); +#endif /* !USE_SCCOPYDESCRIPTION */ va_end(argList); - lines = CFStringCreateArrayBySeparatingStrings(NULL, resultString, CFSTR("\n")); - _SCDLog(NULL, level, lines); - CFRelease(lines); + __SCPrint(stream, resultString); CFRelease(resultString); + return; +} + + +typedef struct { + int _sc_error; +} __SCThreadSpecificData, *__SCThreadSpecificDataRef; + + +static pthread_once_t tsKeyInitialized = PTHREAD_ONCE_INIT; +static pthread_key_t tsDataKey = NULL; + + +static void +__SCThreadSpecificDataFinalize(void *arg) +{ + __SCThreadSpecificDataRef tsd = (__SCThreadSpecificDataRef)arg; + + if (!tsd) return; + + CFAllocatorDeallocate(kCFAllocatorSystemDefault, tsd); + return; +} + + +static void +__SCThreadSpecificKeyInitialize() +{ + pthread_key_create(&tsDataKey, __SCThreadSpecificDataFinalize); + return; +} + + +void +_SCErrorSet(int error) +{ + __SCThreadSpecificDataRef tsd; + + pthread_once(&tsKeyInitialized, __SCThreadSpecificKeyInitialize); + + tsd = pthread_getspecific(tsDataKey); + if (!tsd) { + tsd = CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(__SCThreadSpecificData), 0); + bzero(tsd, sizeof(__SCThreadSpecificData)); + pthread_setspecific(tsDataKey, tsd); + } + + tsd->_sc_error = error; + return; +} + + +int +SCError() +{ + __SCThreadSpecificDataRef tsd; + + pthread_once(&tsKeyInitialized, __SCThreadSpecificKeyInitialize); + + tsd = pthread_getspecific(tsDataKey); + return tsd ? tsd->_sc_error : kSCStatusOK; } const char * -SCDError(SCDStatus status) +SCErrorString(int status) { int i; - for (i = 0; i < nSCD_ERRMSGS; i++) { - if (scd_errmsgs[i].status == status) { - return scd_errmsgs[i].message; + for (i = 0; i < nSC_ERRMSGS; i++) { + if (sc_errmsgs[i].status == status) { + return sc_errmsgs[i].message; } } - return "(unknown error)"; + + if ((status > 0) && (status <= ELAST)) { + return strerror(status); + } + + return mach_error_string(status); } diff --git a/SystemConfiguration.fproj/SCD.h b/SystemConfiguration.fproj/SCD.h index d580665..9a2ef16 100644 --- a/SystemConfiguration.fproj/SCD.h +++ b/SystemConfiguration.fproj/SCD.h @@ -23,609 +23,14 @@ #ifndef _SCD_H #define _SCD_H -#include -#include -#include -#include -#include - - -/*! - @header SCD.h - The SystemConfiguration framework provides access to the data used to configure a running system. The APIs provided by this framework communicate with the "configd" daemon. - -The "configd" daemon manages a "cache" reflecting the desired configuration settings as well as the current state of the system. The daemon provides a notification mechanism for user-level processes which need to be aware of changes made to the "cache" data. Lastly, the daemon loads a number of bundles(or plug-ins) which monitor low-level kernel events and, via a set of policy modules, keep this cached data up to date. - -The "configd" daemon also provides an address space/task/process which can be used by other CFRunLoop based functions which would otherwise require their own process/daemon for execution. - - */ - - -/*! - @enum SCDStatus - @discussion Returned status codes. - @constant SCD_OK Success - @constant SCD_NOSESSION Configuration daemon session not active - @constant SCD_NOSERVER Configuration daemon not (no longer) available - @constant SCD_LOCKED Lock already held - @constant SCD_NEEDLOCK Lock required for this operation - @constant SCD_EACCESS Permission denied (must be root to obtain lock) - @constant SCD_NOKEY No such key - @constant SCD_EXISTS Data associated with key already defined - @constant SCD_STALE Write attempted on stale version of object - @constant SCD_INVALIDARGUMENT Invalid argument - @constant SCD_NOTIFIERACTIVE Notifier is currently active - @constant SCD_FAILED Generic error - */ -typedef enum { - SCD_OK = 0, /* Success */ - SCD_NOSESSION = 1, /* Configuration daemon session not active */ - SCD_NOSERVER = 2, /* Configuration daemon not (no longer) available */ - SCD_LOCKED = 3, /* Lock already held */ - SCD_NEEDLOCK = 4, /* Lock required for this operation */ - SCD_EACCESS = 5, /* Permission denied (must be root to obtain lock) */ - SCD_NOKEY = 6, /* No such key */ - SCD_EXISTS = 7, /* Data associated with key already defined */ - SCD_STALE = 8, /* Write attempted on stale version of object */ - SCD_INVALIDARGUMENT = 9, /* Invalid argument */ - SCD_NOTIFIERACTIVE = 10, /* Notifier is currently active */ - SCD_FAILED = 9999 /* Generic error */ -} SCDStatus; - - -/*! - @typedef SCDSessionRef - @discussion This is the type of a handle to an open "session" with the system - configuration daemon. - */ -typedef const struct __SCDSession * SCDSessionRef; - -/*! - @typedef SCDHandleRef - @discussion This is the type of a handle to data being retrieved from or to be - stored by the system configuration daemon. - */ -typedef const struct __SCDHandle * SCDHandleRef; - - -/*! - @typedef SCDCallbackRoutine_t - @discussion Type of the callback function used by the SCDNotifierInformViaCallback() - function. - @param session The session handle. - @param callback_argument The user-defined argument to be passed to the callback - function. - */ -typedef boolean_t (*SCDCallbackRoutine_t) (SCDSessionRef session, - void *callback_argument); - - -/*! - @enum SCDKeyOption - @discussion Used with the SCDList() and SCDNotifierAdd() functions to describe - the CFStringRef argument. - @constant kSCDRegexKey Specifies that the key consists of a regular expression. - */ -typedef enum { - kSCDRegexKey = 0100000, /* pattern string is a regular expression */ -} SCDKeyOption; - - -/*! - @enum SCDOption - @discussion Options which determine the run-time processing of the system - configuration framework functions. - @constant kSCDOptionDebug Enable debugging - @constant kSCDOptionVerbose Enable verbose logging - @constant kSCDOptionUseSyslog Use syslog(3) for log messages - @constant kSCDOptionUseCFRunLoop Calling application is CFRunLoop() based - */ -typedef enum { - kSCDOptionDebug = 0, /* Enable debugging */ - kSCDOptionVerbose = 1, /* Enable verbose logging */ - kSCDOptionUseSyslog = 2, /* Use syslog(3) for log messages */ - kSCDOptionUseCFRunLoop = 3, /* Calling application is CFRunLoop() based */ -} SCDOption; - - -/* - * "configd" loadable bundle / plug-in options - */ - -/*! - @typedef SCDBundleStartRoutine_t - @discussion Type of the start() initializatioin function which will be called - after all plug-ins have been loaded. This function should initialize any - variables, open any sessions with "configd", and register any needed - notifications. - @param bundlePath The path name associated with the plug-in / bundle. - @param bundleName The name of the plug-in / bundle. - */ -typedef void (*SCDBundleStartRoutine_t) (const char *bundlePath, - const char *bundleName); - -/*! - @typedef SCDBundlePrimeRoutine_t - @discussion Type of the prime() initializatioin function which will be - called after all plug-ins have executed their start() function but - before the main plug-in run loop is started. This function should - be used to initialize any configuration information and/or state - in the cache. - */ -typedef void (*SCDBundlePrimeRoutine_t) (); - -#define BUNDLE_DIRECTORY "/SystemConfiguration" /* [/System/Library]/... */ -#define BUNDLE_OLD_SUBDIR "/" -#define BUNDLE_NEW_SUBDIR "/Contents/MacOS/" -#define BUNDLE_DIR_EXTENSION ".bundle" -#define BUNDLE_DEBUG_EXTENSION "_debug" -#define BUNDLE_ENTRY_POINT "_start" -#define BUNDLE_ENTRY_POINT2 "_prime" - - -__BEGIN_DECLS - -/*! - @function SCDHandleInit - @discussion Creates a new handle used to access the cached configuration - dictionary data. - @result A new "cache" data handle. - */ -SCDHandleRef SCDHandleInit (); - -/*! - @function SCDHandleRelease - @discussion Releases the specified configuration data handle. The dictionary - (or other CFType) associated with this handle will also be released - unless a call was previously made to CFRetain(). - @param handle The cache data handle to be released. - */ -void SCDHandleRelease (SCDHandleRef handle); - -/*! - @function SCDHandleGetInstance - @discussion Returns the instance number associated with the specified - configuration handle. - @param handle The cache data handle. - @result The instance number associated with the specified handle. - */ -int SCDHandleGetInstance (SCDHandleRef handle); - -/*! - @function SCDHandleGetData - @discussion Returns a reference to the data associated with the specified - configuration handle. - @param handle The cache data handle. - @result The CFType data associated with the specified handle. - */ -CFPropertyListRef SCDHandleGetData (SCDHandleRef handle); - -/*! - @function SCDHandleSetData - @discussion Returns a reference to the data associated with the specified - configuration handle. - @param handle The cache data handle. - @param data The CFType data to be associated with the handle. - */ -void SCDHandleSetData (SCDHandleRef handle, - CFPropertyListRef data); -/*! - @function SCDOpen - @discussion Initiates a connection with the configuration daemon. - @param session A pointer to memory which will be filled with an SCDSessionRef - handle to be used for all subsequent requests to the server. - If a session cannot be established with the server, the contents of - memory pointed to by this parameter are undefined. - @param name Pass a string which describes the name of the calling process or - plug-in name of the caller. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDOpen (SCDSessionRef *session, - CFStringRef name); - -/*! - @function SCDClose - @discussion Closes the specified session to the configuration daemon. All - outstanding notification requests will be cancelled. - @param session Pass a pointer to an SCDSessionRef handle which should be closed. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDClose (SCDSessionRef *session); - -/*! - @function SCDLock - @discussion Locks access to the configuration "cache". All other clients - attempting to access the "cache" will block. All change notifications - will be deferred until the lock is released. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDLock (SCDSessionRef session); - -/*! - @function SCDUnlock - @discussion Unlocks access to the configuration "cache". Other clients will - be able to access the "cache". Any change notifications will be delivered. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDUnlock (SCDSessionRef session); - -/*! - @function SCDList - @discussion Returns an array of CFStringRefs representing the configuration "cache" - entries which match the specified pattern key. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param key The string which must prefix those keys in the configuration "cache" - (if regexOptions is zero) or a regex(3) regular expression string which - will be used to match configuration "cache" (if regexOptions is kSCDRegexKey). - @param regexOptions Pass a bitfield of type SCDKeyOption containing one or more - flags describing the pattern key. - @param subKeys Pass a pointer to a CFArrayRef which will be set to a new - array of CFStringRefs's matching the provided key. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDList (SCDSessionRef session, - CFStringRef key, - int regexOptions, - CFArrayRef *subKeys); - -/*! - @function SCDAdd - @discussion Creates a new entry in the configuration "cache" using the - specified key and data. An error is returned if the key is already - defined in the dictionary. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param key Pass a reference to the CFStringRef object to be created. - @param handle Pass a reference to the SCDHandle object containing the data - to be associated with the specified key. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDAdd (SCDSessionRef session, - CFStringRef key, - SCDHandleRef handle); - -/*! - @function SCDAddSession - @discussion Creates a new entry in the configuration "cache" using the - specified key and data. This entry will, unless updated by another - session, automatically be removed when the session is closed. An - error is returned if the key is already defined in the dictionary. - - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param key Pass a reference to the CFStringRef object to be created. - @param handle Pass a reference to the SCDHandle object containing the data - to be associated with the specified key. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDAddSession (SCDSessionRef session, - CFStringRef key, - SCDHandleRef handle); - -/*! - @function SCDGet - @discussion Returns a handle to the configuration "cache" data that corresponds - to the specified key. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param key Pass a reference to the CFStringRef object to be returned. - @param handle Pass a pointer to a SCDHandleRef which will be set to a - new object containing the data associated with the specified key. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDGet (SCDSessionRef session, - CFStringRef key, - SCDHandleRef *handle); - -/*! - @function SCDSet - @discussion Updates the entry in the configuration "cache" that corresponds to - the specified key with the provided data. An error will be returned if - the data in the "cache" has been updated since the data handle was last - updated. - @param session Pass the SCDSessionRef handle which should be used to communicate - with the server. - @param key Pass a reference to the CFStringRef object to be updated. - @param handle Pass a reference to the SCDHandle object containing the data - to be associated with the specified key. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDSet (SCDSessionRef session, - CFStringRef key, - SCDHandleRef handle); - -/*! - @function SCDRemove - @discussion Removes the data from the configuration "cache" data which corresponds - to the specified key. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param key Pass a reference to the CFStringRef object to be removed. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDRemove (SCDSessionRef session, - CFStringRef key); - -/*! - @function SCDTouch - @discussion Updates the instance number for the data in the configuration "cache" - associated with the specified key. If the specified key does not exist - then a CFDate object will be associated with the key. If the associated - data is already a CFDate object then the value will be updated. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param key Pass a reference to the CFStringRef object to be updated. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDTouch (SCDSessionRef session, - CFStringRef key); - -/* - @function SCDSnapshot - @discussion Records the current state of configd's cache dictionary into the - /var/tmp/configd-cache file and configd's session dictionary into the - /var/tmp/configd-session file. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDSnapshot (SCDSessionRef session); - -/*! - @function SCDNotifierList - @discussion Returns an array of CFStringRefs representing the system configuration - data entries being monitored for changes. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param regexOptions Pass a bitfield of type SCDKeyOption which specifies whether - the specific configuration cache key patterns are to be returned or those - based on regex(3) pattern strings. - @param notifierKeys Pass a pointer to a CFArrayRef which will be set to a new - array of CFStringRef's being monitored. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDNotifierList (SCDSessionRef session, - int regexOptions, - CFArrayRef *notifierKeys); - -/*! - @function SCDNotifierAdd - @discussion Adds the specified key to the list of system configuration - data entries which are being monitored for changes. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param key Pass a reference to the CFStringRef object to be monitored. - @param regexOptions Pass a bitfield of type SCDKeyOption which specifies whether - the key is for a specific configuration cache key or if it consists - of a regex(3) pattern string. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDNotifierAdd (SCDSessionRef session, - CFStringRef key, - int regexOptions); - -/*! - @function SCDNotifierRemove - @discussion Removes the specified key from the list of system configuration - data entries which are being monitored for changes. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param key Pass a reference to the CFStringRef object which should not be monitored. - @param regexOptions Pass a bitfield of type SCDKeyOption which specifies whether - the key is for a specific configuration cache key or if it consists - of a regex(3) pattern string. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDNotifierRemove (SCDSessionRef session, - CFStringRef key, - int regexOptions); - -/*! - @function SCDNotifierGetChanges - @discussion Returns an array of CFStringRefs representing the monitored system - configuration data entries which have changed since this function - was last called. - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param notifierKeys Pass a pointer to a CFArrayRef which will be set to a new - array of CFStringRef's being monitored. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDNotifierGetChanges (SCDSessionRef session, - CFArrayRef *notifierKeys); - -/*! - @function SCDNotifierWait - @discussion Waits for a change to be made to a system configuration data - entry associated with the current sessions notifier keys. - - Note: this function is not valid for "configd" plug-ins. - - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDNotifierWait (SCDSessionRef session); - -/*! - @function SCDNotifierInformViaCallback - @discussion Requests that the specified function be called whenever a change - has been detected to one of the system configuration data entries - associated with the current sessions notifier keys. - - The callback function will be called with two arguments, session and arg, which - correspond to the current session and the provided argument. - The function should return a boolean value indicating whether an - error occurred during execution of the callback. - - Note: if the calling application is based on the CFRunLoop() then an additional - run loop source will be added for the notification. - Applications which are not based on the CFRunLoop() will have a separate thread - started to wait for changes. - In either case, the additional run loop source and/or thread will terminate if - the notification is cancelled or if the callback indicates that an error was - detected. - - Note: this function is not valid for "configd" plug-ins. - - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param func Pass a pointer to the callback applier function to call when a - monitored cache entry is changed. If this parameter is not a pointer to - a function of the correct prototype (SCDCallbackRoutine_t), the behavior - is undefined. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDNotifierInformViaCallback (SCDSessionRef session, - SCDCallbackRoutine_t func, - void *arg); - -/*! - @function SCDNotifierInformViaMachPort - @discussion Allocates a mach port which can be used to detect changes to - one of the system configuration data entries associated with the - current sessions notifier keys. When a change is detected, an - empty (no data) mach message with the specified identifier will - be delivered to the calling application via the allocated port. - - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param msgid Pass a mach message ID to be included with any notifications. - @param port Pass a pointer to a mach port. Upon return, port will be filled - with the mach port which will be used for any notifications. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDNotifierInformViaMachPort (SCDSessionRef session, - mach_msg_id_t msgid, - mach_port_t *port); - -/*! - @function SCDNotifierInformViaFD - @discussion Allocates a file descriptor which can be used to detect changes - to one of the system configuration data entries associated with the - current sessions notifier keys. When a change is detected, the - specified identifier (4 bytes) will be delivered to the calling - application via the allocated file descriptor. - - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param identifier Pass an (4 byte) integer identifer which be used for any - notifications. - @param fd Pass a pointer to a file descriptor. Upon return, fd will be filled - with the file descriptor which will be used for any notifications. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDNotifierInformViaFD (SCDSessionRef session, - int32_t identifier, - int *fd); - -/*! - @function SCDNotifierInformViaSignal - @discussion Requests that the specified BSD signal be sent to the process - with the indicated process id whenever a change has been detected - to one of the system configuration data entries associated with the - current sessions notifier keys. - - Note: this function is not valid for "configd" plug-ins. - - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @param pid Pass a UNIX proces ID which should be signalled for any notifications. - @param sig Pass a signal number to be used. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDNotifierInformViaSignal (SCDSessionRef session, - pid_t pid, - int sig); - -/*! - @function SCDNotifierCancel - @discussion Cancels all outstanding notification delivery request for this - session. - - @param session Pass a SCDSessionRef handle which should be used for - communication with the server. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDNotifierCancel (SCDSessionRef session); - -/*! - @function SCDOptionGet - @discussion Returns the value associated with the specified option. - @param session Pass a SCDSessionRef handle of the option of interest (or - NULL for the global option setting). - @param option Pass the SCDOption of interest. - @result The current value of the specified option. - */ -int SCDOptionGet (SCDSessionRef session, - int option); - -/*! - @function SCDOptionSet - @discussion Sets the value associated with the specified option. - @param session Pass a SCDSessionRef handle for the option to be set (or - NULL for the global option settings). - @param option Pass the SCDOption to be updated. - @param value Pass the new value for the option. - @result The current value of the specified option. - */ -void SCDOptionSet (SCDSessionRef session, - int option, - int value); - -/*! - @function SCDSessionLog - @discussion Issues a log and/or debug message. - @param session Pass a SCDSessionRef handle for the current session.. - @param level Pass a syslog(3) logging priority. - - Note: LOG_DEBUG messages will not be issued if the verbose option has not been enabled. - @param formatString Pass the CF format string - @result The specified message will be logged. - */ -void SCDSessionLog (SCDSessionRef session, - int level, - CFStringRef formatString, - ...); - -/*! - @function SCDLog - @discussion Issues a log and/or debug message. - @param level Pass a syslog(3) logging priority. - @param formatString Pass the CF format string - @result The specified message will be logged. - */ -void SCDLog (int level, - CFStringRef formatString, - ...); - -const char * SCDError (SCDStatus status); - -__END_DECLS +#ifndef _SYSTEMCONFIGURATION_H +#warning Your code has directly included the (old) +#warning header file. Please dont do that. Use the top-level header file: +#warning +#warning +#warning +#warning Note: the dynamic store APIs have been moved out of the SCD.h header. +#include /* ...and try to keep everyone happy */ +#endif #endif /* _SCD_H */ diff --git a/SystemConfiguration.fproj/SCDAdd.c b/SystemConfiguration.fproj/SCDAdd.c index 382249e..c1e5cc3 100644 --- a/SystemConfiguration.fproj/SCDAdd.c +++ b/SystemConfiguration.fproj/SCDAdd.c @@ -20,38 +20,52 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDAdd(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) +Boolean +SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - CFDataRef xmlKey; /* serialized key */ - xmlData_t myKeyRef; - CFIndex myKeyLen; - CFDataRef xmlData; /* serialized data */ - xmlData_t myDataRef; - CFIndex myDataLen; - int newInstance; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlKey; /* serialized key */ + xmlData_t myKeyRef; + CFIndex myKeyLen; + CFDataRef xmlData; /* serialized data */ + xmlData_t myDataRef; + CFIndex myDataLen; + int newInstance; + int sc_status; - SCDLog(LOG_DEBUG, CFSTR("SCDAdd:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" data = %@"), SCDHandleGetData(handle)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); - if (key == NULL) { - return SCD_INVALIDARGUMENT; /* no key specified */ + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } /* serialize the key and data */ @@ -59,18 +73,18 @@ SCDAdd(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) myKeyRef = (xmlData_t)CFDataGetBytePtr(xmlKey); myKeyLen = CFDataGetLength(xmlKey); - xmlData = CFPropertyListCreateXMLData(NULL, SCDHandleGetData(handle)); + xmlData = CFPropertyListCreateXMLData(NULL, value); myDataRef = (xmlData_t)CFDataGetBytePtr(xmlData); myDataLen = CFDataGetLength(xmlData); /* send the key & data to the server */ - status = configadd(sessionPrivate->server, + status = configadd(storePrivate->server, myKeyRef, myKeyLen, myDataRef, myDataLen, &newInstance, - (int *)&scd_status); + (int *)&sc_status); /* clean up */ CFRelease(xmlKey); @@ -78,17 +92,17 @@ SCDAdd(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configadd(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configadd(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; } - if (scd_status == SCD_OK) { - _SCDHandleSetInstance(handle, newInstance); + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - SCDLog(LOG_DEBUG, CFSTR(" new instance = %d"), SCDHandleGetInstance(handle)); - - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDAddSession.c b/SystemConfiguration.fproj/SCDAddSession.c index b19ae0e..d470876 100644 --- a/SystemConfiguration.fproj/SCDAddSession.c +++ b/SystemConfiguration.fproj/SCDAddSession.c @@ -20,38 +20,52 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * October 17, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDAddSession(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) +Boolean +SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - CFDataRef xmlKey; /* serialized key */ - xmlData_t myKeyRef; - CFIndex myKeyLen; - CFDataRef xmlData; /* serialized data */ - xmlData_t myDataRef; - CFIndex myDataLen; - int newInstance; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlKey; /* serialized key */ + xmlData_t myKeyRef; + CFIndex myKeyLen; + CFDataRef xmlData; /* serialized data */ + xmlData_t myDataRef; + CFIndex myDataLen; + int newInstance; + int sc_status; - SCDLog(LOG_DEBUG, CFSTR("SCDAddSession:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" data = %@"), SCDHandleGetData(handle)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddTemporaryValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); - if (key == NULL) { - return SCD_INVALIDARGUMENT; /* no key specified */ + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } /* serialize the key and data */ @@ -59,18 +73,18 @@ SCDAddSession(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) myKeyRef = (xmlData_t)CFDataGetBytePtr(xmlKey); myKeyLen = CFDataGetLength(xmlKey); - xmlData = CFPropertyListCreateXMLData(NULL, SCDHandleGetData(handle)); + xmlData = CFPropertyListCreateXMLData(NULL, value); myDataRef = (xmlData_t)CFDataGetBytePtr(xmlData); myDataLen = CFDataGetLength(xmlData); /* send the key & data to the server */ - status = configadd_s(sessionPrivate->server, + status = configadd_s(storePrivate->server, myKeyRef, myKeyLen, myDataRef, myDataLen, &newInstance, - (int *)&scd_status); + (int *)&sc_status); /* clean up */ CFRelease(xmlKey); @@ -78,17 +92,17 @@ SCDAddSession(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configadd_s(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configadd_s(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; } - if (scd_status == SCD_OK) { - _SCDHandleSetInstance(handle, newInstance); + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - SCDLog(LOG_DEBUG, CFSTR(" new instance = %d"), SCDHandleGetInstance(handle)); - - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDClose.c b/SystemConfiguration.fproj/SCDClose.c deleted file mode 100644 index 86aeb3c..0000000 --- a/SystemConfiguration.fproj/SCDClose.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include - -#include -#include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - - -SCDStatus -SCDClose(SCDSessionRef *session) -{ - SCDSessionPrivateRef sessionPrivate; - int oldThreadState; - kern_return_t status; - SCDStatus scd_status; - CFIndex keyCnt; - - SCDLog(LOG_DEBUG, CFSTR("SCDClose:")); - - if ((session == NULL) || (*session == NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCDSessionPrivateRef)*session; - - (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldThreadState); - - scd_status = (sessionPrivate->server == MACH_PORT_NULL) ? SCD_NOSESSION : SCD_OK; - - /* Remove notification keys */ - 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; ireKeys)) > 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; iserver, (int *)&scd_status); - if (status != KERN_SUCCESS) { - if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configclose(): %s"), mach_error_string(status)); - scd_status = SCD_NOSERVER; - } - - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - } - - CFAllocatorDeallocate(NULL, sessionPrivate); - *session = NULL; - - (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldThreadState); - pthread_testcancel(); - - return scd_status; -} diff --git a/SystemConfiguration.fproj/SCDConsoleUser.c b/SystemConfiguration.fproj/SCDConsoleUser.c index a607b93..900db51 100644 --- a/SystemConfiguration.fproj/SCDConsoleUser.c +++ b/SystemConfiguration.fproj/SCDConsoleUser.c @@ -20,72 +20,75 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * January 2, 2001 Allan Nathanson + * - initial revision + */ +#include +#include +#include CFStringRef -SCDKeyCreateConsoleUser() +SCDynamicStoreKeyCreateConsoleUser(CFAllocatorRef allocator) { - return SCDKeyCreate(CFSTR("%@/%@/%@"), - CFSTR("state:"), // FIXME!!! (should be kSCCacheDomainState) - kSCCompUsers, - kSCEntUsersConsoleUser); + return SCDynamicStoreKeyCreate(allocator, + CFSTR("%@/%@/%@"), + kSCDynamicStoreDomainState, + kSCCompUsers, + kSCEntUsersConsoleUser); } -SCDStatus -SCDConsoleUserGet(char *user, int userlen, uid_t *uid, gid_t *gid) +CFStringRef +SCDynamicStoreCopyConsoleUser(SCDynamicStoreRef store, + uid_t *uid, + gid_t *gid) { - CFDictionaryRef dict; - SCDHandleRef handle = NULL; - CFStringRef key; - SCDSessionRef session = NULL; - SCDStatus status; - - /* get current user */ - status = SCDOpen(&session, CFSTR("SCDConsoleUserGet")); - if (status != SCD_OK) { - goto done; + CFStringRef consoleUser = NULL; + CFDictionaryRef dict = NULL; + CFStringRef key; + SCDynamicStoreRef mySession = store; + + if (!store) { + mySession = SCDynamicStoreCreate(NULL, + CFSTR("SCDynamicStoreCopyConsoleUser"), + NULL, + NULL); + if (!mySession) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + return NULL; + } } - key = SCDKeyCreateConsoleUser(); - status = SCDGet(session, key, &handle); + key = SCDynamicStoreKeyCreateConsoleUser(NULL); + dict = SCDynamicStoreCopyValue(mySession, key); CFRelease(key); - if (status != SCD_OK) { + if (!isA_CFDictionary(dict)) { + _SCErrorSet(kSCStatusNoKey); goto done; } - dict = SCDHandleGetData(handle); - - if (user && (userlen > 0)) { - CFStringRef consoleUser; - - bzero(user, userlen); - if (CFDictionaryGetValueIfPresent(dict, - kSCPropUsersConsoleUserName, - (void **)&consoleUser)) { - CFIndex len; - CFRange range; - - range = CFRangeMake(0, CFStringGetLength(consoleUser)); - (void)CFStringGetBytes(consoleUser, - range, - kCFStringEncodingMacRoman, - 0, - FALSE, - user, - userlen, - &len); - } + consoleUser = CFDictionaryGetValue(dict, kSCPropUsersConsoleUserName); + consoleUser = isA_CFString(consoleUser); + if (!consoleUser) { + _SCErrorSet(kSCStatusNoKey); + goto done; } + CFRetain(consoleUser); + if (uid) { CFNumberRef num; SInt32 val; - if (CFDictionaryGetValueIfPresent(dict, - kSCPropUsersConsoleUserUID, - (void **)&num)) { + num = CFDictionaryGetValue(dict, kSCPropUsersConsoleUserUID); + if (isA_CFNumber(num)) { if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) { *uid = (uid_t)val; } @@ -96,9 +99,8 @@ SCDConsoleUserGet(char *user, int userlen, uid_t *uid, gid_t *gid) CFNumberRef num; SInt32 val; - if (CFDictionaryGetValueIfPresent(dict, - kSCPropUsersConsoleUserGID, - (void **)&num)) { + num = CFDictionaryGetValue(dict, kSCPropUsersConsoleUserGID); + if (isA_CFNumber(num)) { if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) { *gid = (gid_t)val; } @@ -107,30 +109,39 @@ SCDConsoleUserGet(char *user, int userlen, uid_t *uid, gid_t *gid) done : - if (handle) SCDHandleRelease(handle); - if (session) (void) SCDClose(&session); - return status; + if (!store && mySession) CFRelease(mySession); + if (dict) CFRelease(dict); + return consoleUser; + } -SCDStatus -SCDConsoleUserSet(const char *user, uid_t uid, gid_t gid) +Boolean +SCDynamicStoreSetConsoleUser(SCDynamicStoreRef store, + const char *user, + uid_t uid, + gid_t gid) { CFStringRef consoleUser; - CFMutableDictionaryRef dict = NULL; - SCDHandleRef handle = NULL; - CFStringRef key = SCDKeyCreateConsoleUser(); + CFMutableDictionaryRef dict = NULL; + CFStringRef key = SCDynamicStoreKeyCreateConsoleUser(NULL); + SCDynamicStoreRef mySession = store; CFNumberRef num; - SCDSessionRef session = NULL; - SCDStatus status; - - status = SCDOpen(&session, CFSTR("SCDConsoleUserSet")); - if (status != SCD_OK) { - goto done; + Boolean ok = TRUE; + + if (!store) { + mySession = SCDynamicStoreCreate(NULL, + CFSTR("SCDynamicStoreSetConsoleUser"), + NULL, + NULL); + if (!mySession) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + return FALSE; + } } if (user == NULL) { - (void)SCDRemove(session, key); + ok = SCDynamicStoreRemoveValue(mySession, key); goto done; } @@ -151,22 +162,12 @@ SCDConsoleUserSet(const char *user, uid_t uid, gid_t gid) CFDictionarySetValue(dict, kSCPropUsersConsoleUserGID, num); CFRelease(num); - handle = SCDHandleInit(); - SCDHandleSetData(handle, dict); - - status = SCDLock(session); - if (status != SCD_OK) { - goto done; - } - (void)SCDRemove(session, key); - (void)SCDAdd (session, key, handle); - status = SCDUnlock(session); + ok = SCDynamicStoreSetValue(mySession, key, dict); done : - if (dict) CFRelease(dict); - if (handle) SCDHandleRelease(handle); - if (key) CFRelease(key); - if (session) (void) SCDClose(&session); - return status; + if (dict) CFRelease(dict); + if (key) CFRelease(key); + if (!store && mySession) CFRelease(mySession); + return ok; } diff --git a/SystemConfiguration.fproj/SCDConsoleUser.h b/SystemConfiguration.fproj/SCDConsoleUser.h index e164799..ded9eb5 100644 --- a/SystemConfiguration.fproj/SCDConsoleUser.h +++ b/SystemConfiguration.fproj/SCDConsoleUser.h @@ -23,74 +23,15 @@ #ifndef _SCDCONSOLEUSER_H #define _SCDCONSOLEUSER_H -#include - -/*! - @header SCDConsoleUser.h - The SystemConfiguration framework provides access to the data used - to configure a running system. - - Specifically, the SCDConsoleUserXXX() API's allow an application - to determine (or set) the login/user currently using the - console. - - The APIs provided by this framework communicate with the "configd" - daemon to obtain information regarding the systems current - configuration. - */ - - -__BEGIN_DECLS - -/*! - @function SCDKeyCreateConsoleUser - @discussion Creates a key which can be used by the SCDNotifierAdd() - function to receive notifications when the current "Console" - user changes. - @result A notification string for the current "Console" user. -*/ -CFStringRef SCDKeyCreateConsoleUser (); - -/*! - @function SCDConsoleUserGet - @discussion Gets the name, user ID, and group ID of the currently - logged in user. - @param user A pointer to a character buffer of at least size - userlen. The returned name is null-terminated unless - in-sufficient space is provided.If NULL, this value - will not be returned. - @param userlen Pass an integer specifying the maximum size of the - user buffer. - @param uid A pointer to memory which will be filled with the user ID - of the current "Console" user. If NULL, this value will not - be returned. - @param gid A pointer to memory which will be filled with the group ID - of the current "Console" user. If NULL, this value will not be - returned. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDConsoleUserGet (char *user, - int userlen, - uid_t *uid, - gid_t *gid); - -/*! - @function SCDConsoleUserSet - @discussion Sets the name, user ID, and group ID of the currently - logged in user. - @param user A pointer to a character buffer containing the name of - the current "Console" user. If NULL, any current "Console" - user information will be reset. - @param uid The user ID of the current "Console" user. - @param gid The group ID of the current "Console" user. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDConsoleUserSet (const char *user, - uid_t uid, - gid_t gid); - -__END_DECLS +#ifndef _SYSTEMCONFIGURATION_H +#warning Your code has directly included the (old) +#warning header file. Please dont do that. Use the top-level header file: +#warning +#warning +#warning +#warning Note: the console user access APIs have been moved out of +#warning the SCDConsoleUser.h header file. +#include /* ...and try to keep everyone happy */ +#endif #endif /* _SCDCONSOLEUSER_H */ diff --git a/SystemConfiguration.fproj/SCDGet.c b/SystemConfiguration.fproj/SCDGet.c index d59a46a..7cccb61 100644 --- a/SystemConfiguration.fproj/SCDGet.c +++ b/SystemConfiguration.fproj/SCDGet.c @@ -20,39 +20,164 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" -SCDStatus -SCDGet(SCDSessionRef session, CFStringRef key, SCDHandleRef *handle) +CFDictionaryRef +SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, + CFArrayRef keys, + CFArrayRef patterns) +{ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlKeys = NULL; /* keys (XML serialized) */ + xmlData_t myKeysRef = NULL; /* keys (serialized) */ + CFIndex myKeysLen = 0; + CFDataRef xmlPatterns = NULL; /* patterns (XML serialized) */ + xmlData_t myPatternsRef = NULL; /* patterns (serialized) */ + CFIndex myPatternsLen = 0; + xmlDataOut_t xmlDictRef; /* dict (serialized) */ + CFIndex xmlDictLen; + CFDataRef xmlDict; /* dict (XML serialized) */ + CFDictionaryRef dict; /* dict (un-serialized) */ + int sc_status; + CFStringRef xmlError; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyMultiple:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" keys = %@"), keys); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" patterns = %@"), patterns); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return NULL; + } + + if (storePrivate->server == MACH_PORT_NULL) { + _SCErrorSet(kSCStatusNoStoreServer); + return NULL; /* you must have an open session to play */ + } + + /* serialize the keys */ + if (keys) { + xmlKeys = CFPropertyListCreateXMLData(NULL, keys); + myKeysRef = (xmlData_t)CFDataGetBytePtr(xmlKeys); + myKeysLen = CFDataGetLength(xmlKeys); + } + + /* serialize the patterns */ + if (patterns) { + xmlPatterns = CFPropertyListCreateXMLData(NULL, patterns); + myPatternsRef = (xmlData_t)CFDataGetBytePtr(xmlPatterns); + myPatternsLen = CFDataGetLength(xmlPatterns); + } + + /* send the keys and patterns, fetch the associated result from the server */ + status = configget_m(storePrivate->server, + myKeysRef, + myKeysLen, + myPatternsRef, + myPatternsLen, + &xmlDictRef, + (int *)&xmlDictLen, + (int *)&sc_status); + + /* clean up */ + if (xmlKeys) CFRelease(xmlKeys); + if (xmlPatterns) CFRelease(xmlPatterns); + + if (status != KERN_SUCCESS) { + if (status != MACH_SEND_INVALID_DEST) + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configget_m(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return NULL; + } + + if (sc_status != kSCStatusOK) { + status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDictRef, xmlDictLen); + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + /* non-fatal???, proceed */ + } + _SCErrorSet(sc_status); + return NULL; + } + + /* un-serialize the dict, return a value associated with the key */ + xmlDict = CFDataCreate(NULL, xmlDictRef, xmlDictLen); + status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDictRef, xmlDictLen); + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + /* non-fatal???, proceed */ + } + dict = CFPropertyListCreateFromXMLData(NULL, + xmlDict, + kCFPropertyListImmutable, + &xmlError); + CFRelease(xmlDict); + if (!dict) { + if (xmlError) { + SCLog(_sc_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() dict: %@"), + xmlError); + CFRelease(xmlError); + } + _SCErrorSet(kSCStatusFailed); + return NULL; + } + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), dict); + + return dict; +} + + +CFPropertyListRef +SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - CFDataRef xmlKey; /* key (XML serialized) */ - xmlData_t myKeyRef; /* key (serialized) */ - CFIndex myKeyLen; - xmlDataOut_t xmlDataRef; /* data (serialized) */ - CFIndex xmlDataLen; - CFDataRef xmlData; /* data (XML serialized) */ - CFPropertyListRef data; /* data (un-serialized) */ - int newInstance; - SCDStatus scd_status; - CFStringRef xmlError; - - SCDLog(LOG_DEBUG, CFSTR("SCDGet:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - - if (key == NULL) { - return SCD_INVALIDARGUMENT; /* no key specified */ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlKey; /* key (XML serialized) */ + xmlData_t myKeyRef; /* key (serialized) */ + CFIndex myKeyLen; + xmlDataOut_t xmlDataRef; /* data (serialized) */ + CFIndex xmlDataLen; + CFDataRef xmlData; /* data (XML serialized) */ + CFPropertyListRef data; /* data (un-serialized) */ + int newInstance; + int sc_status; + CFStringRef xmlError; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return NULL; } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; + if (storePrivate->server == MACH_PORT_NULL) { + _SCErrorSet(kSCStatusNoStoreServer); + return NULL; /* you must have an open session to play */ } /* serialize the key */ @@ -61,41 +186,41 @@ SCDGet(SCDSessionRef session, CFStringRef key, SCDHandleRef *handle) myKeyLen = CFDataGetLength(xmlKey); /* send the key & fetch the associated data from the server */ - status = configget(sessionPrivate->server, + status = configget(storePrivate->server, myKeyRef, myKeyLen, &xmlDataRef, (int *)&xmlDataLen, &newInstance, - (int *)&scd_status); + (int *)&sc_status); /* clean up */ CFRelease(xmlKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configget(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configget(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return NULL; } - if (scd_status != SCD_OK) { + if (sc_status != kSCStatusOK) { status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } - *handle = NULL; - return scd_status; + _SCErrorSet(sc_status); + return NULL; } - /* un-serialize the data, return a handle associated with the key */ - *handle = SCDHandleInit(); + /* un-serialize the data, return a value associated with the key */ xmlData = CFDataCreate(NULL, xmlDataRef, xmlDataLen); status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } data = CFPropertyListCreateFromXMLData(NULL, @@ -103,18 +228,18 @@ SCDGet(SCDSessionRef session, CFStringRef key, SCDHandleRef *handle) kCFPropertyListImmutable, &xmlError); CFRelease(xmlData); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() data: %s"), xmlError); - SCDHandleRelease(*handle); - return SCD_FAILED; + if (!data) { + if (xmlError) { + SCLog(_sc_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() data: %@"), + xmlError); + CFRelease(xmlError); + } + _SCErrorSet(kSCStatusFailed); + return NULL; } - SCDHandleSetData(*handle, data); - CFRelease(data); - - _SCDHandleSetInstance(*handle, newInstance); - SCDLog(LOG_DEBUG, CFSTR(" data = %@"), SCDHandleGetData(*handle)); - SCDLog(LOG_DEBUG, CFSTR(" instance = %d"), SCDHandleGetInstance(*handle)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), data); - return scd_status; + return data; } diff --git a/SystemConfiguration.fproj/SCDHandle.c b/SystemConfiguration.fproj/SCDHandle.c deleted file mode 100644 index 5e4ab8e..0000000 --- a/SystemConfiguration.fproj/SCDHandle.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include "SCDPrivate.h" - - -SCDHandleRef -SCDHandleInit() -{ - SCDHandlePrivateRef privateHandle = CFAllocatorAllocate(NULL, sizeof(SCDHandlePrivate), 0); - - /* set data */ - privateHandle->data = NULL; - - /* set instance */ - privateHandle->instance = 0; - - return (SCDHandleRef)privateHandle; -} - - -void -SCDHandleRelease(SCDHandleRef handle) -{ - SCDHandlePrivateRef privateHandle = (SCDHandlePrivateRef)handle; - - if (privateHandle->data) - CFRelease(privateHandle->data); - - CFAllocatorDeallocate(NULL, privateHandle); - return; -} - - -int -SCDHandleGetInstance(SCDHandleRef handle) -{ - SCDHandlePrivateRef privateHandle = (SCDHandlePrivateRef)handle; - - return privateHandle->instance; -} - - -void -_SCDHandleSetInstance(SCDHandleRef handle, int instance) -{ - SCDHandlePrivateRef privateHandle = (SCDHandlePrivateRef)handle; - - privateHandle->instance = instance; - return; -} - - -CFPropertyListRef -SCDHandleGetData(SCDHandleRef handle) -{ - SCDHandlePrivateRef privateHandle = (SCDHandlePrivateRef)handle; - - if (privateHandle->data == NULL) { - return CFSTR("SCDHandleRef not initialized."); - } - - return privateHandle->data; -} - - -void -SCDHandleSetData(SCDHandleRef handle, CFPropertyListRef data) -{ - SCDHandlePrivateRef privateHandle = (SCDHandlePrivateRef)handle; - - /* remove reference to data previously associated with handle */ - if (privateHandle->data) - CFRelease(privateHandle->data); - - /* associate new data with handle, keep a reference as needed */ - privateHandle->data = data; - if (privateHandle->data) - CFRetain(privateHandle->data); - - return; -} diff --git a/SystemConfiguration.fproj/SCDHostName.c b/SystemConfiguration.fproj/SCDHostName.c index c127f7f..b4ad826 100644 --- a/SystemConfiguration.fproj/SCDHostName.c +++ b/SystemConfiguration.fproj/SCDHostName.c @@ -20,58 +20,74 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * January 8, 2001 Allan Nathanson + * - initial revision + */ +#include +#include +#include CFStringRef -SCDKeyCreateHostName() +SCDynamicStoreKeyCreateComputerName(CFAllocatorRef allocator) { - return SCDKeyCreate(CFSTR("%@/%@"), - kSCCacheDomainSetup, - kSCCompSystem); + return SCDynamicStoreKeyCreate(allocator, + CFSTR("%@/%@"), + kSCDynamicStoreDomainSetup, + kSCCompSystem); } -SCDStatus -SCDHostNameGet(CFStringRef *name, CFStringEncoding *nameEncoding) +CFStringRef +SCDynamicStoreCopyComputerName(SCDynamicStoreRef store, + CFStringEncoding *nameEncoding) { - CFDictionaryRef dict; - SCDHandleRef handle = NULL; - CFStringRef key; - SCDSessionRef session = NULL; - SCDStatus status; - - if (name == NULL) { - return SCD_FAILED; - } + CFDictionaryRef dict = NULL; + CFStringRef key; + CFStringRef name = NULL; + SCDynamicStoreRef mySession = store; - /* get current user */ - status = SCDOpen(&session, CFSTR("SCDHostNameGet")); - if (status != SCD_OK) { - goto done; + if (!store) { + mySession = SCDynamicStoreCreate(NULL, + CFSTR("SCDynamicStoreCopyComputerName"), + NULL, + NULL); + if (!mySession) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + return NULL; + } } - key = SCDKeyCreateHostName(); - status = SCDGet(session, key, &handle); + key = SCDynamicStoreKeyCreateComputerName(NULL); + dict = SCDynamicStoreCopyValue(mySession, key); CFRelease(key); - if (status != SCD_OK) { + if (!dict) { + goto done; + } + if (!isA_CFDictionary(dict)) { + _SCErrorSet(kSCStatusNoKey); goto done; } - dict = SCDHandleGetData(handle); - - *name = CFDictionaryGetValue(dict, kSCPropSystemComputerName); - if (*name == NULL) { + name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemComputerName)); + if (!name) { + _SCErrorSet(kSCStatusNoKey); goto done; } - CFRetain(*name); + CFRetain(name); if (nameEncoding) { CFNumberRef num; num = CFDictionaryGetValue(dict, kSCPropSystemComputerNameEncoding); - if (num) { + if (isA_CFNumber(num)) { CFNumberGetValue(num, kCFNumberIntType, nameEncoding); } else { *nameEncoding = CFStringGetSystemEncoding(); @@ -80,7 +96,57 @@ SCDHostNameGet(CFStringRef *name, CFStringEncoding *nameEncoding) done : - if (handle) SCDHandleRelease(handle); - if (session) (void) SCDClose(&session); - return status; + if (!store && mySession) CFRelease(mySession); + if (dict) CFRelease(dict); + return name; +} + + +Boolean +SCPreferencesSetComputerName(SCPreferencesRef session, + CFStringRef name, + CFStringEncoding encoding) +{ + CFDictionaryRef dict; + CFMutableDictionaryRef newDict = NULL; + CFNumberRef num; + Boolean ok = FALSE; + CFStringRef path = NULL; + + if (CFGetTypeID(name) != CFStringGetTypeID()) { + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + + path = CFStringCreateWithFormat(NULL, + NULL, + CFSTR("/%@/%@"), + kSCPrefSystem, + kSCCompSystem); + + dict = SCPreferencesPathGetValue(session, path); + if (dict) { + newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); + } else { + newDict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + + CFDictionarySetValue(newDict, kSCPropSystemComputerName, name); + + num = CFNumberCreate(NULL, kCFNumberIntType, &encoding); + CFDictionarySetValue(newDict, kSCPropSystemComputerNameEncoding, num); + CFRelease(num); + + ok = SCPreferencesPathSetValue(session, path, newDict); + if (!ok) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesPathSetValue() failed")); + } + + if (path) CFRelease(path); + if (newDict) CFRelease(newDict); + + return ok; } diff --git a/SystemConfiguration.fproj/SCDHostName.h b/SystemConfiguration.fproj/SCDHostName.h index 2ce1cad..ac0440a 100644 --- a/SystemConfiguration.fproj/SCDHostName.h +++ b/SystemConfiguration.fproj/SCDHostName.h @@ -23,47 +23,16 @@ #ifndef _SCDHOSTNAME_H #define _SCDHOSTNAME_H -#include - -/*! - @header SCDHostName.h - The SystemConfiguration framework provides access to the data used - to configure a running system. - - Specifically, the SCDHostNameXXX() API's allow an application - to determine (or set) the login/user currently using the - console. - - The APIs provided by this framework communicate with the "configd" - daemon to obtain information regarding the systems current - configuration. - */ - - -__BEGIN_DECLS - -/*! - @function SCDKeyCreateHostName - @discussion Creates a key which can be used by the SCDNotifierAdd() - function to receive notifications when the current - computer/host name changes. - @result A notification string for the current computer/host name". -*/ -CFStringRef SCDKeyCreateHostName (); - -/*! - @function SCDHostNameGet - @discussion Gets the current computer/host name. - @param name A pointer to memory which will be filled with the current - computer/host name. - @param nameEncoding A pointer to memory which, if non-NULL, will be - filled with the encoding associated with the computer/host name. - @result A constant of type SCDStatus indicating the success (or failure) of - the call. - */ -SCDStatus SCDHostNameGet (CFStringRef *name, - CFStringEncoding *nameEncoding); - -__END_DECLS +#ifndef _SYSTEMCONFIGURATION_H +#warning Your code has directly included the (old) +#warning header file. Please dont do that. Use the top-level header file: +#warning +#warning +#warning +#warning Note: the computer name access APIs have been moved out of +#warning the SCDHostName.h header file. + +#include /* ...and try to keep everyone happy */ +#endif #endif /* _SCDHOSTNAME_H */ diff --git a/SystemConfiguration.fproj/SCDKeys.c b/SystemConfiguration.fproj/SCDKeys.c index e2a51c7..1070ba4 100644 --- a/SystemConfiguration.fproj/SCDKeys.c +++ b/SystemConfiguration.fproj/SCDKeys.c @@ -20,35 +20,49 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * December 11, 2000 Allan Nathanson + * - initial revision + */ + #include #include /* - * SCDKeyCreate* - * - convenience routines that create a CFString key for an item in the cache + * SCDynamicStoreKeyCreate* + * - convenience routines that create a CFString key for an item in the store */ /* - * Function: SCDKeyCreate + * Function: SCDynamicStoreKeyCreate * Purpose: - * Creates a cache key using the given format. + * Creates a store key using the given format. */ CFStringRef -SCDKeyCreate(CFStringRef fmt, ...) +SCDynamicStoreKeyCreate(CFAllocatorRef allocator, + CFStringRef fmt, + ...) { va_list args; va_start(args, fmt); - return (CFStringCreateWithFormatAndArguments(NULL, + return (CFStringCreateWithFormatAndArguments(allocator, NULL, fmt, args)); } CFStringRef -SCDKeyCreateNetworkGlobalEntity(CFStringRef domain, CFStringRef entity) +SCDynamicStoreKeyCreateNetworkGlobalEntity(CFAllocatorRef allocator, + CFStringRef domain, + CFStringRef entity) { - return (CFStringCreateWithFormat(NULL, + return (CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@/%@/%@"), domain, @@ -58,9 +72,10 @@ SCDKeyCreateNetworkGlobalEntity(CFStringRef domain, CFStringRef entity) } CFStringRef -SCDKeyCreateNetworkInterface(CFStringRef domain) +SCDynamicStoreKeyCreateNetworkInterface(CFAllocatorRef allocator, + CFStringRef domain) { - return (CFStringCreateWithFormat(NULL, + return (CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@/%@"), domain, @@ -69,12 +84,13 @@ SCDKeyCreateNetworkInterface(CFStringRef domain) } CFStringRef -SCDKeyCreateNetworkInterfaceEntity(CFStringRef domain, - CFStringRef ifname, - CFStringRef entity) +SCDynamicStoreKeyCreateNetworkInterfaceEntity(CFAllocatorRef allocator, + CFStringRef domain, + CFStringRef ifname, + CFStringRef entity) { if (entity == NULL) { - return (CFStringCreateWithFormat(NULL, + return (CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@/%@/%@"), domain, @@ -82,7 +98,7 @@ SCDKeyCreateNetworkInterfaceEntity(CFStringRef domain, kSCCompInterface, ifname)); } else { - return (CFStringCreateWithFormat(NULL, + return (CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@/%@/%@/%@"), domain, @@ -94,12 +110,13 @@ SCDKeyCreateNetworkInterfaceEntity(CFStringRef domain, } CFStringRef -SCDKeyCreateNetworkServiceEntity(CFStringRef domain, - CFStringRef serviceID, - CFStringRef entity) +SCDynamicStoreKeyCreateNetworkServiceEntity(CFAllocatorRef allocator, + CFStringRef domain, + CFStringRef serviceID, + CFStringRef entity) { if (entity == NULL) { - return (CFStringCreateWithFormat(NULL, + return (CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@/%@/%@"), domain, @@ -107,7 +124,7 @@ SCDKeyCreateNetworkServiceEntity(CFStringRef domain, kSCCompService, serviceID)); } else { - return (CFStringCreateWithFormat(NULL, + return (CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@/%@/%@/%@"), domain, diff --git a/SystemConfiguration.fproj/SCDKeys.h b/SystemConfiguration.fproj/SCDKeys.h index 4c1f2b6..b2ee9d7 100644 --- a/SystemConfiguration.fproj/SCDKeys.h +++ b/SystemConfiguration.fproj/SCDKeys.h @@ -20,44 +20,18 @@ * @APPLE_LICENSE_HEADER_END@ */ -/* - * SCDKeys.h - */ - #ifndef _SCDKEYS_H #define _SCDKEYS_H -#include -#include - -__BEGIN_DECLS - -/* - * SCDKeyCreate* - * - convenience routines that create a CFString key for an item in the cache - */ - -/* - * Function: SCDKeyCreate - * Purpose: - * Creates a cache key using the given format. - */ -CFStringRef SCDKeyCreate (CFStringRef fmt, - ...); - -CFStringRef SCDKeyCreateNetworkGlobalEntity (CFStringRef domain, - CFStringRef entity); - -CFStringRef SCDKeyCreateNetworkInterface (CFStringRef domain); - -CFStringRef SCDKeyCreateNetworkInterfaceEntity (CFStringRef domain, - CFStringRef ifname, - CFStringRef entity); - -CFStringRef SCDKeyCreateNetworkServiceEntity (CFStringRef domain, - CFStringRef serviceID, - CFStringRef entity); - -__END_DECLS +#ifndef _SYSTEMCONFIGURATION_H +#warning Your code has directly included the (old) +#warning header file. Please dont do that. Use the top-level header file: +#warning +#warning +#warning +#warning Note: the dynamic store key creation APIs have been moved out of +#warning the SCDKeys.h header file. +#include /* ...and try to keep everyone happy */ +#endif #endif /* _SCDKEYS_H */ diff --git a/SystemConfiguration.fproj/SCDList.c b/SystemConfiguration.fproj/SCDList.c index 1efabf3..85055cd 100644 --- a/SystemConfiguration.fproj/SCDList.c +++ b/SystemConfiguration.fproj/SCDList.c @@ -20,93 +20,94 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - - -static CFComparisonResult -sort_keys(const void *p1, const void *p2, void *context) { - CFStringRef key1 = (CFStringRef)p1; - CFStringRef key2 = (CFStringRef)p2; - return CFStringCompare(key1, key2, 0); -} - -SCDStatus -SCDList(SCDSessionRef session, CFStringRef key, int regexOptions, CFArrayRef *subKeys) +CFArrayRef +SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - CFDataRef xmlKey; /* serialized key */ - xmlData_t myKeyRef; - CFIndex myKeyLen; - CFDataRef xmlData; /* data (XML serialized) */ - xmlDataOut_t xmlDataRef; /* serialized data */ - int xmlDataLen; - SCDStatus scd_status; - CFArrayRef allKeys; - CFMutableArrayRef sortedKeys; - CFStringRef xmlError; - - SCDLog(LOG_DEBUG, CFSTR("SCDList:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" regexOptions = %0o"), regexOptions); - - if (key == NULL) { - return SCD_INVALIDARGUMENT; /* no key specified */ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlPattern; /* serialized pattern */ + xmlData_t myPatternRef; + CFIndex myPatternLen; + CFDataRef xmlData; /* data (XML serialized) */ + xmlDataOut_t xmlDataRef; /* serialized data */ + int xmlDataLen; + int sc_status; + CFArrayRef allKeys; + CFStringRef xmlError; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyKeyList:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" pattern = %@"), pattern); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return NULL; } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; + if (storePrivate->server == MACH_PORT_NULL) { + _SCErrorSet(kSCStatusNoStoreServer); + return NULL; } - /* serialize the key */ - xmlKey = CFPropertyListCreateXMLData(NULL, key); - myKeyRef = (xmlData_t)CFDataGetBytePtr(xmlKey); - myKeyLen = CFDataGetLength(xmlKey); + /* serialize the pattern */ + xmlPattern = CFPropertyListCreateXMLData(NULL, pattern); + myPatternRef = (xmlData_t)CFDataGetBytePtr(xmlPattern); + myPatternLen = CFDataGetLength(xmlPattern); - /* send the key & fetch the associated data from the server */ - status = configlist(sessionPrivate->server, - myKeyRef, - myKeyLen, - regexOptions, + /* send the pattern & fetch the associated data from the server */ + status = configlist(storePrivate->server, + myPatternRef, + myPatternLen, + TRUE, /* isRegex == TRUE */ &xmlDataRef, &xmlDataLen, - (int *)&scd_status); + (int *)&sc_status); /* clean up */ - CFRelease(xmlKey); + CFRelease(xmlPattern); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configlist(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configlist(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return NULL; } - if (scd_status != SCD_OK) { + if (sc_status != kSCStatusOK) { status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } - *subKeys = NULL; - return scd_status; + _SCErrorSet(sc_status); + return NULL; } /* un-serialize the list of keys */ xmlData = CFDataCreate(NULL, xmlDataRef, xmlDataLen); status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } allKeys = CFPropertyListCreateFromXMLData(NULL, @@ -114,19 +115,16 @@ SCDList(SCDSessionRef session, CFStringRef key, int regexOptions, CFArrayRef *su kCFPropertyListImmutable, &xmlError); CFRelease(xmlData); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() list: %s"), xmlError); - return SCD_FAILED; + if (!allKeys) { + if (xmlError) { + SCLog(_sc_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() list: %@"), + xmlError); + CFRelease(xmlError); + } + _SCErrorSet(kSCStatusFailed); + return NULL; } - myKeyLen = CFArrayGetCount(allKeys); - sortedKeys = CFArrayCreateMutableCopy(NULL, myKeyLen, allKeys); - CFRelease(allKeys); - CFArraySortValues(sortedKeys, - CFRangeMake(0, myKeyLen), - sort_keys, - NULL); - - *subKeys = sortedKeys; - return scd_status; + return allKeys; } diff --git a/SystemConfiguration.fproj/SCDLock.c b/SystemConfiguration.fproj/SCDLock.c index ff1a1d4..227c583 100644 --- a/SystemConfiguration.fproj/SCDLock.c +++ b/SystemConfiguration.fproj/SCDLock.c @@ -20,37 +20,61 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDLock(SCDSessionRef session) +Boolean +SCDynamicStoreLock(SCDynamicStoreRef store) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + int sc_status; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreLock:")); - SCDLog(LOG_DEBUG, CFSTR("SCDLock:")); + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; + } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } /* get the lock from the server */ - status = configlock(sessionPrivate->server, (int *)&scd_status); + status = configlock(storePrivate->server, (int *)&sc_status); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configlock(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configlock(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } + + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDNotifierAdd.c b/SystemConfiguration.fproj/SCDNotifierAdd.c index 689cb2e..392ca27 100644 --- a/SystemConfiguration.fproj/SCDNotifierAdd.c +++ b/SystemConfiguration.fproj/SCDNotifierAdd.c @@ -20,50 +20,67 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDNotifierAdd(SCDSessionRef session, CFStringRef key, int regexOptions) +Boolean +SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - CFDataRef xmlKey; /* serialized key */ - xmlData_t myKeyRef; - CFIndex myKeyLen; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlKey; /* serialized key */ + xmlData_t myKeyRef; + CFIndex myKeyLen; + int sc_status; - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierAdd:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" regexOptions = %0o"), regexOptions); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddWatchedKey:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE"); - if (key == NULL) { - return SCD_INVALIDARGUMENT; /* no key specified */ + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } /* * add new key after checking if key has already been defined */ - if (regexOptions & kSCDRegexKey) { - if (CFSetContainsValue(sessionPrivate->reKeys, key)) - return SCD_EXISTS; /* sorry, key already exists in notifier list */ - CFSetAddValue(sessionPrivate->reKeys, key); /* add key to this sessions notifier list */ + if (isRegex) { + if (CFSetContainsValue(storePrivate->reKeys, key)) { + /* sorry, key already exists in notifier list */ + _SCErrorSet(kSCStatusKeyExists); + return FALSE; + } + CFSetAddValue(storePrivate->reKeys, key); /* add key to this sessions notifier list */ } else { - if (CFSetContainsValue(sessionPrivate->keys, key)) - return SCD_EXISTS; /* sorry, key already exists in notifier list */ - CFSetAddValue(sessionPrivate->keys, key); /* add key to this sessions notifier list */ + if (CFSetContainsValue(storePrivate->keys, key)) { + /* sorry, key already exists in notifier list */ + _SCErrorSet(kSCStatusKeyExists); + return FALSE; + } + CFSetAddValue(storePrivate->keys, key); /* add key to this sessions notifier list */ } /* serialize the key */ @@ -72,22 +89,28 @@ SCDNotifierAdd(SCDSessionRef session, CFStringRef key, int regexOptions) myKeyLen = CFDataGetLength(xmlKey); /* send the key & data to the server */ - status = notifyadd(sessionPrivate->server, + status = notifyadd(storePrivate->server, myKeyRef, myKeyLen, - regexOptions, - (int *)&scd_status); + isRegex, + (int *)&sc_status); /* clean up */ CFRelease(xmlKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("notifyadd(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyadd(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } + + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDNotifierCancel.c b/SystemConfiguration.fproj/SCDNotifierCancel.c index 3ee6d14..e1a236b 100644 --- a/SystemConfiguration.fproj/SCDNotifierCancel.c +++ b/SystemConfiguration.fproj/SCDNotifierCancel.c @@ -20,80 +20,94 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 31, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDNotifierCancel(SCDSessionRef session) +Boolean +SCDynamicStoreNotifyCancel(SCDynamicStoreRef store) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + int sc_status; - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierCancel:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCancel:")); - if (session == NULL) { - return SCD_NOSESSION; /* you can't do anything without a session */ + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - if (sessionPrivate->notifyStatus == NotifierNotRegistered) { - /* nothing to do, no notifications have been registered */ - return SCD_OK; + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } - /* if SCDNotifierInformViaCallback() active, stop the background thread */ - if (sessionPrivate->callbackFunction != NULL) { - - if (SCDOptionGet(session, kSCDOptionUseCFRunLoop)) { - SCDLog(LOG_DEBUG, CFSTR(" cancel callback runloop source")); - - /* XXX invalidating the port is not sufficient, remove the run loop source */ - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), - sessionPrivate->callbackRunLoopSource, + switch (storePrivate->notifyStatus) { + case NotifierNotRegistered : + /* if no notifications have been registered */ + return TRUE; + case Using_NotifierInformViaRunLoop : + /* once activated, a RunLoop notifier cannot be cancelled */ + _SCErrorSet(kSCStatusNotifierActive); + return FALSE; + case Using_NotifierInformViaCallback : + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" cancel callback runloop source")); + + /* remove the run loop source */ + CFRunLoopRemoveSource(storePrivate->callbackRunLoop, + storePrivate->callbackRunLoopSource, kCFRunLoopDefaultMode); - CFRelease(sessionPrivate->callbackRunLoopSource); + CFRelease(storePrivate->callbackRunLoopSource); /* invalidate port */ - CFMachPortInvalidate(sessionPrivate->callbackPort); - CFRelease(sessionPrivate->callbackPort); - } else { - int ts; - - SCDLog(LOG_DEBUG, CFSTR(" cancel callback thread")); - ts = pthread_cancel(sessionPrivate->callbackHelper); - if (ts != 0) { - SCDLog(LOG_DEBUG, CFSTR(" pthread_cancel(): %s"), strerror(ts)); - } - } - - sessionPrivate->callbackFunction = NULL; - sessionPrivate->callbackArgument = NULL; - sessionPrivate->callbackPort = NULL; - sessionPrivate->callbackRunLoopSource = NULL; /* XXX */ - sessionPrivate->callbackHelper = NULL; - } - - if (sessionPrivate->server == MACH_PORT_NULL) { - return SCD_NOSESSION; /* you must have an open session to play */ + CFMachPortInvalidate(storePrivate->callbackPort); + CFRelease(storePrivate->callbackPort); + + storePrivate->callbackArgument = NULL; + storePrivate->callbackFunction = NULL; + storePrivate->callbackRunLoop = NULL; + storePrivate->callbackRunLoopSource = NULL; + storePrivate->callbackPort = NULL; + break; + default : + break; } - status = notifycancel(sessionPrivate->server, (int *)&scd_status); + status = notifycancel(storePrivate->server, (int *)&sc_status); /* set notifier inactive */ - sessionPrivate->notifyStatus = NotifierNotRegistered; + storePrivate->notifyStatus = NotifierNotRegistered; if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("notifycancel(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifycancel(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } + + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDNotifierGetChanges.c b/SystemConfiguration.fproj/SCDNotifierGetChanges.c index 1fbf028..71ecfb2 100644 --- a/SystemConfiguration.fproj/SCDNotifierGetChanges.c +++ b/SystemConfiguration.fproj/SCDNotifierGetChanges.c @@ -20,71 +20,79 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -static CFComparisonResult -sort_keys(const void *p1, const void *p2, void *context) { - CFStringRef key1 = (CFStringRef)p1; - CFStringRef key2 = (CFStringRef)p2; - return CFStringCompare(key1, key2, 0); -} - - -SCDStatus -SCDNotifierGetChanges(SCDSessionRef session, CFArrayRef *notifierKeys) +CFArrayRef +SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - CFDataRef xmlData; /* data (XML serialized) */ - xmlDataOut_t xmlDataRef; /* serialized data */ - int xmlDataLen; - SCDStatus scd_status; - CFArrayRef allKeys; - CFStringRef xmlError; - CFIndex keyCnt; - CFMutableArrayRef sortedKeys; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlData; /* data (XML serialized) */ + xmlDataOut_t xmlDataRef; /* serialized data */ + int xmlDataLen; + int sc_status; + CFArrayRef allKeys; + CFStringRef xmlError; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyNotifiedKeys:")); - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierGetChanges:")); + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return NULL; + } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; + if (storePrivate->server == MACH_PORT_NULL) { + _SCErrorSet(kSCStatusNoStoreServer); + return NULL; } /* send the key & fetch the associated data from the server */ - status = notifychanges(sessionPrivate->server, + status = notifychanges(storePrivate->server, &xmlDataRef, &xmlDataLen, - (int *)&scd_status); + (int *)&sc_status); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("notifychanges(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifychanges(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return NULL; } - if (scd_status != SCD_OK) { + if (sc_status != kSCStatusOK) { status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } - *notifierKeys = NULL; - return scd_status; + _SCErrorSet(sc_status); + return NULL; } /* un-serialize the list of keys which have changed */ xmlData = CFDataCreate(NULL, xmlDataRef, xmlDataLen); status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } allKeys = CFPropertyListCreateFromXMLData(NULL, @@ -92,19 +100,16 @@ SCDNotifierGetChanges(SCDSessionRef session, CFArrayRef *notifierKeys) kCFPropertyListImmutable, &xmlError); CFRelease(xmlData); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() list: %s"), xmlError); - return SCD_FAILED; + if (!allKeys) { + if (xmlError) { + SCLog(_sc_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() list: %@"), + xmlError); + CFRelease(xmlError); + } + _SCErrorSet(kSCStatusFailed); + return NULL; } - keyCnt = CFArrayGetCount(allKeys); - sortedKeys = CFArrayCreateMutableCopy(NULL, keyCnt, allKeys); - CFRelease(allKeys); - CFArraySortValues(sortedKeys, - CFRangeMake(0, keyCnt), - sort_keys, - NULL); - - *notifierKeys = sortedKeys; - return scd_status; + return allKeys; } diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c b/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c index 481d5b1..9b1cf56 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c @@ -20,256 +20,406 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 31, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" +#include "v1Compatibility.h" static void informCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) { - SCDSessionRef session = (SCDSessionRef)info; - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - mach_msg_empty_rcv_t *buf = msg; - mach_msg_id_t msgid = buf->header.msgh_id; - SCDCallbackRoutine_t cbFunc = sessionPrivate->callbackFunction; - void *cbArg = sessionPrivate->callbackArgument; + SCDynamicStoreRef store = (SCDynamicStoreRef)info; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + mach_msg_empty_rcv_t *buf = msg; + mach_msg_id_t msgid = buf->header.msgh_id; + SCDynamicStoreCallBack_v1 cbFunc = storePrivate->callbackFunction; + void *cbArg = storePrivate->callbackArgument; if (msgid == MACH_NOTIFY_NO_SENDERS) { /* the server died, disable additional callbacks */ - SCDLog(LOG_DEBUG, CFSTR(" notifier port closed, disabling notifier")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" notifier port closed, disabling notifier")); } else if (cbFunc == NULL) { /* there is no (longer) a callback function, disable additional callbacks */ - SCDLog(LOG_DEBUG, CFSTR(" no callback function, disabling notifier")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" no callback function, disabling notifier")); } else { - SCDLog(LOG_DEBUG, CFSTR(" executing notifiction function")); - if ((*cbFunc)(session, cbArg)) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" executing notifiction function")); + if ((*cbFunc)(store, cbArg)) { /* * callback function returned success. */ return; } else { - SCDLog(LOG_DEBUG, CFSTR(" callback returned error, disabling notifier")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" callback returned error, disabling notifier")); } } #ifdef DEBUG - if (port != sessionPrivate->callbackPort) { - SCDLog(LOG_DEBUG, CFSTR("informCallback, why is port != callbackPort?")); + if (port != storePrivate->callbackPort) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("informCallback, why is port != callbackPort?")); } #endif /* DEBUG */ - /* we have encountered some type of error, disable additional callbacks */ - - /* XXX invalidating the port is not sufficient, remove the run loop source */ + /* remove the run loop source */ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), - sessionPrivate->callbackRunLoopSource, + storePrivate->callbackRunLoopSource, kCFRunLoopDefaultMode); - CFRelease(sessionPrivate->callbackRunLoopSource); + CFRelease(storePrivate->callbackRunLoopSource); /* invalidate port */ - CFMachPortInvalidate(port); - CFRelease(port); + CFMachPortInvalidate(storePrivate->callbackPort); + CFRelease(storePrivate->callbackPort); - sessionPrivate->notifyStatus = NotifierNotRegistered; - sessionPrivate->callbackFunction = NULL; - sessionPrivate->callbackArgument = NULL; - sessionPrivate->callbackPort = NULL; - sessionPrivate->callbackRunLoopSource = NULL; /* XXX */ + /* disable notifier */ + storePrivate->notifyStatus = NotifierNotRegistered; + storePrivate->callbackArgument = NULL; + storePrivate->callbackFunction = NULL; + storePrivate->callbackPort = NULL; + storePrivate->callbackRunLoop = NULL; + storePrivate->callbackRunLoopSource = NULL; return; } -static void -cleanupMachPort(void *ptr) +Boolean +SCDynamicStoreNotifyCallback(SCDynamicStoreRef store, + CFRunLoopRef runLoop, + SCDynamicStoreCallBack_v1 func, + void *arg) { - mach_port_t *port = (mach_port_t *)ptr; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + mach_port_t port; + mach_port_t oldNotify; + int sc_status; + CFMachPortContext context = { 0, (void *)store, NULL, NULL, NULL }; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCallback:")); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; + } - SCDLog(LOG_DEBUG, CFSTR(" cleaning up notification port %d"), *port); - if (*port != MACH_PORT_NULL) { - (void) mach_port_destroy(mach_task_self(), *port); - free(port); + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } - return; + if (storePrivate->notifyStatus != NotifierNotRegistered) { + /* sorry, you can only have one notification registered at once */ + _SCErrorSet(kSCStatusNotifierActive); + return FALSE; + } + + /* Allocating port (for server response) */ + storePrivate->callbackPort = CFMachPortCreate(NULL, + informCallback, + &context, + NULL); + + /* Request a notification when/if the server dies */ + port = CFMachPortGetPort(storePrivate->callbackPort); + status = mach_port_request_notification(mach_task_self(), + port, + MACH_NOTIFY_NO_SENDERS, + 1, + port, + MACH_MSG_TYPE_MAKE_SEND_ONCE, + &oldNotify); + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); + CFMachPortInvalidate(storePrivate->callbackPort); + CFRelease(storePrivate->callbackPort); + _SCErrorSet(status); + return FALSE; + } + + if (oldNotify != MACH_PORT_NULL) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("SCDynamicStoreNotifyCallback(): why is oldNotify != MACH_PORT_NULL?")); + } + + /* Requesting notification via mach port */ + status = notifyviaport(storePrivate->server, + port, + 0, + (int *)&sc_status); + + if (status != KERN_SUCCESS) { + if (status != MACH_SEND_INVALID_DEST) + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status)); + CFMachPortInvalidate(storePrivate->callbackPort); + CFRelease(storePrivate->callbackPort); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } + + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; + } + + /* set notifier active */ + storePrivate->notifyStatus = Using_NotifierInformViaCallback; + + /* Creating/adding a run loop source for the port */ + storePrivate->callbackArgument = arg; + storePrivate->callbackFunction = func; + storePrivate->callbackRunLoop = runLoop; + storePrivate->callbackRunLoopSource = + CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0); + + CFRunLoopAddSource(storePrivate->callbackRunLoop, + storePrivate->callbackRunLoopSource, + kCFRunLoopDefaultMode); + + return TRUE; } -static void * -watcherThread(void *arg) +static void +rlsCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) { - SCDSessionRef session = (SCDSessionRef)arg; - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - SCDCallbackRoutine_t cbFunc = sessionPrivate->callbackFunction; - void *cbArg = sessionPrivate->callbackArgument; - mach_port_t *port = malloc(sizeof(mach_port_t)); + mach_msg_empty_rcv_t *buf = msg; + mach_msg_id_t msgid = buf->header.msgh_id; + SCDynamicStoreRef store = (SCDynamicStoreRef)info; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + + if (msgid == MACH_NOTIFY_NO_SENDERS) { + /* the server died, disable additional callbacks */ + SCLog(_sc_verbose, LOG_INFO, CFSTR(" rlsCallback(), notifier port closed")); - *port = CFMachPortGetPort(sessionPrivate->callbackPort); - pthread_cleanup_push(cleanupMachPort, (void *)port); +#ifdef DEBUG + if (port != storePrivate->callbackPort) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("rlsCallback(), why is port != callbackPort?")); + } +#endif /* DEBUG */ - while (TRUE) { - mach_msg_id_t msgid; + /* remove the run loop source(s) */ + CFRunLoopSourceInvalidate(storePrivate->callbackRunLoopSource); + CFRelease(storePrivate->callbackRunLoopSource); - SCDLog(LOG_DEBUG, CFSTR("Callback thread waiting, port=%d, tid=0x%08x"), - *port, pthread_self()); + /* invalidate port */ + CFMachPortInvalidate(storePrivate->callbackPort); + CFRelease(storePrivate->callbackPort); - msgid = _waitForMachMessage(*port); + return; + } - if (msgid == MACH_NOTIFY_NO_SENDERS) { - /* the server closed the notifier port, disable additional callbacks */ - SCDLog(LOG_DEBUG, CFSTR(" notifier port closed, disabling notifier")); - break; - } + /* signal the real runloop source */ + CFRunLoopSourceSignal(storePrivate->rls); + return; +} - if (msgid == -1) { - mach_port_type_t pt; - /* an error was detected, disable additional callbacks */ - SCDLog(LOG_DEBUG, CFSTR(" server failure, disabling notifier")); +static void +rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) +{ + SCDynamicStoreRef store = (SCDynamicStoreRef)info; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; - /* check if the server connection is not valid, close if necessary */ - if ((mach_port_type(mach_task_self(), sessionPrivate->server, &pt) == KERN_SUCCESS) && - (pt & MACH_PORT_TYPE_DEAD_NAME)) { - SCDLog(LOG_DEBUG, CFSTR(" server process died, destroying (dead) port")); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - } - break; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("schedule notifications for mode %@"), mode); + + if (storePrivate->rlsRefs++ == 0) { + CFMachPortContext context = { 0, (void *)store, NULL, NULL, NULL }; + mach_port_t oldNotify; + mach_port_t port; + int sc_status; + kern_return_t status; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" activate callback runloop source")); + + /* Allocating port (for server response) */ + status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status)); + return; } + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" port = %d"), port); - if (cbFunc == NULL) { - /* there is no (longer) a callback function, disable additional callbacks */ - SCDLog(LOG_DEBUG, CFSTR(" no callback function, disabling notifier")); - break; + status = mach_port_insert_right(mach_task_self(), + port, + port, + MACH_MSG_TYPE_MAKE_SEND); + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), port); + return; } - SCDLog(LOG_DEBUG, CFSTR(" executing notifiction function")); + /* Request a notification when/if the server dies */ + status = mach_port_request_notification(mach_task_self(), + port, + MACH_NOTIFY_NO_SENDERS, + 1, + port, + MACH_MSG_TYPE_MAKE_SEND_ONCE, + &oldNotify); + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), port); + return; + } - if (!(*cbFunc)(session, cbArg)) { - /* - * callback function returned an error, exit the thread - */ - break; + if (oldNotify != MACH_PORT_NULL) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("rlsSchedule(): why is oldNotify != MACH_PORT_NULL?")); } - } + status = notifyviaport(storePrivate->server, port, 0, (int *)&sc_status); + if (status != KERN_SUCCESS) { + if (status != MACH_SEND_INVALID_DEST) + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), port); + port = MACH_PORT_NULL; + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + return; + } - /* - * pop the cleanup routine for the "port" mach port. We end up calling - * mach_port_destroy() in the process. - */ - pthread_cleanup_pop(1); + storePrivate->callbackPort = CFMachPortCreateWithPort(NULL, port, rlsCallback, &context, NULL); + storePrivate->callbackRunLoopSource = CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0); + } - pthread_exit (NULL); - return NULL; + CFRunLoopAddSource(rl, storePrivate->callbackRunLoopSource, mode); + return; } -SCDStatus -SCDNotifierInformViaCallback(SCDSessionRef session, SCDCallbackRoutine_t func, void *arg) +static void +rlsCancel(void *info, CFRunLoopRef rl, CFStringRef mode) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - mach_port_t port; - mach_port_t oldNotify; - SCDStatus scd_status; - CFMachPortContext context = { 0, (void *)session, NULL, NULL, NULL }; + SCDynamicStoreRef store = (SCDynamicStoreRef)info; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierInformViaCallback:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("cancel notifications for mode %@"), mode); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ - } + CFRunLoopRemoveSource(rl, storePrivate->callbackRunLoopSource, mode); + if (--storePrivate->rlsRefs == 0) { + int sc_status; + kern_return_t status; - if (sessionPrivate->notifyStatus != NotifierNotRegistered) { - /* sorry, you can only have one notification registered at once */ - return SCD_NOTIFIERACTIVE; - } + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" cancel callback runloop source")); - if (func == NULL) { - /* sorry, you must specify a callback function */ - return SCD_INVALIDARGUMENT; - } + /* remove the run loop source */ + CFRelease(storePrivate->callbackRunLoopSource); - /* Allocating port (for server response) */ - sessionPrivate->callbackPort = CFMachPortCreate(NULL, - informCallback, - &context, - NULL); + /* invalidate port */ + CFMachPortInvalidate(storePrivate->callbackPort); + CFRelease(storePrivate->callbackPort); - /* Request a notification when/if the server dies */ - port = CFMachPortGetPort(sessionPrivate->callbackPort); - status = mach_port_request_notification(mach_task_self(), - port, - MACH_NOTIFY_NO_SENDERS, - 1, - port, - MACH_MSG_TYPE_MAKE_SEND_ONCE, - &oldNotify); - if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); - CFMachPortInvalidate(sessionPrivate->callbackPort); - CFRelease(sessionPrivate->callbackPort); - return SCD_FAILED; + status = notifycancel(storePrivate->server, (int *)&sc_status); + if (status != KERN_SUCCESS) { + if (status != MACH_SEND_INVALID_DEST) + SCLog(_sc_verbose, LOG_INFO, CFSTR("notifycancel(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + return; + } } + return; +} -#ifdef DEBUG - if (oldNotify != MACH_PORT_NULL) { - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierInformViaCallback(): why is oldNotify != MACH_PORT_NULL?")); +static void +rlsPerform(void *info) +{ + CFArrayRef changedKeys; + void *context_info; + void (*context_release)(const void *); + SCDynamicStoreCallBack rlsFunction; + SCDynamicStoreRef store = (SCDynamicStoreRef)info; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" executing notifiction function")); + + changedKeys = SCDynamicStoreCopyNotifiedKeys(store); + rlsFunction = storePrivate->rlsFunction; + + if (NULL != storePrivate->rlsContext.retain) { + context_info = (void *)storePrivate->rlsContext.retain(storePrivate->rlsContext.info); + context_release = storePrivate->rlsContext.release; + } else { + context_info = storePrivate->rlsContext.info; + context_release = NULL; + } + (*rlsFunction)(store, changedKeys, storePrivate->rlsContext.info); + if (context_release) { + context_release(context_info); } -#endif /* DEBUG */ - /* Requesting notification via mach port */ - status = notifyviaport(sessionPrivate->server, - port, - 0, - (int *)&scd_status); + CFRelease(changedKeys); + return; +} - if (status != KERN_SUCCESS) { - if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status)); - CFMachPortInvalidate(sessionPrivate->callbackPort); - CFRelease(sessionPrivate->callbackPort); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + +CFRunLoopSourceRef +SCDynamicStoreCreateRunLoopSource(CFAllocatorRef allocator, + SCDynamicStoreRef store, + CFIndex order) +{ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCreateRunLoopSource:")); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return NULL; } - if (scd_status != SCD_OK) { - return scd_status; + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return NULL; } - /* set notifier active */ - sessionPrivate->notifyStatus = Using_NotifierInformViaCallback; - sessionPrivate->callbackFunction = func; - sessionPrivate->callbackArgument = arg; - - if (SCDOptionGet(session, kSCDOptionUseCFRunLoop)) { - /* Creating/adding a run loop source for the port */ - sessionPrivate->callbackRunLoopSource = - CFMachPortCreateRunLoopSource(NULL, sessionPrivate->callbackPort, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), - sessionPrivate->callbackRunLoopSource, - kCFRunLoopDefaultMode); - } else { - pthread_attr_t tattr; - - SCDLog(LOG_DEBUG, CFSTR("Starting background thread to watch for notifications...")); - pthread_attr_init(&tattr); - pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM); - pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); - pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack - pthread_create(&sessionPrivate->callbackHelper, - &tattr, - watcherThread, - (void *)session); - pthread_attr_destroy(&tattr); - SCDLog(LOG_DEBUG, CFSTR(" thread id=0x%08x"), sessionPrivate->callbackHelper); + switch (storePrivate->notifyStatus) { + case NotifierNotRegistered : + case Using_NotifierInformViaRunLoop : + /* set notifier active */ + storePrivate->notifyStatus = Using_NotifierInformViaRunLoop; + break; + default : + /* sorry, you can only have one notification registered at once */ + _SCErrorSet(kSCStatusNotifierActive); + return NULL; } - return SCD_OK; + if (!storePrivate->rls) { + CFRunLoopSourceContext context; + + context.version = 0; + context.info = (void *)store; + context.retain = (const void *(*)(const void *))CFRetain; + context.release = (void (*)(const void *))CFRelease; + context.copyDescription = (CFStringRef (*)(const void *))CFCopyDescription; + context.equal = (Boolean (*)(const void *, const void *))CFEqual; + context.hash = (CFHashCode (*)(const void *))CFHash; + context.schedule = rlsSchedule; + context.cancel = rlsCancel; + context.perform = rlsPerform; + + storePrivate->rls = CFRunLoopSourceCreate(allocator, order, &context); + } + + return (CFRunLoopSourceRef)CFRetain(storePrivate->rls); } + diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaFD.c b/SystemConfiguration.fproj/SCDNotifierInformViaFD.c index 48ba04f..88f5de0 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaFD.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaFD.c @@ -20,44 +20,65 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * April 5, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include -#include -#include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" +#include +#include +#include +#include +#include -SCDStatus -SCDNotifierInformViaFD(SCDSessionRef session, - int32_t identifier, - int *fd) +Boolean +SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, + int32_t identifier, + int *fd) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - SCDStatus scd_status; - struct sockaddr_un un; - int sock; - - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierInformViaFD:")); + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + int sc_status; + struct sockaddr_un un; + int sock; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyFileDescriptor:")); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; + } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } - if (sessionPrivate->notifyStatus != NotifierNotRegistered) { + if (storePrivate->notifyStatus != NotifierNotRegistered) { /* sorry, you can only have one notification registered at once */ - return SCD_NOTIFIERACTIVE; + _SCErrorSet(kSCStatusNotifierActive); + return FALSE; } if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - SCDLog(LOG_NOTICE, CFSTR("socket: %s"), strerror(errno)); - return SCD_FAILED; + _SCErrorSet(errno); + SCLog(_sc_verbose, LOG_NOTICE, CFSTR("socket: %s"), strerror(errno)); + return FALSE; } /* establish a UNIX domain socket for server->client notification */ @@ -67,45 +88,49 @@ SCDNotifierInformViaFD(SCDSessionRef session, sizeof(un.sun_path)-1, "%s%s-%d", _PATH_VARTMP, - "SCDNotifierInformViaFD", - sessionPrivate->server); + "SCDynamicStoreNotifyFileDescriptor", + storePrivate->server); if (bind(sock, (struct sockaddr *)&un, sizeof(un)) == -1) { - SCDLog(LOG_NOTICE, CFSTR("bind: %s"), strerror(errno)); + _SCErrorSet(errno); + SCLog(_sc_verbose, LOG_NOTICE, CFSTR("bind: %s"), strerror(errno)); (void) close(sock); - return SCD_FAILED; + return FALSE; } if (listen(sock, 0) == -1) { - SCDLog(LOG_NOTICE, CFSTR("listen: %s"), strerror(errno)); + _SCErrorSet(errno); + SCLog(_sc_verbose, LOG_NOTICE, CFSTR("listen: %s"), strerror(errno)); (void) close(sock); - return SCD_FAILED; + return FALSE; } - status = notifyviafd(sessionPrivate->server, + status = notifyviafd(storePrivate->server, un.sun_path, strlen(un.sun_path), identifier, - (int *)&scd_status); + (int *)&sc_status); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("notifyviafd(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviafd(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; } *fd = accept(sock, 0, 0); if (*fd == -1) { - SCDLog(LOG_NOTICE, CFSTR("accept: %s"), strerror(errno)); + _SCErrorSet(errno); + SCLog(_sc_verbose, LOG_NOTICE, CFSTR("accept: %s"), strerror(errno)); (void) close(sock); - return SCD_FAILED; + return FALSE; } (void) close(sock); /* set notifier active */ - sessionPrivate->notifyStatus = Using_NotifierInformViaFD; + storePrivate->notifyStatus = Using_NotifierInformViaFD; - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c b/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c index 848579f..63ce3d3 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c @@ -20,50 +20,71 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 31, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDNotifierInformViaMachPort(SCDSessionRef session, mach_msg_id_t identifier, mach_port_t *port) +Boolean +SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier, mach_port_t *port) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - mach_port_t oldNotify; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + mach_port_t oldNotify; + int sc_status; - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierInformViaMachPort:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort:")); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; + } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } - if (sessionPrivate->notifyStatus != NotifierNotRegistered) { + if (storePrivate->notifyStatus != NotifierNotRegistered) { /* sorry, you can only have one notification registered at once */ - return SCD_NOTIFIERACTIVE; + _SCErrorSet(kSCStatusNotifierActive); + return FALSE; } - SCDLog(LOG_DEBUG, CFSTR("Allocating port (for server response)")); + /* Allocating port (for server response) */ status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, port); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status)); - return SCD_FAILED; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status)); + _SCErrorSet(status); + return FALSE; } - SCDLog(LOG_DEBUG, CFSTR(" port = %d"), *port); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" port = %d"), *port); status = mach_port_insert_right(mach_task_self(), *port, *port, MACH_MSG_TYPE_MAKE_SEND); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status)); (void) mach_port_destroy(mach_task_self(), *port); *port = MACH_PORT_NULL; - return SCD_FAILED; + _SCErrorSet(status); + return FALSE; } /* Request a notification when/if the server dies */ @@ -75,35 +96,35 @@ SCDNotifierInformViaMachPort(SCDSessionRef session, mach_msg_id_t identifier, ma MACH_MSG_TYPE_MAKE_SEND_ONCE, &oldNotify); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); (void) mach_port_destroy(mach_task_self(), *port); *port = MACH_PORT_NULL; - return SCD_FAILED; + _SCErrorSet(status); + return FALSE; } -#ifdef DEBUG if (oldNotify != MACH_PORT_NULL) { - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierInformViaMachPort(): why is oldNotify != MACH_PORT_NULL?")); + SCLog(_sc_verbose, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort(): why is oldNotify != MACH_PORT_NULL?")); } -#endif /* DEBUG */ - status = notifyviaport(sessionPrivate->server, + status = notifyviaport(storePrivate->server, *port, identifier, - (int *)&scd_status); + (int *)&sc_status); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status)); (void) mach_port_destroy(mach_task_self(), *port); *port = MACH_PORT_NULL; - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; } /* set notifier active */ - sessionPrivate->notifyStatus = Using_NotifierInformViaMachPort; + storePrivate->notifyStatus = Using_NotifierInformViaMachPort; - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c b/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c index 01e0c14..7036a90 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c @@ -20,64 +20,74 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 31, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDNotifierInformViaSignal(SCDSessionRef session, pid_t pid, int sig) +Boolean +SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - - kern_return_t status; - SCDStatus scd_status; - task_t task; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + int sc_status; + task_t task; - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierInformViaSignal:")); - SCDLog(LOG_DEBUG, CFSTR(" pid = %d"), pid); - SCDLog(LOG_DEBUG, CFSTR(" sig = %d"), sig); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifySignal:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" pid = %d"), pid); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" sig = %d"), sig); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - if (SCDOptionGet(NULL, kSCDOptionIsServer)) { - /* sorry, neither the server nor any plug-ins can "wait" */ - return SCD_FAILED; + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } - if (sessionPrivate->notifyStatus != NotifierNotRegistered) { + if (storePrivate->notifyStatus != NotifierNotRegistered) { /* sorry, you can only have one notification registered at once */ - return SCD_NOTIFIERACTIVE; - } - - if ((sig <= 0) || (sig > NSIG)) { - /* sorry, you must specify a valid signal */ - return SCD_INVALIDARGUMENT; + _SCErrorSet(kSCStatusNotifierActive); + return FALSE; } status = task_for_pid(mach_task_self(), pid, &task); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("task_for_pid(): %s"), mach_error_string(status)); - return SCD_FAILED; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("task_for_pid(): %s"), mach_error_string(status)); + _SCErrorSet(status); + return FALSE; } - status = notifyviasignal(sessionPrivate->server, task, sig, (int *)&scd_status); + status = notifyviasignal(storePrivate->server, task, sig, (int *)&sc_status); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("notifyviasignal(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviasignal(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; } /* set notifier active */ - sessionPrivate->notifyStatus = Using_NotifierInformViaSignal; + storePrivate->notifyStatus = Using_NotifierInformViaSignal; - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDNotifierList.c b/SystemConfiguration.fproj/SCDNotifierList.c index e821232..2e006d3 100644 --- a/SystemConfiguration.fproj/SCDNotifierList.c +++ b/SystemConfiguration.fproj/SCDNotifierList.c @@ -20,54 +20,46 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include -#include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" +#include +#include +#include "SCDynamicStoreInternal.h" -static CFComparisonResult -sort_keys(const void *p1, const void *p2, void *context) { - CFStringRef key1 = (CFStringRef)p1; - CFStringRef key2 = (CFStringRef)p2; - return CFStringCompare(key1, key2, 0); -} - - -SCDStatus -SCDNotifierList(SCDSessionRef session, int regexOptions, CFArrayRef *notifierKeys) +CFArrayRef +SCDynamicStoreCopyWatchedKeyList(SCDynamicStoreRef store, Boolean isRegex) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - CFIndex keyCnt; - void **keyRefs; - CFArrayRef keys; - CFMutableArrayRef sortedKeys; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + CFIndex keyCnt; + void **keyRefs; + CFArrayRef watchedKeys = NULL; - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierList:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyWatchedKeyList:")); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; - } - - if (regexOptions & kSCDRegexKey) { - keyCnt = CFSetGetCount(sessionPrivate->reKeys); + if (isRegex) { + keyCnt = CFSetGetCount(storePrivate->reKeys); keyRefs = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); - CFSetGetValues(sessionPrivate->reKeys, keyRefs); - keys = CFArrayCreate(NULL, keyRefs, keyCnt, &kCFTypeArrayCallBacks); + CFSetGetValues(storePrivate->reKeys, keyRefs); + watchedKeys = CFArrayCreate(NULL, keyRefs, keyCnt, &kCFTypeArrayCallBacks); CFAllocatorDeallocate(NULL, keyRefs); } else { - keyCnt = CFSetGetCount(sessionPrivate->keys); + keyCnt = CFSetGetCount(storePrivate->keys); keyRefs = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); - CFSetGetValues(sessionPrivate->keys, keyRefs); - keys = CFArrayCreate(NULL, keyRefs, keyCnt, &kCFTypeArrayCallBacks); + CFSetGetValues(storePrivate->keys, keyRefs); + watchedKeys = CFArrayCreate(NULL, keyRefs, keyCnt, &kCFTypeArrayCallBacks); CFAllocatorDeallocate(NULL, keyRefs); } - sortedKeys = CFArrayCreateMutableCopy(NULL, keyCnt, keys); - CFRelease(keys); - CFArraySortValues(sortedKeys, CFRangeMake(0, keyCnt), sort_keys, NULL); - - *notifierKeys = sortedKeys; - return SCD_OK; + return watchedKeys; } diff --git a/SystemConfiguration.fproj/SCDNotifierRemove.c b/SystemConfiguration.fproj/SCDNotifierRemove.c index e062600..7cc92a9 100644 --- a/SystemConfiguration.fproj/SCDNotifierRemove.c +++ b/SystemConfiguration.fproj/SCDNotifierRemove.c @@ -20,55 +20,68 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDNotifierRemove(SCDSessionRef session, CFStringRef key, int regexOptions) +Boolean +SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - CFDataRef xmlKey; /* serialized key */ - xmlData_t myKeyRef; - CFIndex myKeyLen; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlKey; /* serialized key */ + xmlData_t myKeyRef; + CFIndex myKeyLen; + int sc_status; - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierRemove:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" regexOptions = %0o"), regexOptions); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveWatchedKey:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE"); - if (key == NULL) { - return SCD_INVALIDARGUMENT; /* no key specified */ + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - if (session == NULL) { - return SCD_NOSESSION; /* you can't do anything without a session */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } /* * remove key from this sessions notifier list after checking that * it was previously defined. */ - if (regexOptions & kSCDRegexKey) { - if (!CFSetContainsValue(sessionPrivate->reKeys, key)) - return SCD_NOKEY; /* sorry, key does not exist in notifier list */ - CFSetRemoveValue(sessionPrivate->reKeys, key); /* remove key from this sessions notifier list */ + if (isRegex) { + if (!CFSetContainsValue(storePrivate->reKeys, key)) { + /* sorry, key does not exist in notifier list */ + _SCErrorSet(kSCStatusNoKey); + return FALSE; + } + CFSetRemoveValue(storePrivate->reKeys, key); /* remove key from this sessions notifier list */ } else { - if (!CFSetContainsValue(sessionPrivate->keys, key)) - return SCD_NOKEY; /* sorry, key does not exist in notifier list */ - CFSetRemoveValue(sessionPrivate->keys, key); /* remove key from this sessions notifier list */ - } - - if (sessionPrivate->server == MACH_PORT_NULL) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (!CFSetContainsValue(storePrivate->keys, key)) { + /* sorry, key does not exist in notifier list */ + _SCErrorSet(kSCStatusNoKey); + return FALSE; + } + CFSetRemoveValue(storePrivate->keys, key); /* remove key from this sessions notifier list */ } /* serialize the key */ @@ -77,22 +90,28 @@ SCDNotifierRemove(SCDSessionRef session, CFStringRef key, int regexOptions) myKeyLen = CFDataGetLength(xmlKey); /* send the key to the server */ - status = notifyremove(sessionPrivate->server, + status = notifyremove(storePrivate->server, myKeyRef, myKeyLen, - regexOptions, - (int *)&scd_status); + isRegex, + (int *)&sc_status); /* clean up */ CFRelease(xmlKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("notifyremove(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyremove(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } + + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDNotifierSetKeys.c b/SystemConfiguration.fproj/SCDNotifierSetKeys.c new file mode 100644 index 0000000..f504f7c --- /dev/null +++ b/SystemConfiguration.fproj/SCDNotifierSetKeys.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - initial revision + */ + +#include +#include + +#include +#include +#include "SCDynamicStoreInternal.h" +#include "config.h" /* MiG generated file */ + + +static __inline__ void +my_CFSetApplyFunction(CFSetRef theSet, + CFSetApplierFunction applier, + void *context) +{ + CFAllocatorRef myAllocator; + CFSetRef mySet; + + myAllocator = CFGetAllocator(theSet); + mySet = CFSetCreateCopy(myAllocator, theSet); + CFSetApplyFunction(mySet, applier, context); + CFRelease(mySet); + return; +} + + +/* + * "context" argument for removeOldKey() and addNewKey() + */ +typedef struct { + SCDynamicStoreRef store; + CFArrayRef newKeys; /* for removeOldKey */ + Boolean isRegex; + Boolean ok; +} updateKeysContext, *updateKeysContextRef; + + +static void +removeOldKey(const void *value, void *context) +{ + CFStringRef oldKey = (CFStringRef)value; + updateKeysContextRef myContextRef = (updateKeysContextRef)context; + + if (!myContextRef->ok) { + return; + } + + if (!myContextRef->newKeys || + !CFArrayContainsValue(myContextRef->newKeys, + CFRangeMake(0, CFArrayGetCount(myContextRef->newKeys)), + oldKey)) { + /* the old notification key is not being retained, remove it */ + myContextRef->ok = SCDynamicStoreRemoveWatchedKey(myContextRef->store, + oldKey, + myContextRef->isRegex); + } + + return; +} + + +static void +addNewKey(const void *value, void *context) +{ + CFStringRef newKey = (CFStringRef)value; + updateKeysContextRef myContextRef = (updateKeysContextRef)context; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)myContextRef->store; + + if (!myContextRef->ok) { + return; + } + + if (myContextRef->isRegex) { + if (!CFSetContainsValue(storePrivate->reKeys, newKey)) { + /* add pattern to this sessions notifier list */ + myContextRef->ok = SCDynamicStoreAddWatchedKey(myContextRef->store, newKey, TRUE); + } + } else { + if (!CFSetContainsValue(storePrivate->keys, newKey)) { + /* add key to this sessions notifier list */ + myContextRef->ok = SCDynamicStoreAddWatchedKey(myContextRef->store, newKey, FALSE); + } + } + + return; +} + +Boolean +SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, + CFArrayRef keys, + CFArrayRef patterns) +{ + updateKeysContext myContext; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSetNotificationKeys:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" keys = %@"), keys); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" patterns = %@"), patterns); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; + } + + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; + } + + myContext.ok = TRUE; + myContext.store = store; + + /* remove any previously registered keys */ + myContext.newKeys = keys; + myContext.isRegex = FALSE; + my_CFSetApplyFunction(storePrivate->keys, removeOldKey, &myContext); + + /* register any new keys */ + if (keys) { + CFArrayApplyFunction(keys, + CFRangeMake(0, CFArrayGetCount(keys)), + addNewKey, + &myContext); + } + + /* remove any previously registered patterns */ + myContext.newKeys = patterns; + myContext.isRegex = TRUE; + my_CFSetApplyFunction(storePrivate->reKeys, removeOldKey, &myContext); + + /* register any new patterns */ + if (patterns) { + CFArrayApplyFunction(patterns, + CFRangeMake(0, CFArrayGetCount(patterns)), + addNewKey, + &myContext); + } + + return myContext.ok; +} diff --git a/SystemConfiguration.fproj/SCDNotifierWait.c b/SystemConfiguration.fproj/SCDNotifierWait.c index 67cf1d9..fa59f2b 100644 --- a/SystemConfiguration.fproj/SCDNotifierWait.c +++ b/SystemConfiguration.fproj/SCDNotifierWait.c @@ -20,56 +20,102 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 31, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDNotifierWait(SCDSessionRef session) +static mach_msg_id_t +waitForMachMessage(mach_port_t port) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - mach_port_t port; - mach_port_t oldNotify; - SCDStatus scd_status; - mach_msg_id_t msgid; + kern_return_t status; + mach_msg_empty_rcv_t *buf; + + mach_msg_size_t size = sizeof(mach_msg_empty_t) + MAX_TRAILER_SIZE; + + status = vm_allocate(mach_task_self(), (vm_address_t *)&buf, size, TRUE); + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status)); + return -1; + } + + status = mach_msg(&buf->header, /* msg */ + MACH_RCV_MSG, /* options */ + 0, /* send_size */ + size, /* rcv_size */ + port, /* rcv_name */ + MACH_MSG_TIMEOUT_NONE, /* timeout */ + MACH_PORT_NULL); /* notify */ + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_msg(): %s"), mach_error_string(status)); + return -1; + } + + return buf->header.msgh_id; +} - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierWait:")); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ +Boolean +SCDynamicStoreNotifyWait(SCDynamicStoreRef store) +{ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + mach_port_t port; + mach_port_t oldNotify; + int sc_status; + mach_msg_id_t msgid; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait:")); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - if (SCDOptionGet(NULL, kSCDOptionIsServer)) { - /* sorry, neither the server nor any plug-ins can "wait" */ - return SCD_FAILED; + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } - if (sessionPrivate->notifyStatus != NotifierNotRegistered) { + if (storePrivate->notifyStatus != NotifierNotRegistered) { /* sorry, you can only have one notification registered at once */ - return SCD_NOTIFIERACTIVE; + _SCErrorSet(kSCStatusNotifierActive); + return FALSE; } - SCDLog(LOG_DEBUG, CFSTR("Allocating port (for server response)")); + /* Allocating port (for server response) */ status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status)); - return SCD_FAILED; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status)); + _SCErrorSet(status); + return FALSE; } - SCDLog(LOG_DEBUG, CFSTR(" port = %d"), port); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" port = %d"), port); status = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status)); (void) mach_port_destroy(mach_task_self(), port); - return SCD_FAILED; + _SCErrorSet(status); + return FALSE; } /* Request a notification when/if the server dies */ @@ -81,71 +127,75 @@ SCDNotifierWait(SCDSessionRef session) MACH_MSG_TYPE_MAKE_SEND_ONCE, &oldNotify); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); (void) mach_port_destroy(mach_task_self(), port); - return SCD_FAILED; + _SCErrorSet(status); + return FALSE; } -#ifdef DEBUG if (oldNotify != MACH_PORT_NULL) { - SCDLog(LOG_DEBUG, CFSTR("SCDNotifierWait(): why is oldNotify != MACH_PORT_NULL?")); + SCLog(_sc_verbose, LOG_ERR, CFSTR("SCDynamicStoreNotifyWait(): why is oldNotify != MACH_PORT_NULL?")); } -#endif /* DEBUG */ - SCDLog(LOG_DEBUG, CFSTR("Requesting notification via mach port %d"), port); - status = notifyviaport(sessionPrivate->server, + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Requesting notification via mach port %d"), port); + status = notifyviaport(storePrivate->server, port, 0, - (int *)&scd_status); + (int *)&sc_status); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; } - if (scd_status != SCD_OK) { - return scd_status; + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } /* set notifier active */ - sessionPrivate->notifyStatus = Using_NotifierWait; + storePrivate->notifyStatus = Using_NotifierWait; - SCDLog(LOG_DEBUG, CFSTR("Waiting...")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Waiting...")); - msgid = _waitForMachMessage(port); + msgid = waitForMachMessage(port); /* set notifier inactive */ - sessionPrivate->notifyStatus = NotifierNotRegistered; + storePrivate->notifyStatus = NotifierNotRegistered; if (msgid == MACH_NOTIFY_NO_SENDERS) { /* the server closed the notifier port */ - SCDLog(LOG_DEBUG, CFSTR(" notifier port closed, destroying port %d"), port); - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" notifier port closed, destroying port %d"), port); + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } if (msgid == -1) { /* one of the mach routines returned an error */ - SCDLog(LOG_DEBUG, CFSTR(" communication with server failed, destroying port %d"), port); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" communication with server failed, destroying port %d"), port); (void) mach_port_destroy(mach_task_self(), port); - return SCD_NOSERVER; + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } - SCDLog(LOG_DEBUG, CFSTR("Something changed, cancelling notification request")); - status = notifycancel(sessionPrivate->server, - (int *)&scd_status); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Something changed, cancelling notification request")); + status = notifycancel(storePrivate->server, + (int *)&sc_status); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("notifycancel(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - scd_status = SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifycancel(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; } (void) mach_port_destroy(mach_task_self(), port); - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDNotify.c b/SystemConfiguration.fproj/SCDNotify.c new file mode 100644 index 0000000..e16481c --- /dev/null +++ b/SystemConfiguration.fproj/SCDNotify.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Modification History + * + * May 19, 2001 Allan Nathanson + * - initial revision + */ + +#include +#include + +#include +#include +#include "SCDynamicStoreInternal.h" +#include "config.h" /* MiG generated file */ + +Boolean +SCDynamicStoreNotifyValue(SCDynamicStoreRef store, + CFStringRef key) +{ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlKey; /* serialized key */ + xmlData_t myKeyRef; + CFIndex myKeyLen; + int sc_status; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; + } + + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; + } + + /* serialize the key */ + xmlKey = CFPropertyListCreateXMLData(NULL, key); + myKeyRef = (xmlData_t)CFDataGetBytePtr(xmlKey); + myKeyLen = CFDataGetLength(xmlKey); + + /* send the key to the server */ + status = confignotify(storePrivate->server, + myKeyRef, + myKeyLen, + (int *)&sc_status); + + /* clean up */ + CFRelease(xmlKey); + + if (status != KERN_SUCCESS) { + if (status != MACH_SEND_INVALID_DEST) + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("confignotify(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } + + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; + } + + return TRUE; +} diff --git a/SystemConfiguration.fproj/SCDOpen.c b/SystemConfiguration.fproj/SCDOpen.c index 7e1f720..ce71d42 100644 --- a/SystemConfiguration.fproj/SCDOpen.c +++ b/SystemConfiguration.fproj/SCDOpen.c @@ -20,92 +20,252 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" +static CFStringRef +__SCDynamicStoreCopyDescription(CFTypeRef cf) { + CFAllocatorRef allocator = CFGetAllocator(cf); + CFMutableStringRef result; + + result = CFStringCreateMutable(allocator, 0); + CFStringAppendFormat(result, NULL, CFSTR(" {\n"), cf, allocator); + CFStringAppendFormat(result, NULL, CFSTR("}")); -SCDSessionRef -_SCDSessionCreatePrivate() + return result; +} + + +static void +__SCDynamicStoreDeallocate(CFTypeRef cf) { - SCDSessionRef newSession; - SCDSessionPrivateRef newPrivate; + CFIndex keyCnt; + int oldThreadState; + int sc_status; + kern_return_t status; + SCDynamicStoreRef store = (SCDynamicStoreRef)cf; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreDeallocate:")); + + (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldThreadState); + + /* Remove notification keys */ + if ((keyCnt = CFSetGetCount(storePrivate->keys)) > 0) { + void **watchedKeys; + CFArrayRef keysToRemove; + CFIndex i; + + watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); + CFSetGetValues(storePrivate->keys, watchedKeys); + keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks); + CFAllocatorDeallocate(NULL, watchedKeys); + for (i=0; ireKeys)) > 0) { + void **watchedKeys; + CFArrayRef keysToRemove; + CFIndex i; + + watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); + CFSetGetValues(storePrivate->reKeys, watchedKeys); + keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks); + CFAllocatorDeallocate(NULL, watchedKeys); + for (i=0; iserver && storePrivate->locked) { + (void) SCDynamicStoreUnlock(store); /* release the lock */ + } + + if (storePrivate->server != MACH_PORT_NULL) { + status = configclose(storePrivate->server, (int *)&sc_status); + if (status != KERN_SUCCESS) { + if (status != MACH_SEND_INVALID_DEST) + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configclose(): %s"), mach_error_string(status)); + } + + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + } + + (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldThreadState); + pthread_testcancel(); + + /* release any callback context info */ + if (storePrivate->rlsContext.release) { + storePrivate->rlsContext.release(storePrivate->rlsContext.info); + } - /* allocate space */ - newSession = (SCDSessionRef)CFAllocatorAllocate(NULL, sizeof(SCDSessionPrivate), 0); - newPrivate = (SCDSessionPrivateRef)newSession; + /* release any keys being watched */ + CFRelease(storePrivate->keys); + CFRelease(storePrivate->reKeys); + + return; +} + + +static CFTypeID __kSCDynamicStoreTypeID = _kCFRuntimeNotATypeID; + + +static const CFRuntimeClass __SCDynamicStoreClass = { + 0, // version + "SCDynamicStore", // className + NULL, // init + NULL, // copy + __SCDynamicStoreDeallocate, // dealloc + NULL, // equal + NULL, // hash + NULL, // copyFormattingDesc + __SCDynamicStoreCopyDescription // copyDebugDesc +}; + + +static pthread_once_t initialized = PTHREAD_ONCE_INIT; + + +static void +__SCDynamicStoreInitialize(void) { + __kSCDynamicStoreTypeID = _CFRuntimeRegisterClass(&__SCDynamicStoreClass); + return; +} + + +SCDynamicStoreRef +__SCDynamicStoreCreatePrivate(CFAllocatorRef allocator, + const CFStringRef name, + SCDynamicStoreCallBack callout, + SCDynamicStoreContext *context) +{ + SCDynamicStorePrivateRef store; + UInt32 size; + + /* initialize runtime */ + pthread_once(&initialized, __SCDynamicStoreInitialize); + + /* allocate session */ + size = sizeof(SCDynamicStorePrivate) - sizeof(CFRuntimeBase); + store = (SCDynamicStorePrivateRef)_CFRuntimeCreateInstance(allocator, + __kSCDynamicStoreTypeID, + size, + NULL); + if (!store) { + return NULL; + } /* server side of the "configd" session */ - newPrivate->server = MACH_PORT_NULL; + store->server = MACH_PORT_NULL; - /* per-session flags */ - SCDOptionSet(newSession, kSCDOptionDebug, SCDOptionGet(NULL, kSCDOptionDebug )); - SCDOptionSet(newSession, kSCDOptionVerbose, SCDOptionGet(NULL, kSCDOptionVerbose )); - SCDOptionSet(newSession, kSCDOptionIsLocked, FALSE); - SCDOptionSet(newSession, kSCDOptionUseSyslog, SCDOptionGet(NULL, kSCDOptionUseSyslog )); - SCDOptionSet(newSession, kSCDOptionUseCFRunLoop, SCDOptionGet(NULL, kSCDOptionUseCFRunLoop)); + /* flags */ + store->locked = FALSE; /* SCDKeys being watched */ - newPrivate->keys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); - newPrivate->reKeys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); + store->keys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); + store->reKeys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); + + /* Notification status */ + store->notifyStatus = NotifierNotRegistered; - /* No notifications pending */ - newPrivate->notifyStatus = NotifierNotRegistered; + /* "client" information associated with SCDynamicStoreCreateRunLoopSource() */ + store->rlsRefs = 0; + store->rls = NULL; + store->rlsFunction = callout; + store->rlsContext.info = NULL; + store->rlsContext.retain = NULL; + store->rlsContext.release = NULL; + store->rlsContext.copyDescription = NULL; + if (context) { + bcopy(context, &store->rlsContext, sizeof(SCDynamicStoreContext)); + if (context->retain) { + store->rlsContext.info = (void *)context->retain(context->info); + } + } - /* "client" information about active (notification) callback */ - newPrivate->callbackFunction = NULL; - newPrivate->callbackArgument = NULL; - newPrivate->callbackPort = NULL; - newPrivate->callbackRunLoopSource = NULL; /* XXX */ - newPrivate->callbackHelper = NULL; + /* "client" information associated with SCDynamicStoreNotifyCallback() */ + store->callbackFunction = NULL; + store->callbackArgument = NULL; + store->callbackPort = NULL; + store->callbackRunLoop = NULL; + store->callbackRunLoopSource = NULL; - /* "server" information associated with SCDNotifierInformViaMachPort(); */ - newPrivate->notifyPort = MACH_PORT_NULL; - newPrivate->notifyPortIdentifier = 0; + /* "server" information associated with SCDynamicStoreNotifyMachPort(); */ + store->notifyPort = MACH_PORT_NULL; + store->notifyPortIdentifier = 0; - /* "server" information associated with SCDNotifierInformViaFD(); */ - newPrivate->notifyFile = -1; - newPrivate->notifyFileIdentifier = 0; + /* "server" information associated with SCDynamicStoreNotifyFileDescriptor(); */ + store->notifyFile = -1; + store->notifyFileIdentifier = 0; - /* "server" information associated with SCDNotifierInformViaSignal(); */ - newPrivate->notifySignal = 0; - newPrivate->notifySignalTask = TASK_NULL; + /* "server" information associated with SCDynamicStoreNotifySignal(); */ + store->notifySignal = 0; + store->notifySignalTask = TASK_NULL; - return newSession; + return (SCDynamicStoreRef)store; } -SCDStatus -SCDOpen(SCDSessionRef *session, CFStringRef name) +SCDynamicStoreRef +SCDynamicStoreCreate(CFAllocatorRef allocator, + CFStringRef name, + SCDynamicStoreCallBack callout, + SCDynamicStoreContext *context) { - SCDSessionPrivateRef sessionPrivate; - kern_return_t status; - mach_port_t bootstrap_port; - mach_port_t server; - CFDataRef xmlName; /* serialized name */ - xmlData_t myNameRef; - CFIndex myNameLen; - SCDStatus scd_status; - - SCDLog(LOG_DEBUG, CFSTR("SCDOpen:")); - SCDLog(LOG_DEBUG, CFSTR(" name = %@"), name); + SCDynamicStoreRef store; + SCDynamicStorePrivateRef storePrivate; + kern_return_t status; + mach_port_t bootstrap_port; + mach_port_t server; + CFDataRef xmlName; /* serialized name */ + xmlData_t myNameRef; + CFIndex myNameLen; + int sc_status; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCreate:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" name = %@"), name); /* * allocate and initialize a new session */ - sessionPrivate = (SCDSessionPrivateRef)_SCDSessionCreatePrivate(); - *session = (SCDSessionRef)sessionPrivate; + store = __SCDynamicStoreCreatePrivate(allocator, name, callout, context); + storePrivate = (SCDynamicStorePrivateRef)store; status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status)); - CFAllocatorDeallocate(NULL, sessionPrivate); - *session = NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status)); + CFRelease(store); + _SCErrorSet(status); + return NULL; } status = bootstrap_look_up(bootstrap_port, SCD_SERVER, &server); @@ -115,17 +275,17 @@ SCDOpen(SCDSessionRef *session, CFStringRef name) break; case BOOTSTRAP_UNKNOWN_SERVICE : /* service not currently registered, try again later */ - CFAllocatorDeallocate(NULL, sessionPrivate); - *session = NULL; - return SCD_NOSERVER; + CFRelease(store); + _SCErrorSet(status); + return NULL; break; default : #ifdef DEBUG - SCDLog(LOG_DEBUG, CFSTR("bootstrap_status: %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("bootstrap_status: %s"), mach_error_string(status)); #endif /* DEBUG */ - CFAllocatorDeallocate(NULL, sessionPrivate); - *session = NULL; - return SCD_NOSERVER; + CFRelease(store); + _SCErrorSet(status); + return NULL; } /* serialize the name */ @@ -134,19 +294,31 @@ SCDOpen(SCDSessionRef *session, CFStringRef name) myNameLen = CFDataGetLength(xmlName); /* open a new session with the server */ - status = configopen(server, myNameRef, myNameLen, &sessionPrivate->server, (int *)&scd_status); + status = configopen(server, myNameRef, myNameLen, &storePrivate->server, (int *)&sc_status); /* clean up */ CFRelease(xmlName); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configopen(): %s"), mach_error_string(status)); - CFAllocatorDeallocate(NULL, sessionPrivate); - *session = NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configopen(): %s"), mach_error_string(status)); + CFRelease(store); + _SCErrorSet(status); + return NULL; + } + + if (sc_status != kSCStatusOK) { + CFRelease(store); + _SCErrorSet(sc_status); + return FALSE; } - SCDLog(LOG_DEBUG, CFSTR(" server port = %d"), sessionPrivate->server); - return scd_status; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" server port = %d"), storePrivate->server); + return store; +} + + +CFTypeID +SCDynamicStoreGetTypeID(void) { + return __kSCDynamicStoreTypeID; } diff --git a/SystemConfiguration.fproj/SCDPlugin.h b/SystemConfiguration.fproj/SCDPlugin.h new file mode 100644 index 0000000..e0cf531 --- /dev/null +++ b/SystemConfiguration.fproj/SCDPlugin.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCDPLUGIN_H +#define _SCDPLUGIN_H + +#include +#include + + +/*! + @header SCDPlugin + */ + + +/* + @define kSCBundleRequires + */ +#define kSCBundleRequires CFSTR("Requires") + + +/* + @define kSCBundleVerbose + */ +#define kSCBundleVerbose CFSTR("Verbose") + + +/*! + @typedef SCDynamicStoreBundleLoadFunction + @discussion Type of the load() initialization function that will be + called when a plug-in is loaded. This function is called + before calling the start() function and can be uesd to + initialize any variables, open any sessions with "configd", + and register any needed notifications. + @param bundle The CFBundle being loaded. + @param verbose A boolean value indicating whether verbose logging has + been enabled for this bundle. + */ +typedef void (*SCDynamicStoreBundleLoadFunction) (CFBundleRef bundle, + Boolean bundleVerbose); + +/*! + @typedef SCDynamicStoreBundleStartFunction + @discussion Type of the start() initialization function that will be + called after all plug-ins have been loaded and their load() + functions have been called. This function can initialize + variables, open sessions with "configd", and register any + needed notifications. + @param bundleName The name of the plug-in / bundle. + @param bundlePath The path name associated with the plug-in / bundle. + */ +typedef void (*SCDynamicStoreBundleStartFunction) (const char *bundleName, + const char *bundlePath); + +/*! + @typedef SCDynamicStoreBundlePrimeFunction + @discussion Type of the prime() initialization function that will be + called after all plug-ins have executed their start() function but + before the main plug-in run loop is started. This function should + be used to initialize any configuration information and/or state + in the store. + */ +typedef void (*SCDynamicStoreBundlePrimeFunction) (); + + +__BEGIN_DECLS + +__END_DECLS + +#endif /* _SCDPLUGIN_H */ diff --git a/SystemConfiguration.fproj/SCDPrivate.c b/SystemConfiguration.fproj/SCDPrivate.c index 86a6f03..8e0b6ba 100644 --- a/SystemConfiguration.fproj/SCDPrivate.c +++ b/SystemConfiguration.fproj/SCDPrivate.c @@ -20,57 +20,37 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + +#include +#include + #include #include #include #include -#include "SCDPrivate.h" - - -__private_extern__ mach_msg_id_t -_waitForMachMessage(mach_port_t port) -{ - kern_return_t status; - mach_msg_empty_rcv_t *buf; - - mach_msg_size_t size = sizeof(mach_msg_empty_t) + MAX_TRAILER_SIZE; - - status = vm_allocate(mach_task_self(), (vm_address_t *)&buf, size, TRUE); - if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status)); - return -1; - } - - status = mach_msg(&buf->header, /* msg */ - MACH_RCV_MSG, /* options */ - 0, /* send_size */ - size, /* rcv_size */ - port, /* rcv_name */ - MACH_MSG_TIMEOUT_NONE, /* timeout */ - MACH_PORT_NULL); /* notify */ - if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_msg(): %s"), mach_error_string(status)); - return -1; - } - - return buf->header.msgh_id; -} - - void -_showMachPortStatus() +__showMachPortStatus() { #ifdef DEBUG /* print status of in-use mach ports */ - if (SCDOptionGet(NULL, kSCDOptionDebug) && SCDOptionGet(NULL, kSCDOptionVerbose)) { + if (_sc_debug) { kern_return_t status; mach_port_name_array_t ports; mach_port_type_array_t types; int pi, pn, tn; CFMutableStringRef str; - SCDLog(LOG_DEBUG, CFSTR("----------")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("----------")); /* report on ALL mach ports associated with this task */ status = mach_port_names(mach_task_self(), &ports, &pn, &types, &tn); @@ -97,11 +77,11 @@ _showMachPortStatus() *rp = '\0'; CFStringAppendFormat(str, NULL, CFSTR(" %d%s"), ports[pi], rights); } - SCDLog(LOG_DEBUG, CFSTR("Task ports (n=%d):%@"), pn, str); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Task ports (n=%d):%@"), pn, str); CFRelease(str); } else { /* log (but ignore) errors */ - SCDLog(LOG_DEBUG, CFSTR("mach_port_names(): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_names(): %s"), mach_error_string(status)); } } #endif /* DEBUG */ @@ -110,7 +90,7 @@ _showMachPortStatus() void -_showMachPortReferences(mach_port_t port) +__showMachPortReferences(mach_port_t port) { #ifdef DEBUG kern_return_t status; @@ -120,39 +100,39 @@ _showMachPortReferences(mach_port_t port) mach_port_urefs_t refs_pset = 0; mach_port_urefs_t refs_dead = 0; - SCDLog(LOG_DEBUG, CFSTR("user references for mach port %d"), port); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("user references for mach port %d"), port); status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, &refs_send); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_SEND): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_SEND): %s"), mach_error_string(status)); return; } status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, &refs_recv); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_RECEIVE): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_RECEIVE): %s"), mach_error_string(status)); return; } status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND_ONCE, &refs_once); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_SEND_ONCE): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_SEND_ONCE): %s"), mach_error_string(status)); return; } status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_PORT_SET, &refs_pset); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_PORT_SET): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_PORT_SET): %s"), mach_error_string(status)); return; } status = mach_port_get_refs(mach_task_self(), port, MACH_PORT_RIGHT_DEAD_NAME, &refs_dead); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_DEAD_NAME): %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" mach_port_get_refs(MACH_PORT_RIGHT_DEAD_NAME): %s"), mach_error_string(status)); return; } - SCDLog(LOG_DEBUG, + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" send = %d, receive = %d, send once = %d, port set = %d, dead name = %d"), refs_send, refs_recv, diff --git a/SystemConfiguration.fproj/SCDPrivate.h b/SystemConfiguration.fproj/SCDPrivate.h deleted file mode 100644 index 3601d35..0000000 --- a/SystemConfiguration.fproj/SCDPrivate.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _SCDPRIVATE_H -#define _SCDPRIVATE_H - -#include - -#include -#include -#include -#include -#include - - -/* Define the per-session (and global) flags */ -typedef struct { - int debug; - int verbose; - boolean_t isLocked; - boolean_t useSyslog; - boolean_t useCFRunLoop; -} _SCDFlags; - - -/* Define the status of any registered notification. */ -typedef enum { - NotifierNotRegistered = 0, - Using_NotifierWait, - Using_NotifierInformViaCallback, - Using_NotifierInformViaMachPort, - Using_NotifierInformViaFD, - Using_NotifierInformViaSignal, -} _SCDNotificationStatus; - - -typedef struct { - - /* server side of the "configd" session */ - mach_port_t server; - - /* per-session flags */ - _SCDFlags flags; - - /* SCDKeys being watched */ - CFMutableSetRef keys; - CFMutableSetRef reKeys; - - /* current status of notification requests */ - _SCDNotificationStatus notifyStatus; - - /* "client" information associated with SCDNotifierInformViaCallback() */ - SCDCallbackRoutine_t callbackFunction; - void *callbackArgument; - CFMachPortRef callbackPort; - CFRunLoopSourceRef callbackRunLoopSource; /* XXX CFMachPortInvalidate() doesn't work */ - pthread_t callbackHelper; - - /* "server" information associated with SCDNotifierInformViaMachPort() */ - mach_port_t notifyPort; - mach_msg_id_t notifyPortIdentifier; - - /* "server" information associated with SCDNotifierInformViaFD() */ - int notifyFile; - int notifyFileIdentifier; - - /* "server" information associated with SCDNotifierInformViaSignal() */ - int notifySignal; - task_t notifySignalTask; - -} SCDSessionPrivate, *SCDSessionPrivateRef; - - -typedef struct { - - /* configuration data associated with key */ - CFPropertyListRef data; - - /* instance value of last fetched data */ - int instance; - -} SCDHandlePrivate, *SCDHandlePrivateRef; - - -/* per-session options */ -typedef enum { - kSCDOptionIsLocked = 1024, -} SCDServerSessionOptions; - - -/* global options */ -typedef enum { - kSCDOptionIsServer = 2048, -} SCDServerGlobalOptions; - - -__BEGIN_DECLS - -SCDSessionRef _SCDSessionCreatePrivate (); - -void _SCDHandleSetInstance (SCDHandleRef handle, - int instance); - -mach_msg_id_t _waitForMachMessage (mach_port_t port); - -void _showMachPortStatus (); -void _showMachPortReferences (mach_port_t port); - -__END_DECLS - -#endif /* !_SCDPRIVATE_H */ diff --git a/SystemConfiguration.fproj/SCDRemove.c b/SystemConfiguration.fproj/SCDRemove.c index 30cc8b1..0f08ccc 100644 --- a/SystemConfiguration.fproj/SCDRemove.c +++ b/SystemConfiguration.fproj/SCDRemove.c @@ -20,33 +20,47 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include - -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" -SCDStatus -SCDRemove(SCDSessionRef session, CFStringRef key) +Boolean +SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - CFDataRef xmlKey; /* serialized key */ - xmlData_t myKeyRef; - CFIndex myKeyLen; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlKey; /* serialized key */ + xmlData_t myKeyRef; + CFIndex myKeyLen; + int sc_status; - SCDLog(LOG_DEBUG, CFSTR("SCDRemove:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - if (key == NULL) { - return SCD_INVALIDARGUMENT; /* no key specified */ + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } /* serialize the key */ @@ -55,21 +69,27 @@ SCDRemove(SCDSessionRef session, CFStringRef key) myKeyLen = CFDataGetLength(xmlKey); /* send the key to the server */ - status = configremove(sessionPrivate->server, + status = configremove(storePrivate->server, myKeyRef, myKeyLen, - (int *)&scd_status); + (int *)&sc_status); /* clean up */ CFRelease(xmlKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configremove(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configremove(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } + + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDSet.c b/SystemConfiguration.fproj/SCDSet.c index 1cb79ad..da4fd4c 100644 --- a/SystemConfiguration.fproj/SCDSet.c +++ b/SystemConfiguration.fproj/SCDSet.c @@ -20,39 +20,140 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" +Boolean +SCDynamicStoreSetMultiple(SCDynamicStoreRef store, + CFDictionaryRef keysToSet, + CFArrayRef keysToRemove, + CFArrayRef keysToNotify) +{ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlSet = NULL; /* key/value pairs to set (XML serialized) */ + xmlData_t mySetRef = NULL; /* key/value pairs to set (serialized) */ + CFIndex mySetLen = 0; + CFDataRef xmlRemove = NULL; /* keys to remove (XML serialized) */ + xmlData_t myRemoveRef = NULL; /* keys to remove (serialized) */ + CFIndex myRemoveLen = 0; + CFDataRef xmlNotify = NULL; /* keys to notify (XML serialized) */ + xmlData_t myNotifyRef = NULL; /* keys to notify (serialized) */ + CFIndex myNotifyLen = 0; + int sc_status; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSetMultiple:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" keysToSet = %@"), keysToSet); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" keysToRemove = %@"), keysToRemove); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" keysToNotify = %@"), keysToNotify); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return NULL; + } + + if (storePrivate->server == MACH_PORT_NULL) { + _SCErrorSet(kSCStatusNoStoreServer); + return NULL; /* you must have an open session to play */ + } + + /* serialize the key/value pairs to set*/ + if (keysToSet) { + xmlSet = CFPropertyListCreateXMLData(NULL, keysToSet); + mySetRef = (xmlData_t)CFDataGetBytePtr(xmlSet); + mySetLen = CFDataGetLength(xmlSet); + } + + /* serialize the keys to remove */ + if (keysToRemove) { + xmlRemove = CFPropertyListCreateXMLData(NULL, keysToRemove); + myRemoveRef = (xmlData_t)CFDataGetBytePtr(xmlRemove); + myRemoveLen = CFDataGetLength(xmlRemove); + } -SCDStatus -SCDSet(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) + /* serialize the keys to notify */ + if (keysToNotify) { + xmlNotify = CFPropertyListCreateXMLData(NULL, keysToNotify); + myNotifyRef = (xmlData_t)CFDataGetBytePtr(xmlNotify); + myNotifyLen = CFDataGetLength(xmlNotify); + } + + /* send the keys and patterns, fetch the associated result from the server */ + status = configset_m(storePrivate->server, + mySetRef, + mySetLen, + myRemoveRef, + myRemoveLen, + myNotifyRef, + myNotifyLen, + (int *)&sc_status); + + /* clean up */ + if (xmlSet) CFRelease(xmlSet); + if (xmlRemove) CFRelease(xmlRemove); + if (xmlNotify) CFRelease(xmlNotify); + + if (status != KERN_SUCCESS) { + if (status != MACH_SEND_INVALID_DEST) + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configset_m(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } + + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; + } + + return TRUE; +} + +Boolean +SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - CFDataRef xmlKey; /* serialized key */ - xmlData_t myKeyRef; - CFIndex myKeyLen; - CFDataRef xmlData; /* serialized data */ - xmlData_t myDataRef; - CFIndex myDataLen; - SCDStatus scd_status; - int newInstance; - - SCDLog(LOG_DEBUG, CFSTR("SCDSet:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" data = %@"), SCDHandleGetData(handle)); - SCDLog(LOG_DEBUG, CFSTR(" instance = %d"), SCDHandleGetInstance(handle)); - - if (key == NULL) { - return SCD_INVALIDARGUMENT; /* no key specified */ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlKey; /* serialized key */ + xmlData_t myKeyRef; + CFIndex myKeyLen; + CFDataRef xmlData; /* serialized data */ + xmlData_t myDataRef; + CFIndex myDataLen; + int sc_status; + int newInstance; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSetValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); + + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } /* serialize the key and data */ @@ -60,19 +161,19 @@ SCDSet(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) myKeyRef = (xmlData_t)CFDataGetBytePtr(xmlKey); myKeyLen = CFDataGetLength(xmlKey); - xmlData = CFPropertyListCreateXMLData(NULL, SCDHandleGetData(handle)); + xmlData = CFPropertyListCreateXMLData(NULL, value); myDataRef = (xmlData_t)CFDataGetBytePtr(xmlData); myDataLen = CFDataGetLength(xmlData); /* send the key & data to the server, get new instance id */ - status = configset(sessionPrivate->server, + status = configset(storePrivate->server, myKeyRef, myKeyLen, myDataRef, myDataLen, - SCDHandleGetInstance(handle), + 0, &newInstance, - (int *)&scd_status); + (int *)&sc_status); /* clean up */ CFRelease(xmlKey); @@ -80,17 +181,17 @@ SCDSet(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configset(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configset(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; } - if (scd_status == SCD_OK) { - _SCDHandleSetInstance(handle, newInstance); + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - SCDLog(LOG_DEBUG, CFSTR(" new instance = %d"), SCDHandleGetInstance(handle)); - - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDSnapshot.c b/SystemConfiguration.fproj/SCDSnapshot.c index 1339cda..03bbffc 100644 --- a/SystemConfiguration.fproj/SCDSnapshot.c +++ b/SystemConfiguration.fproj/SCDSnapshot.c @@ -20,36 +20,60 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * April 14, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDSnapshot(SCDSessionRef session) +Boolean +SCDynamicStoreSnapshot(SCDynamicStoreRef store) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + int sc_status; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSnapshot:")); - SCDLog(LOG_DEBUG, CFSTR("SCDSnapshot:")); + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; + } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } - status = snapshot(sessionPrivate->server, (int *)&scd_status); + status = snapshot(storePrivate->server, (int *)&sc_status); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("snapshot(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("snapshot(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } + + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDTouch.c b/SystemConfiguration.fproj/SCDTouch.c index 2e83c37..ac3d6c4 100644 --- a/SystemConfiguration.fproj/SCDTouch.c +++ b/SystemConfiguration.fproj/SCDTouch.c @@ -20,33 +20,47 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * June 20, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDTouch(SCDSessionRef session, CFStringRef key) +Boolean +SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - CFDataRef xmlKey; /* serialized key */ - xmlData_t myKeyRef; - CFIndex myKeyLen; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + CFDataRef xmlKey; /* serialized key */ + xmlData_t myKeyRef; + CFIndex myKeyLen; + int sc_status; - SCDLog(LOG_DEBUG, CFSTR("SCDTouch:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreTouchValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - if (key == NULL) { - return SCD_INVALIDARGUMENT; /* no key specified */ + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; } /* serialize the key */ @@ -55,21 +69,27 @@ SCDTouch(SCDSessionRef session, CFStringRef key) myKeyLen = CFDataGetLength(xmlKey); /* send the key to the server */ - status = configtouch(sessionPrivate->server, + status = configtouch(storePrivate->server, myKeyRef, myKeyLen, - (int *)&scd_status); + (int *)&sc_status); /* clean up */ CFRelease(xmlKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configtouch(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configtouch(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } + + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDUnlock.c b/SystemConfiguration.fproj/SCDUnlock.c index c1540b9..38e7745 100644 --- a/SystemConfiguration.fproj/SCDUnlock.c +++ b/SystemConfiguration.fproj/SCDUnlock.c @@ -20,41 +20,60 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include -#include +#include +#include +#include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "SCDPrivate.h" - -SCDStatus -SCDUnlock(SCDSessionRef session) +Boolean +SCDynamicStoreUnlock(SCDynamicStoreRef store) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - kern_return_t status; - SCDStatus scd_status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + kern_return_t status; + int sc_status; - SCDLog(LOG_DEBUG, CFSTR("SCDUnlock:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreUnlock:")); - if (session == NULL) { - return SCD_NOSESSION; /* you can't do anything without closed session */ + if (!store) { + /* sorry, you must provide a session */ + _SCErrorSet(kSCStatusNoStoreSession); + return FALSE; } - scd_status = (sessionPrivate->server == MACH_PORT_NULL) ? SCD_NOSESSION : SCD_OK; + if (storePrivate->server == MACH_PORT_NULL) { + /* sorry, you must have an open session to play */ + _SCErrorSet(kSCStatusNoStoreServer); + return FALSE; + } - if (scd_status == SCD_OK) { - /* (attempt to) release the servers lock */ - status = configunlock(sessionPrivate->server, (int *)&scd_status); + /* (attempt to) release the servers lock */ + status = configunlock(storePrivate->server, (int *)&sc_status); + if (status != KERN_SUCCESS) { + if (status != MACH_SEND_INVALID_DEST) + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configunlock(): %s"), mach_error_string(status)); + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + _SCErrorSet(status); + return FALSE; + } - if (status != KERN_SUCCESS) { - if (status != MACH_SEND_INVALID_DEST) - SCDLog(LOG_DEBUG, CFSTR("configunlock(): %s"), mach_error_string(status)); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->server); - sessionPrivate->server = MACH_PORT_NULL; - return SCD_NOSERVER; - } + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; } - return scd_status; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDynamicStore.h b/SystemConfiguration.fproj/SCDynamicStore.h new file mode 100644 index 0000000..9347352 --- /dev/null +++ b/SystemConfiguration.fproj/SCDynamicStore.h @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCDYNAMICSTORE_H +#define _SCDYNAMICSTORE_H + +#include +#include +#include +#include + + +/*! + @header SCDynamicStore + The SystemConfiguration framework provides access to the + data used to configure a running system. The APIs provided + by this framework communicate with the "configd" daemon. + + The "configd" daemon manages a "dynamic store" reflecting the + desired configuration settings as well as the current state + of the system. The daemon provides a notification mechanism + for user-level processes that need to be aware of changes + made to the data. Lastly, the daemon loads a number of + bundles (or plug-ins) that monitor low-level kernel events + and, via a set of policy modules, keep the state data up + to date. + */ + + +/*! + @typedef SCDynamicStoreRef + @discussion This is the handle to an open "dynamic store" session + with the system configuration daemon. + */ +typedef const struct __SCDynamicStore * SCDynamicStoreRef; + +/*! + @typedef SCDynamicStoreContext + */ +typedef struct { + CFIndex version; + void * info; + const void *(*retain)(const void *info); + void (*release)(const void *info); + CFStringRef (*copyDescription)(const void *info); +} SCDynamicStoreContext; + +/*! + @typedef SCDynamicStoreCallBack + @discussion Type of the callback function used when a + dynamic store change is delivered. + @param store The "dynamic store" session. + @param changedKeys The list of changed keys. + @param info .... + */ +typedef void (*SCDynamicStoreCallBack) ( + SCDynamicStoreRef store, + CFArrayRef changedKeys, + void *info + ); + + +__BEGIN_DECLS + +/*! + @function SCDynamicStoreGetTypeID + Returns the type identifier of all SCDynamicStore instances. + */ +CFTypeID +SCDynamicStoreGetTypeID (void); + + +/*! + @function SCDynamicStoreCreate + @discussion Creates a new session used to interact with the dynamic + store maintained by the SystemConfiguration server. + @param allocator The CFAllocator which should be used to allocate + memory for the local "dynamic store" and its storage for + values. + This parameter may be NULL in which case the current + default CFAllocator is used. If this reference is not + a valid CFAllocator, the behavior is undefined. + @param name A string that describes the name of the calling + process or plug-in of the caller. + @param callout The function to be called when a watched value + in the "dynamic store" is changed. + A NULL value can be specified if no callouts are + desired. + @param context The SCDynamicStoreContext associated with the callout. + @result A reference to the new SCDynamicStore. + */ +SCDynamicStoreRef +SCDynamicStoreCreate ( + CFAllocatorRef allocator, + CFStringRef name, + SCDynamicStoreCallBack callout, + SCDynamicStoreContext *context + ); + +/*! + @function SCDynamicStoreCreateRunLoopSource + @discussion Creates a new session used to interact with the dynamic + store maintained by the SystemConfiguration server. + @param allocator The CFAllocator which should be used to allocate + memory for the local "dynamic store" and its storage for + values. + This parameter may be NULL in which case the current + default CFAllocator is used. If this reference is not + a valid CFAllocator, the behavior is undefined. + @param store The "dynamic store" session. + @param order On platforms which support it, this parameter + determines the order in which the sources which are + ready to be processed are handled. A lower order + number causes processing before higher order number + sources. It is inadvisable to depend on the order + number for any architectural or design aspect of + code. In the absence of any reason to do otherwise, + zero should be used. + @result A reference to the new CFRunLoopSource. + You must release the returned value. + + */ +CFRunLoopSourceRef +SCDynamicStoreCreateRunLoopSource ( + CFAllocatorRef allocator, + SCDynamicStoreRef store, + CFIndex order + ); + +/*! + @function SCDynamicStoreCopyKeyList + @discussion Returns an array of CFString keys representing the + configuration "dynamic store" entries that match a + specified pattern. + @param store The "dynamic store" session. + @param pattern A regex(3) regular expression pattern that + will be used to match the "dynamic store" keys. + @result The list of matching keys. + You must release the returned value. + A NULL value will be returned if the list could not be obtained. + */ +CFArrayRef +SCDynamicStoreCopyKeyList ( + SCDynamicStoreRef store, + CFStringRef pattern + ); + +/*! + @function SCDynamicStoreAddValue + @discussion Adds the key-value pair to the "dynamic store" if no + such key already exists. + @param store The "dynamic store" session. + @param key The key of the value to add to the "dynamic store". + @param value The value to add to the "dynamic store". + @result TRUE if the key was added; FALSE if the key was already + present in the "dynamic store" or if an error was encountered. + */ +Boolean +SCDynamicStoreAddValue ( + SCDynamicStoreRef store, + CFStringRef key, + CFPropertyListRef value + ); + +/*! + @function SCDynamicStoreAddTemporaryValue + @discussion Adds the key-value pair on a temporary basis to the + "dynamic store" if no such key already exists. This entry + will, unless updated by another session, automatically be + removed when the session is closed. + @param store The "dynamic store" session. + @param key The key of the value to add to the "dynamic store". + @param value The value to add to the "dynamic store". + @result TRUE if the key was added; FALSE if the key was already + present in the "dynamic store" or if an error was encountered. + */ +Boolean +SCDynamicStoreAddTemporaryValue ( + SCDynamicStoreRef store, + CFStringRef key, + CFPropertyListRef value + ); + +/*! + @function SCDynamicStoreCopyValue + @discussion Obtains a value from the "dynamic store" for the + specified key. + @param store The "dynamic store" session. + @param key The key you wish to obtain. + @result The value from the store that is associated with the + given key. The value is returned as a Core Foundation + Property List data type. + You must release the returned value. + If no value was located, NULL is returned. + */ +CFPropertyListRef +SCDynamicStoreCopyValue ( + SCDynamicStoreRef store, + CFStringRef key + ); + +/*! + @function SCDynamicStoreCopyMultiple + @discussion Fetches multiple values in the "dynamic store". + @param store The "dynamic store" session. + @param keys The keys to be fetched; NULL if no specific keys + are requested. + @param patterns The regex(3) pattern strings to be fetched; NULL + if no key patterns are requested. + @result A dictionary containing the specific keys which were found + in the "dynamic store" and any keys which matched the specified + patterns; NULL is returned if an error was encountered. + You must release the returned value. + */ +CFDictionaryRef +SCDynamicStoreCopyMultiple ( + SCDynamicStoreRef store, + CFArrayRef keys, + CFArrayRef patterns + ); + +/*! + @function SCDynamicStoreSetValue + @discussion Adds or replaces a value in the "dynamic store" for + the specified key. + @param store The "dynamic store" session. + @param key The key you wish to set. + @param value The value to add to or replace in the "dynamic store". + @result TRUE if the key was updated; FALSE if an error was encountered. + */ +Boolean +SCDynamicStoreSetValue ( + SCDynamicStoreRef store, + CFStringRef key, + CFPropertyListRef value + ); + +/*! + @function SCDynamicStoreSetMultiple + @discussion Updates multiple values in the "dynamic store". + @param store The "dynamic store" session. + @param keysToSet Key/value pairs you wish to set into the "dynamic store". + @param keysToRemove A list of keys you wish to remove from the "dynamic store". + @param keysToNotify A list of keys to flag as changed (without actually changing the data). + @result TRUE if the dynamic store updates were successful; FALSE if an error was encountered. + */ +Boolean +SCDynamicStoreSetMultiple ( + SCDynamicStoreRef store, + CFDictionaryRef keysToSet, + CFArrayRef keysToRemove, + CFArrayRef keysToNotify + ); + +/*! + @function SCDynamicStoreRemoveValue + @discussion Removes the value of the specified key from the + "dynamic store". + @param store The "dynamic store" session. + @param key The key of the value you wish to remove. + @result TRUE if the key was removed; FALSE if no value was + located or an error was encountered. + */ +Boolean +SCDynamicStoreRemoveValue ( + SCDynamicStoreRef store, + CFStringRef key + ); + +/*! + @function SCDynamicStoreNotifyValue + @discussion Triggers a notification to be delivered for the + specified key in the dynamic store. + @param store The "dynamic store" session. + @param key The key which should be flagged as changed (without actually changing the data). + @result TRUE if the value was updated; FALSE if an error was encountered. + */ +Boolean +SCDynamicStoreNotifyValue ( + SCDynamicStoreRef store, + CFStringRef key + ); + +/*! + @function SCDynamicStoreSetNotificationKeys + @discussion Specifies a set of specific keys and key patterns + which should be monitored for changes. + @param store The "dynamic store" session being watched. + @param keys The keys to be monitored; NULL if no specific keys + are to be monitored. + @param patterns The regex(3) pattern strings to be monitored; NULL + if no key patterns are to be monitored. + @result TRUE if the monitored keys were set; FALSE if an error + was encountered. + */ +Boolean +SCDynamicStoreSetNotificationKeys ( + SCDynamicStoreRef store, + CFArrayRef keys, + CFArrayRef patterns + ); + +/*! + @function SCDynamicStoreCopyNotifiedKeys + @discussion Returns an array of CFString keys representing the + "dynamic store" entries that have changed since this + function was last called. + @param store The "dynamic store" session. + @result The list of changed keys. + You must release the returned value. + A NULL value will be returned if the list could not be obtained. + */ +CFArrayRef +SCDynamicStoreCopyNotifiedKeys ( + SCDynamicStoreRef store + ); + +__END_DECLS + +#endif /* _SCDYNAMICSTORE_H */ diff --git a/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h b/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h new file mode 100644 index 0000000..fa34138 --- /dev/null +++ b/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCDYNAMICSTORECOPYDHCPINFO_H +#define _SCDYNAMICSTORECOPYDHCPINFO_H + +#include +#include +#include + + +/*! + @header SCDynamicStoreCopyDHCPInfo.h + The following APIs allow an application to retrieve DHCP/BOOTP + information, in particular DHCP/BOOTP options. + */ + + +__BEGIN_DECLS + +/*! + @function SCDynamicStoreCopyDHCPInfo + @discussion Copies the DHCP/BOOTP information dictionary for the + requested serviceID, or the primary service if + serviceID == NULL. + @param store An SCDynamicStoreRef that should be used for communication + with the server. + If NULL, a temporary session will be used. + @param serviceID A CFStringRef containing the requested service. + If NULL, returns information for the primary service. + @result A dictionary containing DHCP/BOOTP information if successful, + NULL otherwise. + Use the DHCPInfoGetOption() to retrieve + individual options from the returned dictionary. + + A non-NULL return value must be released using CFRelease(). + */ +CFDictionaryRef +SCDynamicStoreCopyDHCPInfo(SCDynamicStoreRef store, CFStringRef serviceID); + +/*! + @function DHCPInfoGetOptionData + @discussion Returns a non-NULL CFDataRef containing the BOOTP/DHCP + option data if present, NULL otherwise. + @param info The non-NULL DHCP information dictionary returned by + calling SCDynamicStoreCopyDHCPInfo. + @param code The DHCP/BOOTP option code (see RFC 2132) to return + data for. + @result A non-NULL CFDataRef containing the option data, + NULL otherwise. + + The return value must NOT be released. + */ +CFDataRef +DHCPInfoGetOptionData(CFDictionaryRef info, UInt8 code); + +/*! + @function DHCPInfoGetLeaseStartTime + @discussion Returns a CFDateRef corresponding to the lease start time, + if present, NULL otherwise. A NULL return value is returned + if the configuration method is BOOTP. + @param info The non-NULL DHCP information dictionary returned by + calling SCDynamicStoreCopyDHCPInfo. + @result A non-NULL CFDateRef if present, NULL otherwise. + + The return value must NOT be released. + */ +CFDateRef +DHCPInfoGetLeaseStartTime(CFDictionaryRef info); + +__END_DECLS + +#endif /* _SCDYNAMICSTORECOPYDHCPINFO_H */ diff --git a/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h b/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h new file mode 100644 index 0000000..89ab3bf --- /dev/null +++ b/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCDYNAMICSTORECOPYSPECIFIC_H +#define _SCDYNAMICSTORECOPYSPECIFIC_H + +#include +#include +#include + + +/*! + @header SCDynamicStoreCopySpecific + The following APIs allow an application to determine specific + configuration information about the current system (e.g. the + computer/sharing name, the currently logged in user, etc). + */ + + +__BEGIN_DECLS + +/*! + @function SCDynamicStoreCopyComputerName + @discussion Gets the current computer/host name. + @param store An SCDynamicStoreRef that should be used for communication + with the server. + If NULL, a temporary session will be used. + @param nameEncoding A pointer to memory that, if non-NULL, will be + filled with the encoding associated with the computer/host name. + @result The current computer/host name; + NULL if the name has not been set or if an error was encountered. + You must release the returned value. + */ +CFStringRef +SCDynamicStoreCopyComputerName ( + SCDynamicStoreRef store, + CFStringEncoding *nameEncoding + ); + +/*! + @function SCDynamicStoreCopyConsoleUser + @discussion Gets the name, user ID, and group ID of the currently + logged in user. + @param store An SCDynamicStoreRef that should be used for communication + with the server. + If NULL, a temporary session will be used. + @param uid A pointer to memory that will be filled with the user ID + of the current "Console" user. If NULL, this value will not + be returned. + @param gid A pointer to memory that will be filled with the group ID + of the current "Console" user. If NULL, this value will not be + returned. + @result The current user logged into the system; + NULL if no user is logged in or if an error was encountered. + You must release the returned value. + */ +CFStringRef +SCDynamicStoreCopyConsoleUser ( + SCDynamicStoreRef session, + uid_t *uid, + gid_t *gid + ); + +/*! + @function SCDynamicStoreCopyProxies + @discussion Gets the current internet proxy settings. + @param store An SCDynamicStoreRef that should be used for communication + with the server. + If NULL, a temporary session will be used. + @result A dictionary with key/value pairs representing the current + internet proxy settings (HTTP, FTP, etc); + NULL if no proxy settings have been defined or if an error was encountered. + You must release the returned value. + */ +CFDictionaryRef +SCDynamicStoreCopyProxies ( + SCDynamicStoreRef store + ); + +__END_DECLS + +#endif /* _SCDYNAMICSTORECOPYSPECIFIC_H */ diff --git a/SystemConfiguration.fproj/SCDynamicStoreInternal.h b/SystemConfiguration.fproj/SCDynamicStoreInternal.h new file mode 100644 index 0000000..f007b53 --- /dev/null +++ b/SystemConfiguration.fproj/SCDynamicStoreInternal.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCDYNAMICSTOREINTERNAL_H +#define _SCDYNAMICSTOREINTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Define the status of any registered notification. */ +typedef enum { + NotifierNotRegistered = 0, + Using_NotifierWait, + Using_NotifierInformViaCallback, + Using_NotifierInformViaMachPort, + Using_NotifierInformViaFD, + Using_NotifierInformViaSignal, + Using_NotifierInformViaRunLoop, +} __SCDynamicStoreNotificationStatus; + + +typedef struct { + + /* base CFType information */ + CFRuntimeBase cfBase; + + /* server side of the "configd" session */ + mach_port_t server; + + /* per-session flags */ + Boolean locked; + + /* SCDynamicStoreKeys being watched */ + CFMutableSetRef keys; + CFMutableSetRef reKeys; + + /* current status of notification requests */ + __SCDynamicStoreNotificationStatus notifyStatus; + + /* "client" information associated with SCDynamicStoreCreateRunLoopSource() */ + CFIndex rlsRefs; + CFRunLoopSourceRef rls; + SCDynamicStoreCallBack rlsFunction; + SCDynamicStoreContext rlsContext; + + /* "client" information associated with SCDynamicStoreNotifyCallback() */ + SCDynamicStoreCallBack_v1 callbackFunction; + void *callbackArgument; + CFMachPortRef callbackPort; + CFRunLoopRef callbackRunLoop; + CFRunLoopSourceRef callbackRunLoopSource; + + /* "server" information associated with SCDynamicStoreNotifyMachPort() */ + mach_port_t notifyPort; + mach_msg_id_t notifyPortIdentifier; + + /* "server" information associated with SCDynamicStoreNotifyFileDescriptor() */ + int notifyFile; + int notifyFileIdentifier; + + /* "server" information associated with SCDynamicStoreNotifySignal() */ + int notifySignal; + task_t notifySignalTask; + +} SCDynamicStorePrivate, *SCDynamicStorePrivateRef; + + +__BEGIN_DECLS + +SCDynamicStoreRef +__SCDynamicStoreCreatePrivate (CFAllocatorRef allocator, + const CFStringRef name, + SCDynamicStoreCallBack callout, + SCDynamicStoreContext *context); + +void +__SCLog (int level, + CFStringRef str); + +void +__SCPrint (FILE *stream, + CFStringRef str); + +void +__showMachPortStatus (); + +void +__showMachPortReferences (mach_port_t port); + +__END_DECLS + +#endif /* _SCDYNAMICSTOREINTERNAL_H */ diff --git a/SystemConfiguration.fproj/SCDynamicStoreKey.h b/SystemConfiguration.fproj/SCDynamicStoreKey.h new file mode 100644 index 0000000..aa76284 --- /dev/null +++ b/SystemConfiguration.fproj/SCDynamicStoreKey.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCDYNAMICSTOREKEY_H +#define _SCDYNAMICSTOREKEY_H + +#include +#include + + +/*! + @header SCDynamicStoreKey + */ + + +__BEGIN_DECLS + +/* + * SCDynamicStoreKeyCreate* + * - convenience routines that create a CFString key for an item in the store + */ + +/*! + @function SCDynamicStoreKeyCreate + @discussion Creates a store key using the given format. + */ +CFStringRef +SCDynamicStoreKeyCreate ( + CFAllocatorRef allocator, + CFStringRef fmt, + ... + ); + +/*! + @function SCDynamicStoreKeyCreateNetworkGlobalEntity + */ +CFStringRef +SCDynamicStoreKeyCreateNetworkGlobalEntity ( + CFAllocatorRef allocator, + CFStringRef domain, + CFStringRef entity + ); + +/*! + @function SCDynamicStoreKeyCreateNetworkInterface + */ +CFStringRef +SCDynamicStoreKeyCreateNetworkInterface ( + CFAllocatorRef allocator, + CFStringRef domain + ); + +/*! + @function SCDynamicStoreKeyCreateNetworkInterfaceEntity + */ +CFStringRef +SCDynamicStoreKeyCreateNetworkInterfaceEntity ( + CFAllocatorRef allocator, + CFStringRef domain, + CFStringRef ifname, + CFStringRef entity + ); + +/*! + @function SCDynamicStoreKeyCreateNetworkServiceEntity + */ +CFStringRef +SCDynamicStoreKeyCreateNetworkServiceEntity ( + CFAllocatorRef allocator, + CFStringRef domain, + CFStringRef serviceID, + CFStringRef entity + ); + +/*! + @function SCDynamicStoreKeyCreateComputerName + @discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys() + function to receive notifications when the current + computer/host name changes. + @result A notification string for the current computer/host name. +*/ +CFStringRef +SCDynamicStoreKeyCreateComputerName ( + CFAllocatorRef allocator + ); + +/*! + @function SCDynamicStoreKeyCreateConsoleUser + @discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys() + function to receive notifications when the current "Console" + user changes. + @result A notification string for the current "Console" user. +*/ +CFStringRef +SCDynamicStoreKeyCreateConsoleUser ( + CFAllocatorRef allocator + ); + +/*! + @function SCDynamicStoreKeyCreateProxies + @discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys() + function to receive notifications when the current network proxy + settings (HTTP, FTP, ...) are changed. + @result A notification string for the current proxy settings. +*/ +CFStringRef +SCDynamicStoreKeyCreateProxies ( + CFAllocatorRef allocator + ); + +__END_DECLS + +#endif /* _SCDYNAMICSTOREKEY_H */ diff --git a/SystemConfiguration.fproj/SCDynamicStorePrivate.h b/SystemConfiguration.fproj/SCDynamicStorePrivate.h new file mode 100644 index 0000000..03d43e1 --- /dev/null +++ b/SystemConfiguration.fproj/SCDynamicStorePrivate.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCDYNAMICSTOREPRIVATE_H +#define _SCDYNAMICSTOREPRIVATE_H + +#include +#include +#include +#include +#include + +/*! + @typedef SCDynamicStoreCallBack + @discussion Type of the callback function used when a + dynamic store change is delivered. + @param store The "dynamic store" session. + @param changedKeys The list of changed keys. + @param info .... + */ +typedef boolean_t (*SCDynamicStoreCallBack_v1) ( + SCDynamicStoreRef store, + void *info + ); + + +__BEGIN_DECLS + +/*! + @function SCDynamicStoreLock + @discussion Locks access to the configuration "dynamic store". All + other clients attempting to access the "dynamic store" will + block. All change notifications will be deferred until the + lock is released. + @param store The "dynamic store" session that should be locked. + @result TRUE if the lock was obtained; FALSE if an error was encountered. + */ +Boolean +SCDynamicStoreLock (SCDynamicStoreRef store); + +/*! + @function SCDynamicStoreUnlock + @discussion Unlocks access to the configuration "dynamic store". Other + clients will be able to access the "dynamic store". Any change + notifications will be delivered. + @param store The "dynamic store" session that should be unlocked. + @result TRUE if the lock was released; FALSE if an error was encountered. + */ +Boolean +SCDynamicStoreUnlock (SCDynamicStoreRef store); + +/*! + @function SCDynamicStoreTouchValue + @discussion Updates the value of the specified key in the + "dynamic store". + If the value does not exist then a CFDate object + will be associated with the key. + If the associated data is already a CFDate object + then it will be updated with the current time. + @param store The "dynamic store" session. + @param key The key of the value to updated. + @result TRUE if the value was updated; FALSE if an error was encountered. + */ +Boolean +SCDynamicStoreTouchValue (SCDynamicStoreRef store, + CFStringRef key); + +/*! + @function SCDynamicStoreAddWatchedKey + @discussion Adds the specified key to the list of "dynamic store" + values that are being monitored for changes. + @param store The "dynamic store" session being watched. + @param key The key to be monitored. + @param isRegex A booolean indicating whether a specific key should + be monitored or if it consists of a regex(3) pattern string + of keys. + @result TRUE if the key was successfully added to the "watch" + list; FALSE if an error was encountered. + */ +Boolean +SCDynamicStoreAddWatchedKey (SCDynamicStoreRef store, + CFStringRef key, + Boolean isRegex); + +/*! + @function SCDynamicStoreRemoveWatchedKey + @discussion Removes the specified key from the list of "dynamic store" + values that are being monitored for changes. + @param store The "dynamic store" session being watched. + @param key The key that should no longer be monitored. + @param isRegex A booolean indicating whether a specific key should + be monitored or if it consists of a regex(3) pattern string + of keys. + @result TRUE if the key was successfully removed from the "watch" + list; FALSE if an error was encountered. + */ +Boolean +SCDynamicStoreRemoveWatchedKey (SCDynamicStoreRef store, + CFStringRef key, + Boolean isRegex); + +CFArrayRef +SCDynamicStoreCopyWatchedKeyList (SCDynamicStoreRef store, + Boolean isRegex); + +/*! + @function SCDynamicStoreNotifyCallback + @discussion Requests that the specified function be called whenever a + change has been detected to one of the "dynamic store" values + being monitored. + + The callback function will be called with two arguments, store and + context, that correspond to the current "dynamic store" session and + the provided context argument. + + The callback function should return a Boolean value indicating + whether an error occurred during execution of the callback. + + Note: An additional run loop source will be added for the notification. + This additional source will be removed if the notification is cancelled + or if the callback indicates that an error was detected. + + @param store The "dynamic store" session. + @param runLoop A pointer to the run loop. + @param funct The callback function to call for each notification. + If this parameter is not a pointer to a function of the + correct prototype, the behavior is undefined. + @param context A pointer-sized user-defined value, that is passed as + the second parameter to the notification callback function, + but is otherwise unused by this function. If the context + is not what is expected by the notification function, the + behavior is undefined. + @result TRUE if the notification callback runloop source was + successfully added; FALSE if an error was encountered. + */ +Boolean +SCDynamicStoreNotifyCallback (SCDynamicStoreRef store, + CFRunLoopRef runLoop, + SCDynamicStoreCallBack_v1 func, + void *context); + +/*! + @function SCDynamicStoreNotifyMachPort + @discussion Allocates a mach port that can be used to detect changes to + one of the system configuration data entries associated with the + current session's notifier keys. When a change is detected, an + empty (no data) mach message with the specified identifier will + be delivered to the calling application via the allocated port. + + @param store An SCDynamicStoreRef that should be used for communication with the server. + @param msgid A mach message ID to be included with any notifications. + @param port A pointer to a mach port. Upon return, port will be filled + with the mach port that will be used for any notifications. + @result A boolean indicating the success (or failure) of the call. + */ +Boolean +SCDynamicStoreNotifyMachPort (SCDynamicStoreRef store, + mach_msg_id_t msgid, + mach_port_t *port); + +/*! + @function SCDynamicStoreNotifyFileDescriptor + @discussion Allocates a file descriptor that can be used to detect changes + to one of the system configuration data entries associated with the + current session's notifier keys. When a change is detected, the + specified identifier (4 bytes) will be delivered to the calling + application via the allocated file descriptor. + + @param store An SCDynamicStoreRef that should be used for communication with the server. + @param identifier A (4 byte) integer that can be used to identify this + notification. + @param fd A pointer to a file descriptor. Upon return, fd will + contain the file descriptor that will be used for any notifications. + @result A boolean indicating the success (or failure) of the call. + */ +Boolean +SCDynamicStoreNotifyFileDescriptor (SCDynamicStoreRef store, + int32_t identifier, + int *fd); + +/*! + @function SCDynamicStoreNotifySignal + @discussion Requests that the specified BSD signal be sent to the process + with the indicated process id whenever a change has been detected + to one of the system configuration data entries associated with the + current session's notifier keys. + + Note: this function is not valid for "configd" plug-ins. + + @param store An SCDynamicStoreRef that should be used for communication with the server. + @param pid A UNIX process ID that should be signalled for any notifications. + @param sig A signal number to be used. + @result A boolean indicating the success (or failure) of the call. + */ +Boolean +SCDynamicStoreNotifySignal (SCDynamicStoreRef store, + pid_t pid, + int sig); + +/*! + @function SCDynamicStoreNotifyWait + @discussion Waits for a change to be made to a value in the + "dynamic store" that is being monitored. + @param store The "dynamic store" session. + @result TRUE if a change has been detected; FALSE if an error was encountered. + */ +Boolean +SCDynamicStoreNotifyWait (SCDynamicStoreRef store); + +/*! + @function SCDynamicStoreNotifyCancel + @discussion Cancels any outstanding notification requests for + this "dynamic store" session. + + @param store The "dynamic store" session. + @result TRUE if all notifications have been cancelled; FALSE if an + error was encountered. + */ +Boolean +SCDynamicStoreNotifyCancel (SCDynamicStoreRef store); + +Boolean +SCDynamicStoreSnapshot (SCDynamicStoreRef store); + +__END_DECLS + +#endif /* _SCDYNAMICSTOREPRIVATE_H */ diff --git a/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h b/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h new file mode 100644 index 0000000..eb58171 --- /dev/null +++ b/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCDYNAMICSTORESETSPECIFICPRIVATE_H +#define _SCDYNAMICSTORESETSPECIFICPRIVATE_H + +#include +#include + + +__BEGIN_DECLS + +/*! + @function SCDynamicStoreSetConsoleUser + @discussion Sets the name, user ID, and group ID of the currently + logged in user. + @param session An SCDynamicStoreRef that should be used for communication + with the server. + If NULL, a temporary session will be used. + @param user A pointer to a character buffer containing the name of + the current "Console" user. If NULL, any current "Console" + user information will be reset. + @param uid The user ID of the current "Console" user. + @param gid The group ID of the current "Console" user. + @result A boolean indicating the success (or failure) of the call. + */ +Boolean +SCDynamicStoreSetConsoleUser ( + SCDynamicStoreRef session, + const char *user, + uid_t uid, + gid_t gid + ); + +__END_DECLS + +#endif /* _SCDYNAMICSTORESETSPECIFICPRIVATE_H */ diff --git a/SystemConfiguration.fproj/SCNetwork.c b/SystemConfiguration.fproj/SCNetwork.c index 1828984..b413ec8 100644 --- a/SystemConfiguration.fproj/SCNetwork.c +++ b/SystemConfiguration.fproj/SCNetwork.c @@ -20,7 +20,22 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 10, 2001 Allan Nathanson + * - updated to use service-based "State:" information + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * January 30, 2001 Allan Nathanson + * - initial revision + */ + #include +#include +#include #include #include @@ -34,7 +49,6 @@ #include "ppp.h" - static int inet_atonCF(CFStringRef cfStr, struct in_addr *addr) { @@ -82,405 +96,452 @@ parse_component(CFStringRef key, CFStringRef prefix) } -/* - * return a dictionary of configured services. - */ -static CFDictionaryRef -getServices(SCDSessionRef session) +typedef struct { + CFMutableDictionaryRef aDict; /* active services */ + CFStringRef aPrefix; /* prefix for active services */ + CFMutableDictionaryRef cDict; /* configured services */ + CFStringRef cPrefix; /* prefix for configured services */ + CFMutableDictionaryRef iDict; /* active interfaces */ + CFStringRef iPrefix; /* prefix for active interfaces */ + CFMutableArrayRef order; /* service order */ +} initContext, *initContextRef; + + +static void +collectInfo(const void *key, const void *value, void *context) { - CFArrayRef defined = NULL; - int i; - CFStringRef key; - CFStringRef prefix; - CFMutableDictionaryRef services; - SCDStatus status; - - prefix = SCDKeyCreate(CFSTR("%@/%@/%@/"), - kSCCacheDomainSetup, - kSCCompNetwork, - kSCCompService); - - services = CFDictionaryCreateMutable(NULL, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - key = SCDKeyCreateNetworkServiceEntity(kSCCacheDomainSetup, - kSCCompAnyRegex, - kSCEntNetIPv4); - status = SCDList(session, key, kSCDRegexKey, &defined); - CFRelease(key); - if (status != SCD_OK) { - goto done; + initContextRef info = (initContextRef)context; + CFStringRef interface; + CFStringRef interfaceKey; + CFStringRef service; + CFStringRef serviceKey; + + if (!isA_CFString(key) || !isA_CFDictionary(value)) { + return; } - for (i = 0; i < CFArrayGetCount(defined); i++) { - CFDictionaryRef if_dict; - SCDHandleRef if_handle = NULL; - CFDictionaryRef ip_dict; - SCDHandleRef ip_handle = NULL; - boolean_t isPPP = FALSE; - CFDictionaryRef ppp_dict; - SCDHandleRef ppp_handle = NULL; - CFMutableDictionaryRef sDict = NULL; - CFStringRef sid = NULL; - - key = CFArrayGetValueAtIndex(defined, i); - - /* get IPv4 dictionary for service */ - status = SCDGet(session, key, &ip_handle); - if (status != SCD_OK) { - /* if service was removed behind our back */ - goto nextService; + service = parse_component((CFStringRef)key, info->cPrefix); + if (service) { + serviceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + service, + kSCEntNetIPv4); + if (CFEqual((CFStringRef)key, serviceKey)) { + CFMutableDictionaryRef dict; + + dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)value); + CFDictionaryAddValue(info->cDict, service, dict); + CFRelease(dict); } - ip_dict = SCDHandleGetData(ip_handle); - - sDict = CFDictionaryCreateMutableCopy(NULL, 0, ip_dict); + CFRelease(serviceKey); - /* add keys from the service's Interface dictionary */ - sid = parse_component(key, prefix); - if (sid == NULL) { - goto nextService; + if (!CFArrayContainsValue(info->order, CFRangeMake(0, CFArrayGetCount(info->order)), service)) { + CFArrayAppendValue(info->order, service); } - key = SCDKeyCreateNetworkServiceEntity(kSCCacheDomainSetup, - sid, - kSCEntNetInterface); - status = SCDGet(session, key, &if_handle); - CFRelease(key); - if (status != SCD_OK) { - goto nextService; - } - if_dict = SCDHandleGetData(if_handle); - - /* check the interface "Type", "SubType", and "DeviceName" */ - if (CFDictionaryGetValueIfPresent(if_dict, - kSCPropNetInterfaceType, - (void **)&key)) { - CFDictionaryAddValue(sDict, kSCPropNetInterfaceType, key); - isPPP = CFEqual(key, kSCValNetInterfaceTypePPP); + CFRelease(service); + return; + } + + service = parse_component((CFStringRef)key, info->aPrefix); + if (service) { + serviceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainState, + service, + kSCEntNetIPv4); + if (CFEqual((CFStringRef)key, serviceKey)) { + CFMutableDictionaryRef dict; + + dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)value); + CFDictionaryAddValue(info->aDict, service, dict); + CFRelease(dict); } - if (CFDictionaryGetValueIfPresent(if_dict, - kSCPropNetInterfaceSubType, - (void **)&key)) { - CFDictionaryAddValue(sDict, kSCPropNetInterfaceSubType, key); + CFRelease(serviceKey); + + if (!CFArrayContainsValue(info->order, CFRangeMake(0, CFArrayGetCount(info->order)), service)) { + CFArrayAppendValue(info->order, service); } - if (isPPP) { - key = SCDKeyCreateNetworkServiceEntity(kSCCacheDomainSetup, - sid, - kSCEntNetPPP); - status = SCDGet(session, key, &ppp_handle); - CFRelease(key); - if (status != SCD_OK) { - goto nextService; - } - ppp_dict = SCDHandleGetData(ppp_handle); + CFRelease(service); + return; + } - /* get Dial-on-Traffic flag */ - if (CFDictionaryGetValueIfPresent(ppp_dict, - kSCPropNetPPPDialOnDemand, - (void **)&key)) { - CFDictionaryAddValue(sDict, kSCPropNetPPPDialOnDemand, key); - } + interface = parse_component((CFStringRef)key, info->iPrefix); + if (interface) { + interfaceKey = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, + kSCDynamicStoreDomainState, + interface, + kSCEntNetIPv4); + if (CFEqual((CFStringRef)key, interfaceKey)) { + CFMutableDictionaryRef dict; + + dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)value); + CFDictionaryAddValue(info->iDict, interface, dict); + CFRelease(dict); } + CFRelease(interfaceKey); + CFRelease(interface); + return; + } + + return; +} - CFDictionaryAddValue(services, sid, sDict); - nextService: +static void +collectExtraInfo(const void *key, const void *value, void *context) +{ + CFStringRef interfaceKey; + initContextRef info = (initContextRef)context; + CFMutableDictionaryRef dict; + Boolean match; + CFStringRef pppKey; + CFStringRef service; + + if (!isA_CFString(key) || !isA_CFDictionary(value)) { + return; + } + + service = parse_component((CFStringRef)key, info->cPrefix); + if (!service) { + /* this key/value pair contains supplemental information */ + return; + } + + dict = (CFMutableDictionaryRef)CFDictionaryGetValue(info->cDict, service); + if (!dict) { + /* we don't have any IPv4 information for this service */ + goto done; + } - if (sid) CFRelease(sid); - if (if_handle) SCDHandleRelease(if_handle); - if (ip_handle) SCDHandleRelease(ip_handle); - if (ppp_handle) SCDHandleRelease(ppp_handle); - if (sDict) CFRelease(sDict); + interfaceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + service, + kSCEntNetInterface); + match = CFEqual((CFStringRef)key, interfaceKey); + CFRelease(interfaceKey); + if (match) { + CFStringRef interface; + + interface = CFDictionaryGetValue((CFDictionaryRef)value, + kSCPropNetInterfaceType); + if (isA_CFString(interface)) { + /* if "InterfaceType" available */ + CFDictionaryAddValue(dict, kSCPropNetInterfaceType, interface); + CFDictionarySetValue(info->cDict, service, dict); + } + goto done; } - done: + pppKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + service, + kSCEntNetPPP); + match = CFEqual((CFStringRef)key, pppKey); + CFRelease(pppKey); + if (match) { + CFNumberRef dialOnDemand; + + dialOnDemand = CFDictionaryGetValue((CFDictionaryRef)value, + kSCPropNetPPPDialOnDemand); + if (isA_CFNumber(dialOnDemand)) { + /* if "DialOnDemand" information not available */ + CFDictionaryAddValue(dict, kSCPropNetPPPDialOnDemand, dialOnDemand); + CFDictionarySetValue(info->cDict, service, dict); + } + goto done; + } - if (defined) CFRelease(defined); - CFRelease(prefix); + done : - return services; + CFRelease(service); + return; } -/* - * return a dictionary of configured interfaces. - */ -static CFDictionaryRef -getInterfaces(SCDSessionRef session) +static void +removeKnownAddresses(const void *key, const void *value, void *context) { - CFMutableArrayRef defined = NULL; - int i; - CFStringRef key; - CFMutableDictionaryRef interfaces; - CFStringRef prefix; - SCDStatus status; - - prefix = SCDKeyCreate(CFSTR("%@/%@/%@/"), - kSCCacheDomainState, - kSCCompNetwork, - kSCCompInterface); + CFMutableDictionaryRef ifDict; + CFStringRef ifName; + CFMutableDictionaryRef interfaces = (CFMutableDictionaryRef)context; + CFMutableDictionaryRef serviceDict = (CFMutableDictionaryRef)value; + Boolean updated = FALSE; - interfaces = CFDictionaryCreateMutable(NULL, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); + CFIndex i; + CFArrayRef iAddrs; + CFArrayRef iDests; + CFArrayRef iMasks; + CFIndex n; + CFMutableArrayRef nAddrs = NULL; + CFMutableArrayRef nDests = NULL; + CFMutableArrayRef nMasks = NULL; + CFIndex s; + CFArrayRef sAddrs; + CFArrayRef sDests; + CFArrayRef sMasks; + + ifName = CFDictionaryGetValue(serviceDict, kSCPropInterfaceName); + if (!ifName) { + /* if no "InterfaceName" for this service */ + return; + } - key = SCDKeyCreateNetworkInterfaceEntity(kSCCacheDomainState, - kSCCompAnyRegex, - kSCEntNetIPv4); - status = SCDList(session, key, kSCDRegexKey, &defined); - CFRelease(key); - if (status != SCD_OK) { - goto done; + ifDict = (CFMutableDictionaryRef)CFDictionaryGetValue(interfaces, ifName); + if (!ifDict) { + /* if the indicated interface is not active */ + return; } - for (i=0; i= 0) { + if (sMasks && + CFEqual(CFArrayGetValueAtIndex(sAddrs, s), + CFArrayGetValueAtIndex(nAddrs, i)) && + CFEqual(CFArrayGetValueAtIndex(sMasks, s), + CFArrayGetValueAtIndex(nMasks, i)) + ) { + /* we have a match */ + CFArrayRemoveValueAtIndex(nAddrs, i); + CFArrayRemoveValueAtIndex(nMasks, i); + updated = TRUE; + } else if (sDests && + CFEqual(CFArrayGetValueAtIndex(sAddrs, s), + CFArrayGetValueAtIndex(nAddrs, i)) && + CFEqual(CFArrayGetValueAtIndex(sDests, s), + CFArrayGetValueAtIndex(nDests, i)) + ) { + /* we have a match */ + CFArrayRemoveValueAtIndex(nAddrs, i); + CFArrayRemoveValueAtIndex(nDests, i); + updated = TRUE; } } } - for (i = 0; i < CFArrayGetCount(iKeys); i++) { - CFStringRef iKey; + if (updated) { + if (nAddrs) { + CFDictionarySetValue(ifDict, + kSCPropNetIPv4Addresses, + nAddrs); + } + if (nMasks) { + CFDictionarySetValue(ifDict, + kSCPropNetIPv4SubnetMasks, + nMasks); + } else { + CFDictionarySetValue(ifDict, + kSCPropNetIPv4DestAddresses, + nDests); + } + CFDictionarySetValue(interfaces, ifName, ifDict); + } + CFRelease(nAddrs); + if (nMasks) CFRelease(nMasks); + if (nDests) CFRelease(nDests); + + return; +} - iKey = CFArrayGetValueAtIndex(iKeys, i); - CFArrayAppendValue(order, iKey); + +static void +addUnknownService(const void *key, const void *value, void *context) +{ + CFArrayRef addrs; + CFMutableDictionaryRef ifDict = (CFMutableDictionaryRef)value; + initContextRef info = (initContextRef)context; + CFStringRef service; + CFUUIDRef uuid; + + addrs = CFDictionaryGetValue(ifDict, kSCPropNetIPv4Addresses); + if (!addrs || (CFArrayGetCount(addrs) == 0)) { + /* if no addresses */ + return; } - CFRelease(iKeys); - return order; + /* add the "InterfaceName" to the (new/fake) service dictionary */ + CFDictionaryAddValue(ifDict, kSCPropInterfaceName, (CFStringRef)key); + + /* create a (new/fake) service to hold any remaining addresses */ + uuid = CFUUIDCreate(NULL); + service = CFUUIDCreateString(NULL, uuid); + CFDictionaryAddValue(info->aDict, service, ifDict); + CFArrayAppendValue(info->order, service); + CFRelease(service); + CFRelease(uuid); + + return; } -static boolean_t +static Boolean getAddresses(CFDictionaryRef iDict, CFIndex *nAddrs, CFArrayRef *addrs, CFArrayRef *masks, CFArrayRef *dests) { - *addrs = CFDictionaryGetValue(iDict, kSCPropNetIPv4Addresses); - *masks = CFDictionaryGetValue(iDict, kSCPropNetIPv4SubnetMasks); - *dests = CFDictionaryGetValue(iDict, kSCPropNetIPv4DestAddresses); + *addrs = isA_CFArray(CFDictionaryGetValue(iDict, + kSCPropNetIPv4Addresses)); + *masks = isA_CFArray(CFDictionaryGetValue(iDict, + kSCPropNetIPv4SubnetMasks)); + *dests = isA_CFArray(CFDictionaryGetValue(iDict, + kSCPropNetIPv4DestAddresses)); if ((*addrs == NULL) || ((*nAddrs = CFArrayGetCount(*addrs)) == 0)) { /* sorry, no addresses */ + _SCErrorSet(kSCStatusReachabilityUnknown); return FALSE; } - if ((*masks && *dests) || - (*masks == NULL) && (*dests == NULL)) { + if (((*masks == NULL) && (*dests == NULL)) || + ((*masks != NULL) && (*dests != NULL))) { /* * sorry, we expect to have "SubnetMasks" or - * "DestAddresses" (not both) and if the count + * "DestAddresses" (not both) and the count * must match the number of "Addresses". */ + _SCErrorSet(kSCStatusReachabilityUnknown); return FALSE; } if (*masks && (*nAddrs != CFArrayGetCount(*masks))) { /* if we don't like the netmasks */ + _SCErrorSet(kSCStatusReachabilityUnknown); return FALSE; } if (*dests && (*nAddrs != CFArrayGetCount(*dests))) { /* if we don't like the destaddresses */ + _SCErrorSet(kSCStatusReachabilityUnknown); return FALSE; } return TRUE; } -static SCNStatus -checkAddress(SCDSessionRef session, +static Boolean +checkAddress(SCDynamicStoreRef store, const struct sockaddr *address, const int addrlen, - CFDictionaryRef services, - CFDictionaryRef interfaces, - CFArrayRef interfaceOrder, + CFDictionaryRef config, + CFDictionaryRef active, + CFArrayRef serviceOrder, struct in_addr *defaultRoute, - int *flags, - const char **errorMessage) + SCNetworkConnectionFlags *flags) { + CFIndex aCnt; + CFStringRef aType = NULL; + CFDictionaryRef cDict = NULL; CFIndex i; - struct ifreq ifr; - CFIndex iCnt; - CFStringRef iKey = NULL; - CFStringRef iType = NULL; - void **keys; + CFStringRef key = NULL; int pppRef = -1; - SCNStatus scn_status = SCN_REACHABLE_UNKNOWN; - CFIndex sCnt; - CFMutableArrayRef sKeys = NULL; - CFStringRef sID = NULL; - CFArrayRef sIDs = NULL; - CFArrayRef sList = NULL; - int sock = -1; - CFStringRef sKey = NULL; - CFDictionaryRef sDict = NULL; - CFArrayRef tKeys; - - if (flags != NULL) { - *flags = 0; - } + int sc_status = kSCStatusReachabilityUnknown; + char *statusMessage = NULL; - if (address == NULL) { - return SCN_REACHABLE_NO; + if (!address || !flags) { + sc_status = kSCStatusInvalidArgument; + goto done; } - sCnt = CFDictionaryGetCount(services); - keys = CFAllocatorAllocate(NULL, sCnt * sizeof(CFStringRef), 0); - CFDictionaryGetKeysAndValues(services, keys, NULL); - tKeys = CFArrayCreate(NULL, keys, sCnt, &kCFTypeArrayCallBacks); - CFAllocatorDeallocate(NULL, keys); - sKeys = CFArrayCreateMutableCopy(NULL, 0, tKeys); - CFRelease(tKeys); + *flags = 0; if (address->sa_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *)address; -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR("checkAddress(%s)"), inet_ntoa(sin->sin_addr)); -#endif /* DEBUG */ - /* - * Check for loopback address - */ - if (ntohl(sin->sin_addr.s_addr) == ntohl(INADDR_LOOPBACK)) { - /* if asking about the loopback address */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" isReachable via loopback")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_YES; - goto done; - } + SCLog(_sc_debug, LOG_INFO, CFSTR("checkAddress(%s)"), inet_ntoa(sin->sin_addr)); /* * Check if the address is on one of the subnets * associated with our active IPv4 interfaces */ - iCnt = CFArrayGetCount(interfaceOrder); - for (i=0; isin_addr.s_addr) & ntohl(ifMask.s_addr))) { /* the requested address is on this subnet */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" isReachable (my subnet)")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_YES; + statusMessage = "isReachable (my subnet)"; + *flags |= kSCNetworkFlagsReachable; goto checkInterface; } } else { @@ -526,21 +584,15 @@ checkAddress(SCDSessionRef session, /* check local address */ if (ntohl(sin->sin_addr.s_addr) == ntohl(ifAddr.s_addr)) { /* the address is our side of the link */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" isReachable (my local address)")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_YES; + statusMessage = "isReachable (my local address)"; + *flags |= kSCNetworkFlagsReachable; goto checkInterface; } if (ntohl(sin->sin_addr.s_addr) == ntohl(destAddr.s_addr)) { /* the address is the other side of the link */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" isReachable (my remote address)")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_YES; + statusMessage = "isReachable (my remote address)"; + *flags |= kSCNetworkFlagsReachable; goto checkInterface; } } @@ -550,18 +602,21 @@ checkAddress(SCDSessionRef session, /* * Check if the address is accessible via the "default" route. */ - for (i=0; isin_addr.s_addr || + !defaultRoute || + !aDict || + !getAddresses(aDict, &nAddrs, &addrs, &masks, &dests)) { /* if no addresses to check */ continue; } @@ -586,11 +641,8 @@ checkAddress(SCDSessionRef session, if ((ntohl(ifAddr.s_addr) & ntohl(ifMask.s_addr)) == (ntohl(defaultRoute->s_addr) & ntohl(ifMask.s_addr))) { /* the requested address is on this subnet */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" isReachable via default route (my subnet)")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_YES; + statusMessage = "isReachable via default route (my subnet)"; + *flags |= kSCNetworkFlagsReachable; goto checkInterface; } } else { @@ -605,11 +657,8 @@ checkAddress(SCDSessionRef session, if (ntohl(destAddr.s_addr) == ntohl(defaultRoute->s_addr)) { /* the address is the other side of the link */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" isReachable via default route (my remote address)")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_YES; + statusMessage = "isReachable via default route (my remote address)"; + *flags |= kSCNetworkFlagsReachable; goto checkInterface; } } @@ -619,115 +668,58 @@ checkAddress(SCDSessionRef session, /* * Check the not active (but configured) IPv4 services */ - sCnt = CFArrayGetCount(sKeys); - for (i=0; isin_addr.s_addr) & ntohl(ifMask.s_addr))) { - /* the requested address is on this subnet */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" is configured w/static info (my subnet)")); -#endif /* DEBUG */ - goto checkService; - } - } else { - struct in_addr destAddr; + aType = CFDictionaryGetValue(cDict, kSCPropNetInterfaceType); + if (!aType || !CFEqual(aType, kSCValNetInterfaceTypePPP)) { + /* if we can't get a connection on this service */ + sc_status = kSCStatusOK; + goto done; + } - /* check remote address */ - if (inet_atonCF(CFArrayGetValueAtIndex(dests, j), - &destAddr) == 0) { - /* if DestAddresses string is invalid */ - break; - } + statusMessage = "is configured w/dynamic addressing"; + *flags |= kSCNetworkFlagsTransientConnection; + *flags |= kSCNetworkFlagsReachable; + *flags |= kSCNetworkFlagsConnectionRequired; - /* check local address */ - if (ntohl(sin->sin_addr.s_addr) == ntohl(ifAddr.s_addr)) { - /* the address is our side of the link */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" is configured w/static info (my local address)")); -#endif /* DEBUG */ - goto checkService; - } - - if (ntohl(sin->sin_addr.s_addr) == ntohl(destAddr.s_addr)) { - /* the address is the other side of the link */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" is configured w/static info (my remote address)")); -#endif /* DEBUG */ - goto checkService; - } - } + if (_sc_debug) { + SCLog(TRUE, LOG_INFO, CFSTR(" status = %s"), statusMessage); + SCLog(TRUE, LOG_INFO, CFSTR(" service id = %@"), key); } - /* - * check for dynamic (i.e. not manual) configuration - * method. - */ - if (CFDictionaryGetValueIfPresent(sDict, - kSCPropNetIPv4ConfigMethod, - (void **)&configMethod) && - !CFEqual(configMethod, kSCValNetIPv4ConfigMethodManual)) { - /* if only we were "connected" */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" is configured w/dynamic addressing")); -#endif /* DEBUG */ - goto checkService; - } + sc_status = kSCStatusOK; + goto done; } -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" cannot be reached")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_NO; + SCLog(_sc_debug, LOG_INFO, CFSTR(" cannot be reached")); + sc_status = kSCStatusOK; goto done; } else { /* * if no code for this address family (yet) */ - SCDSessionLog(session, - LOG_ERR, - CFSTR("checkAddress(): unexpected address family %d"), - address->sa_family); - if (errorMessage != NULL) { - *errorMessage = "unexpected address family"; - } + SCLog(_sc_verbose, LOG_ERR, + CFSTR("checkAddress(): unexpected address family %d"), + address->sa_family); + sc_status = kSCStatusInvalidArgument; goto done; } @@ -735,52 +727,61 @@ checkAddress(SCDSessionRef session, checkInterface : + if (_sc_debug) { + CFDictionaryRef aDict; + CFStringRef interface = NULL; + + /* attempt to get the interface type from the config info */ + aDict = CFDictionaryGetValue(active, key); + if (aDict) { + interface = CFDictionaryGetValue(aDict, kSCPropInterfaceName); + } + + SCLog(TRUE, LOG_INFO, CFSTR(" status = %s"), statusMessage); + SCLog(TRUE, LOG_INFO, CFSTR(" service id = %@"), key); + SCLog(TRUE, LOG_INFO, CFSTR(" device = %@"), interface ? interface : CFSTR("?")); + } + + sc_status = kSCStatusOK; + /* * We have an interface which "claims" to be a valid path * off of the system. Check to make sure that this isn't * a dial-on-demand PPP link that isn't connected yet. */ - if (sIDs) { + { CFNumberRef num; - CFDictionaryRef sDict; - - /* attempt to get the interface type from the first service */ - sID = CFArrayGetValueAtIndex(sIDs, 0); - sDict = CFDictionaryGetValue(services, sID); - if (sDict) { - iType = CFDictionaryGetValue(sDict, kSCPropNetInterfaceType); - } + CFDictionaryRef cDict; - if (!iType) { - /* if we don't know the interface type */ - goto done; + /* attempt to get the interface type from the config info */ + cDict = CFDictionaryGetValue(config, key); + if (cDict) { + aType = CFDictionaryGetValue(cDict, kSCPropNetInterfaceType); } - if (!CFEqual(iType, kSCValNetInterfaceTypePPP)) { - /* if not a ppp interface */ + if (!aType || !CFEqual(aType, kSCValNetInterfaceTypePPP)) { + /* + * if we don't know the interface type or if + * it is not a ppp interface + */ goto done; } - num = CFDictionaryGetValue(sDict, kSCPropNetPPPDialOnDemand); + num = CFDictionaryGetValue(cDict, kSCPropNetPPPDialOnDemand); if (num) { int dialOnDemand; - CFNumberGetValue(num, kCFNumberIntType, &dialOnDemand); - if (flags && (dialOnDemand != 0)) { - *flags |= kSCNFlagsConnectionAutomatic; + CFNumberGetValue(num, kCFNumberIntType, &dialOnDemand); + if (dialOnDemand != 0) { + *flags |= kSCNetworkFlagsConnectionAutomatic; } - + } - } else if (!CFStringHasPrefix(iKey, CFSTR("ppp"))) { - /* if not a ppp interface */ - goto done; } - if (flags != NULL) { - *flags |= kSCNFlagsTransientConnection; - } + *flags |= kSCNetworkFlagsTransientConnection; - if (sID) { + { u_int32_t pppLink; struct ppp_status *pppLinkStatus; int pppStatus; @@ -791,45 +792,26 @@ checkAddress(SCDSessionRef session, */ pppStatus = PPPInit(&pppRef); if (pppStatus != 0) { -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_DEBUG, CFSTR(" PPPInit() failed: status=%d"), pppStatus); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_UNKNOWN; - if (errorMessage != NULL) { - *errorMessage = "PPPInit() failed"; - } + SCLog(_sc_debug, LOG_DEBUG, CFSTR(" PPPInit() failed: status=%d"), pppStatus); + sc_status = kSCStatusReachabilityUnknown; goto done; } - pppStatus = PPPGetLinkByServiceID(pppRef, sID, &pppLink); + pppStatus = PPPGetLinkByServiceID(pppRef, key, &pppLink); if (pppStatus != 0) { -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_DEBUG, CFSTR(" PPPGetLinkByServiceID() failed: status=%d"), pppStatus); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_UNKNOWN; - if (errorMessage != NULL) { - *errorMessage = "PPPGetLinkByServiceID() failed"; - } + SCLog(_sc_debug, LOG_DEBUG, CFSTR(" PPPGetLinkByServiceID() failed: status=%d"), pppStatus); + sc_status = kSCStatusReachabilityUnknown; goto done; } pppStatus = PPPStatus(pppRef, pppLink, &pppLinkStatus); if (pppStatus != 0) { -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_DEBUG, CFSTR(" PPPStatus() failed: status=%d"), pppStatus); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_UNKNOWN; - if (errorMessage != NULL) { - *errorMessage = "PPPStatus() failed"; - } + SCLog(_sc_debug, LOG_DEBUG, CFSTR(" PPPStatus() failed: status=%d"), pppStatus); + sc_status = kSCStatusReachabilityUnknown; goto done; } #ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_DEBUG, CFSTR(" PPP link status = %d"), pppLinkStatus->status); + SCLog(_sc_debug, LOG_DEBUG, CFSTR(" PPP link status = %d"), pppLinkStatus->status); #endif /* DEBUG */ switch (pppLinkStatus->status) { case PPP_RUNNING : @@ -837,389 +819,460 @@ checkAddress(SCDSessionRef session, break; case PPP_IDLE : /* if we're not connected at all */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" PPP link idle, dial-on-traffic to connect")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_CONNECTION_REQUIRED; + SCLog(_sc_debug, LOG_INFO, CFSTR(" PPP link idle, dial-on-traffic to connect")); + *flags |= kSCNetworkFlagsReachable; + *flags |= kSCNetworkFlagsConnectionRequired; + sc_status = kSCStatusOK; break; default : /* if we're in the process of [dis]connecting */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" PPP link, connection in progress")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_CONNECTION_REQUIRED; + SCLog(_sc_debug, LOG_INFO, CFSTR(" PPP link, connection in progress")); + *flags |= kSCNetworkFlagsReachable; + *flags |= kSCNetworkFlagsConnectionRequired; + sc_status = kSCStatusOK; break; } CFAllocatorDeallocate(NULL, pppLinkStatus); - } else { - /* - * The service ID is not available, check the interfaces - * UP and RUNNING flags. - */ - bzero(&ifr, sizeof(ifr)); - if (!CFStringGetCString(iKey, - (char *)&ifr.ifr_name, - sizeof(ifr.ifr_name), - kCFStringEncodingMacRoman)) { - scn_status = SCN_REACHABLE_UNKNOWN; - if (errorMessage != NULL) { - *errorMessage = "could not convert interface name to C string"; - } - goto done; - } - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) { - scn_status = SCN_REACHABLE_UNKNOWN; - if (errorMessage != NULL) { - *errorMessage = strerror(errno); - } - goto done; - } - - if (ioctl(sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { - scn_status = SCN_REACHABLE_UNKNOWN; - if (errorMessage != NULL) { - *errorMessage = strerror(errno); - } - goto done; - } - -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" flags for %s == 0x%hx"), ifr.ifr_name, ifr.ifr_flags); -#endif /* DEBUG */ - if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - if ((ifr.ifr_flags & IFF_UP) == IFF_UP) { - /* if we're "up" but not "running" */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" up & not running, dial-on-traffic to connect")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_CONNECTION_REQUIRED; - if (flags != NULL) { - *flags |= kSCNFlagsConnectionAutomatic; - } - } else { - /* if we're not "up" and "running" */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" not up & running, connection required")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_CONNECTION_REQUIRED; - } - goto done; - } } goto done; - checkService : - - /* - * We have a service which "claims" to be a potential path - * off of the system. Check to make sure that this is a - * type of PPP link before claiming it's viable. - */ - if (sDict && - CFDictionaryGetValueIfPresent(sDict, - kSCPropNetInterfaceType, - (void **)&iType) && - !CFEqual(iType, kSCValNetInterfaceTypePPP)) { - /* no path if this not a ppp interface */ -#ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR(" cannot be reached")); -#endif /* DEBUG */ - scn_status = SCN_REACHABLE_NO; - goto done; - } - - scn_status = SCN_REACHABLE_CONNECTION_REQUIRED; - if (flags != NULL) { - *flags |= kSCNFlagsTransientConnection; - } - done : - if (sKeys) CFRelease(sKeys); - if (sList) CFRelease(sList); if (pppRef != -1) (void) PPPDispose(pppRef); - if (sock != -1) (void)close(sock); - return scn_status; + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; + } + + return TRUE; } static void -_IsReachableInit(SCDSessionRef session, - CFDictionaryRef *services, - CFDictionaryRef *interfaces, - CFArrayRef *interfaceOrder, - struct in_addr **defaultRoute) +_CheckReachabilityInit(SCDynamicStoreRef store, + CFDictionaryRef *config, + CFDictionaryRef *active, + CFArrayRef *serviceOrder, + struct in_addr **defaultRoute) { - CFStringRef addr; - CFDictionaryRef dict; - CFStringRef key; - SCDHandleRef handle; - CFNumberRef pppOverridePrimary = NULL; - CFArrayRef serviceOrder = NULL; - struct in_addr *route = NULL; - SCDStatus status; + CFMutableDictionaryRef activeDict; + CFMutableDictionaryRef configDict; + initContext context; + CFDictionaryRef dict; + CFMutableDictionaryRef interfaces; + CFMutableArrayRef keys; + CFMutableArrayRef orderArray; + CFDictionaryRef orderDict; + CFStringRef orderKey; + CFStringRef pattern; + CFMutableArrayRef patterns; + CFStringRef routeKey; + CFDictionaryRef routeDict; + + configDict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + *config = configDict; + + activeDict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + *active = activeDict; + + orderArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + *serviceOrder = orderArray; + + *defaultRoute = NULL; + + interfaces = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); /* - * get the ServiceOrder and PPPOverridePrimary keys - * from the global settings. + * collect information on the configured services and their + * associated interface type. */ - key = SCDKeyCreateNetworkGlobalEntity(kSCCacheDomainSetup, kSCEntNetIPv4); - status = SCDGet(session, key, &handle); - CFRelease(key); - switch (status) { - case SCD_OK : - /* if global settings are available */ - dict = SCDHandleGetData(handle); - - /* get service order */ - if ((CFDictionaryGetValueIfPresent(dict, - kSCPropNetServiceOrder, - (void **)&serviceOrder) == TRUE)) { - CFRetain(serviceOrder); - } + keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - /* get PPP overrides primary flag */ - if ((CFDictionaryGetValueIfPresent(dict, - kSCPropNetPPPOverridePrimary, - (void **)&pppOverridePrimary) == TRUE)) { - CFRetain(pppOverridePrimary); - } + /* + * Setup:/Network/Global/IPv4 (for the ServiceOrder) + */ + orderKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, + kSCDynamicStoreDomainSetup, + kSCEntNetIPv4); + CFArrayAppendValue(keys, orderKey); - SCDHandleRelease(handle); - break; - case SCD_NOKEY : - /* if no global settings */ - break; - default : - SCDLog(LOG_ERR, CFSTR("SCDGet() failed: %s"), SCDError(status)); - /* XXX need to do something more with this FATAL error XXXX */ - goto error; + /* + * State:/Network/Global/IPv4 (for the DefaultRoute) + */ + routeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, + kSCDynamicStoreDomainState, + kSCEntNetIPv4); + CFArrayAppendValue(keys, routeKey); + + /* Setup: per-service IPv4 info */ + pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + kSCCompAnyRegex, + kSCEntNetIPv4); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + + /* Setup: per-service Interface info */ + pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + kSCCompAnyRegex, + kSCEntNetInterface); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + + /* Setup: per-service PPP info */ + pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + kSCCompAnyRegex, + kSCEntNetPPP); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + + /* State: per-service IPv4 info */ + pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainState, + kSCCompAnyRegex, + kSCEntNetIPv4); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + + /* State: per-interface IPv4 info */ + pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, + kSCDynamicStoreDomainState, + kSCCompAnyRegex, + kSCEntNetIPv4); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + + /* fetch the configuration information */ + dict = SCDynamicStoreCopyMultiple(store, keys, patterns); + CFRelease(keys); + CFRelease(patterns); + if (!dict) { + goto done; } /* - * Get default route + * get the ServiceOrder key from the global settings. */ - key = SCDKeyCreateNetworkGlobalEntity(kSCCacheDomainState, - kSCEntNetIPv4); - status = SCDGet(session, key, &handle); - CFRelease(key); - switch (status) { - case SCD_OK : - dict = SCDHandleGetData(handle); - addr = CFDictionaryGetValue(dict, kSCPropNetIPv4Router); - if (addr == NULL) { - /* if no default route */ - break; - } + orderDict = CFDictionaryGetValue(dict, orderKey); + if (isA_CFDictionary(orderDict)) { + CFArrayRef array; + + /* global settings are available */ + array = (CFMutableArrayRef)CFDictionaryGetValue(orderDict, kSCPropNetServiceOrder); + if (isA_CFArray(array)) { + CFArrayAppendArray(orderArray, + array, + CFRangeMake(0, CFArrayGetCount(array))); + } + } + + /* + * get the DefaultRoute + */ + routeDict = CFDictionaryGetValue(dict, routeKey); + if (isA_CFDictionary(routeDict)) { + CFStringRef addr; + + /* global state is available, get default route */ + addr = CFDictionaryGetValue(routeDict, kSCPropNetIPv4Router); + if (isA_CFString(addr)) { + struct in_addr *route; route = CFAllocatorAllocate(NULL, sizeof(struct in_addr), 0); if (inet_atonCF(addr, route) == 0) { /* if address string is invalid */ CFAllocatorDeallocate(NULL, route); route = NULL; - break; + } else { + *defaultRoute = route; } - *defaultRoute = route; - - break; - case SCD_NOKEY : - /* if no default route */ - break; - default : - SCDSessionLog(session, - LOG_ERR, - CFSTR("SCDGet() failed: %s"), - SCDError(status)); - goto error; - } - if (handle) { - SCDHandleRelease(handle); - handle = NULL; + } } /* - * get the configured services and interfaces + * collect the configured services, the active services, and + * the active interfaces. */ - *services = getServices (session); - *interfaces = getInterfaces(session); - *interfaceOrder = getInterfaceOrder(*interfaces, - serviceOrder, - pppOverridePrimary); + context.cDict = configDict; + context.cPrefix = SCDynamicStoreKeyCreate(NULL, + CFSTR("%@/%@/%@/"), + kSCDynamicStoreDomainSetup, + kSCCompNetwork, + kSCCompService); + context.aDict = activeDict; + context.aPrefix = SCDynamicStoreKeyCreate(NULL, + CFSTR("%@/%@/%@/"), + kSCDynamicStoreDomainState, + kSCCompNetwork, + kSCCompService); + context.iDict = interfaces; + context.iPrefix = SCDynamicStoreKeyCreate(NULL, + CFSTR("%@/%@/%@/"), + kSCDynamicStoreDomainState, + kSCCompNetwork, + kSCCompInterface); + context.order = orderArray; + + CFDictionaryApplyFunction(dict, collectInfo, &context); - error : + /* + * add additional information for the configured services + */ + CFDictionaryApplyFunction(dict, collectExtraInfo, &context); - if (serviceOrder) CFRelease(serviceOrder); - if (pppOverridePrimary) CFRelease(pppOverridePrimary); + /* + * remove any addresses associated with known services + */ + CFDictionaryApplyFunction(activeDict, removeKnownAddresses, interfaces); + + /* + * create new services for any remaining addresses + */ + CFDictionaryApplyFunction(interfaces, addUnknownService, &context); + + CFRelease(context.cPrefix); + CFRelease(context.aPrefix); + CFRelease(context.iPrefix); + CFRelease(dict); + + done : + + CFRelease(interfaces); + CFRelease(orderKey); + CFRelease(routeKey); #ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) { - SCDLog(LOG_NOTICE, CFSTR("interfaces = %@"), *interfaces); - SCDLog(LOG_NOTICE, CFSTR("services = %@"), *services); - SCDLog(LOG_NOTICE, CFSTR("interfaceOrder = %@"), *interfaceOrder); - SCDLog(LOG_NOTICE, CFSTR("defaultRoute = %s"), *defaultRoute?inet_ntoa(**defaultRoute):"None"); - } + SCLog(_sc_debug, LOG_NOTICE, CFSTR("config = %@"), *config); + SCLog(_sc_debug, LOG_NOTICE, CFSTR("active = %@"), *active); + SCLog(_sc_debug, LOG_NOTICE, CFSTR("serviceOrder = %@"), *serviceOrder); + SCLog(_sc_debug, LOG_NOTICE, CFSTR("defaultRoute = %s"), *defaultRoute?inet_ntoa(**defaultRoute):"None"); #endif /* DEBUG */ return; - } static void -_IsReachableFree(CFDictionaryRef services, - CFDictionaryRef interfaces, - CFArrayRef interfaceOrder, - struct in_addr *defaultRoute) +_CheckReachabilityFree(CFDictionaryRef config, + CFDictionaryRef active, + CFArrayRef serviceOrder, + struct in_addr *defaultRoute) { - if (services) CFRelease(services); - if (interfaces) CFRelease(interfaces); - if (interfaceOrder) CFRelease(interfaceOrder); + if (config) CFRelease(config); + if (active) CFRelease(active); + if (serviceOrder) CFRelease(serviceOrder); if (defaultRoute) CFAllocatorDeallocate(NULL, defaultRoute); return; } -SCNStatus -SCNIsReachableByAddress(const struct sockaddr *address, - const int addrlen, - int *flags, - const char **errorMessage) +Boolean +SCNetworkCheckReachabilityByAddress(const struct sockaddr *address, + const int addrlen, + SCNetworkConnectionFlags *flags) { - struct in_addr *defaultRoute = NULL; - CFDictionaryRef interfaces = NULL; - CFArrayRef interfaceOrder = NULL; - CFDictionaryRef services = NULL; - SCDSessionRef session = NULL; - SCDStatus scd_status; - SCNStatus scn_status; - - scd_status = SCDOpen(&session, CFSTR("SCNIsReachableByAddress")); - if (scd_status != SCD_OK) { - if (errorMessage != NULL) { - *errorMessage = SCDError(scd_status); + CFDictionaryRef active = NULL; + CFDictionaryRef config = NULL; + struct in_addr *defaultRoute = NULL; + Boolean ok; + CFArrayRef serviceOrder = NULL; + SCDynamicStoreRef store = NULL; + + *flags = 0; + + /* + * Check if 0.0.0.0 + */ + if (address->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)address; + + if (sin->sin_addr.s_addr == 0) { + SCLog(_sc_debug, LOG_INFO, CFSTR("checkAddress(0.0.0.0)")); + SCLog(_sc_debug, LOG_INFO, CFSTR(" status = isReachable (this host)")); + *flags |= kSCNetworkFlagsReachable; + return TRUE; } - return SCN_REACHABLE_UNKNOWN; } - _IsReachableInit(session, &services, &interfaces, &interfaceOrder, &defaultRoute); - scn_status = checkAddress(session, - address, - addrlen, - services, - interfaces, - interfaceOrder, - defaultRoute, - flags, - errorMessage); - _IsReachableFree(services, interfaces, interfaceOrder, defaultRoute); + store = SCDynamicStoreCreate(NULL, + CFSTR("SCNetworkCheckReachabilityByAddress"), + NULL, + NULL); + if (!store) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + return FALSE; + } - (void) SCDClose(&session); - return scn_status; + _CheckReachabilityInit(store, &config, &active, &serviceOrder, &defaultRoute); + ok = checkAddress(store, + address, + addrlen, + config, + active, + serviceOrder, + defaultRoute, + flags); + _CheckReachabilityFree(config, active, serviceOrder, defaultRoute); + + CFRelease(store); + return ok; } -SCNStatus -SCNIsReachableByName(const char *nodename, - int *flags, - const char **errorMessage) +/* + * rankReachability() + * Not reachable == 0 + * Connection Required == 1 + * Reachable == 2 + */ +static int +rankReachability(int flags) { - struct in_addr *defaultRoute = NULL; - struct hostent *h; - int i; - CFDictionaryRef interfaces = NULL; - CFArrayRef interfaceOrder = NULL; - SCDStatus scd_status = SCD_OK; - SCNStatus ns_status = SCN_REACHABLE_YES; - struct addrinfo *res = NULL; - struct addrinfo *resP; - CFDictionaryRef services = NULL; - SCDSessionRef session = NULL; - SCNStatus scn_status = SCN_REACHABLE_YES; - - scd_status = SCDOpen(&session, CFSTR("SCNIsReachableByName")); - if (scd_status != SCD_OK) { - scn_status = SCN_REACHABLE_UNKNOWN; - if (errorMessage != NULL) { - *errorMessage = SCDError(scd_status); - } - goto done; + int rank = 0; + + if (flags & kSCNetworkFlagsReachable) rank = 2; + if (flags & kSCNetworkFlagsConnectionRequired) rank = 1; + return rank; +} + + +Boolean +SCNetworkCheckReachabilityByName(const char *nodename, + SCNetworkConnectionFlags *flags) +{ + CFDictionaryRef active = NULL; + CFDictionaryRef config = NULL; + struct in_addr *defaultRoute = NULL; + struct hostent *h; + Boolean haveDNS = FALSE; + int i; + Boolean ok = TRUE; + struct addrinfo *res = NULL; + struct addrinfo *resP; + CFArrayRef serviceOrder = NULL; + SCDynamicStoreRef store = NULL; + + store = SCDynamicStoreCreate(NULL, + CFSTR("SCNetworkCheckReachabilityByName"), + NULL, + NULL); + if (!store) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + return FALSE; } - _IsReachableInit(session, &services, &interfaces, &interfaceOrder, &defaultRoute); + _CheckReachabilityInit(store, &config, &active, &serviceOrder, &defaultRoute); /* - * since we don't know which name server will be consulted - * to resolve the specified nodename we need to check the - * availability of ALL name servers. + * We first assume that all of the configured DNS servers + * are available. Since we don't know which name server will + * be consulted to resolve the specified nodename we need to + * check the availability of ALL name servers. We can only + * proceed if we know that our query can be answered. */ + + *flags = kSCNetworkFlagsReachable; + res_init(); for (i=0; i<_res.nscount; i++) { - ns_status = checkAddress(session, - (struct sockaddr *)&_res.nsaddr_list[i], - _res.nsaddr_list[i].sin_len, - services, - interfaces, - interfaceOrder, - defaultRoute, - flags, - errorMessage); - if (ns_status < scn_status) { + SCNetworkConnectionFlags ns_flags = 0; + + if (_res.nsaddr_list[i].sin_addr.s_addr == 0) { + continue; + } + + haveDNS = TRUE; + + if (_res.nsaddr_list[i].sin_len == 0) { + _res.nsaddr_list[i].sin_len = sizeof(_res.nsaddr_list[i]); + } + + ok = checkAddress(store, + (struct sockaddr *)&_res.nsaddr_list[i], + _res.nsaddr_list[i].sin_len, + config, + active, + serviceOrder, + defaultRoute, + &ns_flags); + if (!ok) { + /* not today */ + break; + } + if (rankReachability(ns_flags) < rankReachability(*flags)) { /* return the worst case result */ - scn_status = ns_status; - if (ns_status == SCN_REACHABLE_UNKNOWN) { - /* not today */ - break; - } + *flags = ns_flags; } } - if (ns_status < SCN_REACHABLE_YES) { + if (!ok || (rankReachability(*flags) < 2)) { goto done; } + SCLog(_sc_debug, LOG_INFO, CFSTR("check DNS for \"%s\""), nodename); + /* * OK, all of the DNS name servers are available. Let's * first assume that the requested host is NOT available, * resolve the nodename, and check its address for * accessibility. We return the best status available. */ - scn_status = SCN_REACHABLE_UNKNOWN; + *flags = 0; /* * resolve the nodename into an address */ i = getaddrinfo(nodename, NULL, NULL, &res); if (i != 0) { - SCDSessionLog(session, - LOG_ERR, - CFSTR("getaddrinfo() failed: %s"), - gai_strerror(i)); + SCLog(_sc_verbose, LOG_ERR, + CFSTR("getaddrinfo() failed: %s"), + gai_strerror(i)); goto done; } for (resP=res; resP!=NULL; resP=resP->ai_next) { - ns_status = checkAddress(session, - resP->ai_addr, - resP->ai_addrlen, - services, - interfaces, - interfaceOrder, - defaultRoute, - flags, - errorMessage); - if (ns_status > scn_status) { + SCNetworkConnectionFlags ns_flags = 0; + + if (resP->ai_addr->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)resP->ai_addr; + + if (sin->sin_addr.s_addr == 0) { + SCLog(_sc_debug, LOG_INFO, CFSTR("checkAddress(0.0.0.0)")); + SCLog(_sc_debug, LOG_INFO, CFSTR(" status = isReachable (this host)")); + *flags |= kSCNetworkFlagsReachable; + break; + } + } + + ok = checkAddress(store, + resP->ai_addr, + resP->ai_addrlen, + config, + active, + serviceOrder, + defaultRoute, + &ns_flags); + if (!ok) { + /* not today */ + break; + } + if (rankReachability(ns_flags) > rankReachability(*flags)) { /* return the best case result */ - scn_status = ns_status; - if (ns_status == SCN_REACHABLE_YES) { + *flags = ns_flags; + if (rankReachability(*flags) == 2) { /* we're in luck */ break; } @@ -1240,35 +1293,47 @@ SCNIsReachableByName(const char *nodename, */ #ifdef DEBUG - if (SCDOptionGet(session, kSCDOptionDebug)) - SCDLog(LOG_INFO, CFSTR("getaddrinfo() returned no addresses, try gethostbyname()")); + SCLog(_sc_debug, + LOG_INFO, + CFSTR("getaddrinfo() returned no addresses, try gethostbyname()")); #endif /* DEBUG */ h = gethostbyname(nodename); if (h && h->h_length) { struct in_addr **s = (struct in_addr **)h->h_addr_list; - while (*s) { - struct sockaddr_in sa; + while (*s) { + SCNetworkConnectionFlags ns_flags = 0; + struct sockaddr_in sa; bzero(&sa, sizeof(sa)); sa.sin_len = sizeof(sa); sa.sin_family = AF_INET; sa.sin_addr = **s; - ns_status = checkAddress(session, - (struct sockaddr *)&sa, - sizeof(sa), - services, - interfaces, - interfaceOrder, - defaultRoute, - flags, - errorMessage); - if (ns_status > scn_status) { + if (sa.sin_addr.s_addr == 0) { + SCLog(_sc_debug, LOG_INFO, CFSTR("checkAddress(0.0.0.0)")); + SCLog(_sc_debug, LOG_INFO, CFSTR(" status = isReachable (this host)")); + *flags |= kSCNetworkFlagsReachable; + break; + } + + ok = checkAddress(store, + (struct sockaddr *)&sa, + sizeof(sa), + config, + active, + serviceOrder, + defaultRoute, + &ns_flags); + if (!ok) { + /* not today */ + break; + } + if (rankReachability(ns_flags) > rankReachability(*flags)) { /* return the best case result */ - scn_status = ns_status; - if (ns_status == SCN_REACHABLE_YES) { + *flags = ns_flags; + if (rankReachability(*flags) == 2) { /* we're in luck */ break; } @@ -1276,13 +1341,69 @@ SCNIsReachableByName(const char *nodename, s++; } + } else { + char *msg; + + switch(h_errno) { + case NETDB_INTERNAL : + msg = strerror(errno); + break; + case HOST_NOT_FOUND : + msg = "Host not found."; + if (!haveDNS) { + /* + * No DNS servers are defined. Set flags based on + * the availability of configured (but not active) + * services. + */ + struct sockaddr_in sa; + + bzero(&sa, sizeof(sa)); + sa.sin_len = sizeof(sa); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = 0; + ok = checkAddress(store, + (struct sockaddr *)&sa, + sizeof(sa), + config, + active, + serviceOrder, + defaultRoute, + flags); + if (ok && + (*flags & kSCNetworkFlagsReachable) && + (*flags & kSCNetworkFlagsConnectionRequired)) { + /* + * We might pick up a set of DNS servers + * from this connection, don't reply with + * "Host not found." just yet. + */ + goto done; + } + *flags = 0; + } + break; + case TRY_AGAIN : + msg = "Try again."; + break; + case NO_RECOVERY : + msg = "No recovery."; + break; + case NO_DATA : + msg = "No data available."; + break; + default : + msg = "Unknown"; + break; + } + SCLog(_sc_debug, LOG_INFO, CFSTR("gethostbyname() failed: %s"), msg); } done : - _IsReachableFree(services, interfaces, interfaceOrder, defaultRoute); - if (session) (void)SCDClose(&session); + _CheckReachabilityFree(config, active, serviceOrder, defaultRoute); + if (store) CFRelease(store); if (res) freeaddrinfo(res); - return scn_status; + return ok; } diff --git a/SystemConfiguration.fproj/SCNetwork.h b/SystemConfiguration.fproj/SCNetwork.h index 2f22ca1..c48e342 100644 --- a/SystemConfiguration.fproj/SCNetwork.h +++ b/SystemConfiguration.fproj/SCNetwork.h @@ -20,145 +20,125 @@ * @APPLE_LICENSE_HEADER_END@ */ -#ifndef _SCPNETWORK_H -#define _SCPNETWORK_H +#ifndef _SCNETWORK_H +#define _SCNETWORK_H #include +#include #include +#include + /*! - @header SCPNetwork.h - The SystemConfiguration framework provides access to the data used - to configure a running system. + @header SCNetwork + The SCNetworkCheckReachabilityXXX() APIs allow an application to + determine the status of the system's current network configuration. + + The term "reachable" reflects whether a data packet, sent by + an application into the network stack, will be able to reach + the destination host. - Specifically, the SCPNetworkXXX() API's allow an application - to determine the status of the systems current network - configuration. + Please note that being able to reach the destination host + does not guarantee that the data packet will reach the + host. The APIs provided by this framework communicate with the "configd" - daemon to obtain information regarding the systems current - configuration. + daemon to obtain information regarding the system's current + configuration. */ /*! - @enum SCNStatus - @discussion Returned status codes from the SCNIsReachableByAddress() - and SCNIsReachableByName() functions. - - The term "reachable" in these status codes reflects whether - a data packet, sent by an application into the network stack, - will be able to reach the destination host. - - Please not that being "able" to reach the destination host - does not guarantee that the data packet "will" reach the - host. - - @constant SCN_REACHABLE_UNKNOWN - A determination could not be made regarding the reachability - of the specified nodename/address. - - @constant SCN_REACHABLE_NO - The specified nodename/address can not be reached using the - current network configuration. - - @constant SCN_REACHABLE_CONNECTION_REQUIRED - The specified nodename/address can be reached using the - current network configuration but a connection must first - be established. - - This status would be returned for a dialup connection which - was not currently active but could handle network traffic for - the target system. - - @constant SCN_REACHABLE_YES - The specified nodename/address can be reached using the - current network configuration. - */ -typedef enum { - SCN_REACHABLE_UNKNOWN = -1, - SCN_REACHABLE_NO = 0, - SCN_REACHABLE_CONNECTION_REQUIRED = 1, - SCN_REACHABLE_YES = 2, -} SCNStatus; + @enum SCNetworkConnectionFlags + @discussion Flags that indicate whether the specified network + nodename/address is reachable, requires a connection, + requires some user intervention in establishing the + connection, and whether the calling application must + initiate the connection using the (TBD???) API. + + @constant kSCNetworkFlagsTransientConnection + This flag indicates that the specified nodename/address can + be reached via a transient (e.g. PPP) connection. + @constant kSCNetworkFlagsReachable + This flag indicates that the specified nodename/address can + be reached using the current network configuration. -/*! - @enum SCNConnectionFlags - @discussion Additional flags which reflect whether a network connection - to the specified nodename/address is reachable, requires a - connection, requires some user intervention in establishing - the connection, and whether the calling application must initiate - the connection using the SCNEstablishConnection() API. - - @constant kSCNFlagsTransientConnection + @constant kSCNetworkFlagsConnectionRequired This flag indicates that the specified nodename/address can - be reached via a transient (e.g. PPP) connection. + be reached using the current network configuration but a + connection must first be established. + + As an example, this status would be returned for a dialup + connection that was not currently active but could handle + network traffic for the target system. + + @constant kSCNetworkFlagsConnectionAutomatic + This flag indicates that the specified nodename/address can + be reached using the current network configuration but a + connection must first be established. Any traffic directed + to the specified name/address will initiate the connection. - @constant kSCNFlagsConnectionAutomatic - The specified nodename/address can be reached using the - current network configuration but a connection must first - be established. Any traffic directed to the specified - name/address will initiate the connection. - - @constant kSCNFlagsInterventionRequired - The specified nodename/address can be reached using the - current network configuration but a connection must first - be established. In addition, some form of user intervention - will be required to establish this connection (e.g. providing - a password, authentication token, etc.). + @constant kSCNetworkFlagsInterventionRequired + This flag indicates that the specified nodename/address can + be reached using the current network configuration but a + connection must first be established. In addition, some + form of user intervention will be required to establish + this connection (e.g. providing a password, authentication + token, etc.). */ typedef enum { - kSCNFlagsTransientConnection = 1<<0, - kSCNFlagsConnectionAutomatic = 1<<1, - kSCNFlagsInterventionRequired = 1<<2, -} SCNConnectionFlags; + kSCNetworkFlagsTransientConnection = 1<<0, + kSCNetworkFlagsReachable = 1<<1, + kSCNetworkFlagsConnectionRequired = 1<<2, + kSCNetworkFlagsConnectionAutomatic = 1<<3, + kSCNetworkFlagsInterventionRequired = 1<<4, +} SCNetworkConnectionFlags; __BEGIN_DECLS /*! - @function SCNIsReachableByAddress + @function SCNetworkCheckReachabilityByAddress @discussion Determines if the given network address is reachable using the current network configuration. Note: This API is not thread safe. - @param address Pass the network address of the desired host. - @param addrlen Pass the length, in bytes, of the address. - @param flags A pointer to memory which will be filled with a - set of SCNConnectionFlags related to the reachability - of the specified address. If NULL, no flags will be - returned. - @param status A pointer to memory which will be filled with the - error status associated with any error communicating with - the system configuration daemon. - @result A constant of type SCNStatus indicating the reachability - of the specified node address. + @param address The network address of the desired host. + @param addrlen The length, in bytes, of the address. + @param flags A pointer to memory that will be filled with a + set of SCNetworkConnectionFlags detailing the reachability + of the specified address. + @result TRUE if the network connection flags are valid; FALSE if the + status could not be determined. */ -SCNStatus SCNIsReachableByAddress (const struct sockaddr *address, - const int addrlen, - int *flags, - const char **errorMessage); +Boolean +SCNetworkCheckReachabilityByAddress ( + const struct sockaddr *address, + const int addrlen, + SCNetworkConnectionFlags *flags + ); /*! - @function SCNIsReachableByName + @function SCNetworkCheckReachabilityByName @discussion Determines if the given network host/node name is reachable using the current network configuration. - @param nodename Pass a node name of the desired host. This name would + + Note: This API is not thread safe. + + @param nodename The node name of the desired host. This name would be the same as that passed to gethostbyname() or getaddrinfo(). - @param flags A pointer to memory which will be filled with a - set of SCNConnectionFlags related to the reachability - of the specified address. If NULL, no flags will be - returned. - @param status A pointer to memory which will be filled with the - error status associated with any error communicating with - the system configuration daemon. - @result A constant of type SCNStatus indicating the reachability - of the specified node address. + @param flags A pointer to memory that will be filled with a + set of SCNetworkConnectionFlags detailing the reachability + of the specified node name. + @result TRUE if the network connection flags are valid; FALSE if the + status could not be determined. */ -SCNStatus SCNIsReachableByName (const char *nodename, - int *flags, - const char **errorMessage); +Boolean +SCNetworkCheckReachabilityByName ( + const char *nodename, + SCNetworkConnectionFlags *flags + ); __END_DECLS -#endif /* _SCPNETWORK_H */ +#endif /* _SCNETWORK_H */ diff --git a/SystemConfiguration.fproj/SCP.c b/SystemConfiguration.fproj/SCP.c index 15d39f3..9252a15 100644 --- a/SystemConfiguration.fproj/SCP.c +++ b/SystemConfiguration.fproj/SCP.c @@ -20,8 +20,19 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #include -#include "SCPPrivate.h" +#include +#include "SCPreferencesInternal.h" #include #include @@ -29,29 +40,8 @@ #include #include - -static const struct scp_errmsg { - SCPStatus status; - char *message; -} scp_errmsgs[] = { - { SCP_OK, "Success!" }, - { SCP_BUSY, "Configuration daemon busy" }, - { SCP_NEEDLOCK, "Lock required for this operation" }, - { SCP_EACCESS, "Permission denied (must be root to obtain lock)" }, - { SCP_ENOENT, "Configuration file not found" }, - { SCP_BADCF, "Configuration file corrupt" }, - { SCP_NOKEY, "No such key" }, - { SCP_NOLINK, "No such link" }, - { SCP_EXISTS, "Key already defined" }, - { SCP_STALE, "Write attempted on stale version of object" }, - { SCP_INVALIDARGUMENT, "Invalid argument" }, - { SCP_FAILED, "Failed!" } -}; -#define nSCP_ERRMSGS (sizeof(scp_errmsgs)/sizeof(struct scp_errmsg)) - - __private_extern__ CFDataRef -_SCPSignatureFromStatbuf(const struct stat *statBuf) +__SCPSignatureFromStatbuf(const struct stat *statBuf) { CFMutableDataRef signature; SCPSignatureDataRef sig; @@ -68,7 +58,10 @@ _SCPSignatureFromStatbuf(const struct stat *statBuf) __private_extern__ char * -_SCPPrefsPath(CFStringRef prefsID, boolean_t perUser, CFStringRef user) +__SCPreferencesPath(CFAllocatorRef allocator, + CFStringRef prefsID, + Boolean perUser, + CFStringRef user) { CFStringRef path = NULL; int pathLen; @@ -90,24 +83,33 @@ _SCPPrefsPath(CFStringRef prefsID, boolean_t perUser, CFStringRef user) bzero(&login, sizeof(login)); if (user == NULL) { + CFStringRef u; + /* get current console user */ - if (SCDConsoleUserGet(login, - MAXLOGNAME, - NULL, - NULL) != SCD_OK) { + u = SCDynamicStoreCopyConsoleUser(NULL, NULL, NULL); + if (!u) { /* if could not get console user */ return NULL; } + (void) CFStringGetBytes(u, + CFRangeMake(0, CFStringGetLength(u)), + kCFStringEncodingMacRoman, + 0, + FALSE, + login, + MAXLOGNAME, + NULL); + CFRelease(u); } else { /* use specified user */ - (void)CFStringGetBytes(user, - CFRangeMake(0, CFStringGetLength(user)), - kCFStringEncodingMacRoman, - 0, - FALSE, - login, - MAXLOGNAME, - NULL); + (void) CFStringGetBytes(user, + CFRangeMake(0, CFStringGetLength(user)), + kCFStringEncodingMacRoman, + 0, + FALSE, + login, + MAXLOGNAME, + NULL); } /* get password entry for user */ @@ -118,7 +120,7 @@ _SCPPrefsPath(CFStringRef prefsID, boolean_t perUser, CFStringRef user) } /* create prefs ID */ - path = CFStringCreateWithFormat(NULL, + path = CFStringCreateWithFormat(allocator, NULL, CFSTR("%s/%@/%@"), pwd->pw_dir, @@ -128,7 +130,7 @@ _SCPPrefsPath(CFStringRef prefsID, boolean_t perUser, CFStringRef user) } else { if (prefsID == NULL) { /* default preference ID */ - path = CFStringCreateWithFormat(NULL, + path = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@"), PREFS_DEFAULT_DIR, @@ -138,7 +140,7 @@ _SCPPrefsPath(CFStringRef prefsID, boolean_t perUser, CFStringRef user) path = CFRetain(prefsID); } else { /* relative path */ - path = CFStringCreateWithFormat(NULL, + path = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@"), PREFS_DEFAULT_DIR, @@ -150,13 +152,13 @@ _SCPPrefsPath(CFStringRef prefsID, boolean_t perUser, CFStringRef user) * convert CFStringRef path to C-string path */ pathLen = CFStringGetLength(path) + 1; - pathStr = CFAllocatorAllocate(NULL, pathLen, 0); + pathStr = CFAllocatorAllocate(allocator, pathLen, 0); if (!CFStringGetCString(path, pathStr, pathLen, kCFStringEncodingMacRoman)) { - SCDLog(LOG_DEBUG, CFSTR("could not convert path to C string")); - CFAllocatorDeallocate(NULL, pathStr); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("could not convert path to C string")); + CFAllocatorDeallocate(allocator, pathStr); pathStr = NULL; } @@ -165,86 +167,75 @@ _SCPPrefsPath(CFStringRef prefsID, boolean_t perUser, CFStringRef user) } -SCPStatus -SCPGetSignature(SCPSessionRef session, CFDataRef *signature) +CFDataRef +SCPreferencesGetSignature(SCPreferencesRef session) { - SCPSessionPrivateRef sessionPrivate; + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; - if (session == NULL) { - return SCP_FAILED; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCPSessionPrivateRef)session; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesGetSignature:")); - *signature = sessionPrivate->signature; - return SCP_OK; + sessionPrivate->accessed = TRUE; + return sessionPrivate->signature; } __private_extern__ CFStringRef -_SCPNotificationKey(CFStringRef prefsID, - boolean_t perUser, - CFStringRef user, - int keyType) +_SCPNotificationKey(CFAllocatorRef allocator, + CFStringRef prefsID, + Boolean perUser, + CFStringRef user, + int keyType) { CFStringRef key = NULL; char *pathStr; char *typeStr; - pathStr = _SCPPrefsPath(prefsID, perUser, user); + pathStr = __SCPreferencesPath(allocator, prefsID, perUser, user); if (pathStr == NULL) { return NULL; } /* create notification key */ switch (keyType) { - case kSCPKeyLock : + case kSCPreferencesKeyLock : typeStr = "lock"; break; - case kSCPKeyCommit : + case kSCPreferencesKeyCommit : typeStr = "commit"; break; - case kSCPKeyApply : + case kSCPreferencesKeyApply : typeStr = "apply"; break; default : typeStr = "?"; } - key = CFStringCreateWithFormat(NULL, + key = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@%s:%s"), - kSCCacheDomainPrefs, + kSCDynamicStoreDomainPrefs, typeStr, pathStr); - CFAllocatorDeallocate(NULL, pathStr); + CFAllocatorDeallocate(allocator, pathStr); return key; } CFStringRef -SCPNotificationKeyCreate(CFStringRef prefsID, int keyType) +SCDynamicStoreKeyCreatePreferences(CFAllocatorRef allocator, + CFStringRef prefsID, + int keyType) { - return _SCPNotificationKey(prefsID, FALSE, NULL, keyType); + return _SCPNotificationKey(allocator, prefsID, FALSE, NULL, keyType); } CFStringRef -SCPUserNotificationKeyCreate(CFStringRef prefsID, CFStringRef user, int keyType) -{ - return _SCPNotificationKey(prefsID, TRUE, user, keyType); -} - - -const char * -SCPError(SCPStatus status) +SCDynamicStoreKeyCreateUserPreferences(CFAllocatorRef allocator, + CFStringRef prefsID, + CFStringRef user, + int keyType) { - int i; - - for (i = 0; i < nSCP_ERRMSGS; i++) { - if (scp_errmsgs[i].status == status) { - return scp_errmsgs[i].message; - } - } - return "(unknown error)"; + return _SCPNotificationKey(allocator, prefsID, TRUE, user, keyType); } diff --git a/SystemConfiguration.fproj/SCP.h b/SystemConfiguration.fproj/SCP.h index 3c210c4..ab6957a 100644 --- a/SystemConfiguration.fproj/SCP.h +++ b/SystemConfiguration.fproj/SCP.h @@ -23,382 +23,15 @@ #ifndef _SCP_H #define _SCP_H -#include -#include - -/*! - @header SCP.h - The SystemConfiguration framework provides access to the data used - to configure a running system. - - Specifically, the SCPxxx() API's allow an application to load and - store XML configuration data in a controlled manner - and provides the necessary notifications to other - applications which need to be aware of configuration - changes. - - The APIs provided by this framework communicate with the "configd" - daemon for any tasks requiring synchronization and/or - notification. - */ - - -/*! - @enum SCPStatus - @discussion Returned status codes. - @constant SCP_OK Success - @constant SCP_NOSESSION Preference session not active - @constant SCP_BUSY Configuration daemon busy - @constant SCD_NEEDLOCK Lock required for this operation - @constant SCP_EACCESS Permission denied (must be root to obtain lock) - @constant SCP_ENOENT Configuration file not found - @constant SCP_BADCF Configuration file corrupt - @constant SCD_NOKEY No such key - @constant SCD_NOLINK No such link - @constant SCP_EXISTS Key already defined - @constant SCP_STALE Write attempted on stale version of object - @constant SCP_INVALIDARGUMENT Invalid argument - @constant SCP_FAILED Generic error - */ -typedef enum { - SCP_OK = 0, /* Success */ - SCP_NOSESSION = 1024, /* Preference session not active */ - SCP_BUSY = 1025, /* Preferences update currently in progress */ - SCP_NEEDLOCK = 1026, /* Lock required for this operation */ - SCP_EACCESS = 1027, /* Permission denied */ - SCP_ENOENT = 1028, /* Configuration file not found */ - SCP_BADCF = 1029, /* Configuration file corrupt */ - SCP_NOKEY = 1030, /* No such key */ - SCP_NOLINK = 1031, /* No such link */ - SCP_EXISTS = 1032, /* No such key */ - SCP_STALE = 1033, /* Write attempted on stale version of object */ - SCP_INVALIDARGUMENT = 1034, /* Invalid argument */ - SCP_FAILED = 9999 /* Generic error */ -} SCPStatus; - - -/*! - @enum SCPOption - @discussion Used with the SCP[User]Open() and SCP[User]NotificationKeyCreate() - to describe the prefsID CFStringRef argument. - @constant kSCPOptionCreatePrefs Specifies that the preferences file should - be created if it does not exist. - */ -typedef enum { - kSCPOpenCreatePrefs = 1, /* create preferences file if not found */ -} SCPOption; - - -/*! - @enum SCPKeyType - @discussion Used with the SCDList() and SCDNotifierAdd() functions to describe - the CFStringRef argument. - @constant kSCDKeyLock key used when exclusive access to the stored preferences - is obtained or released. - @constant kSCDKeyCommit key used when new preferences are committed to the store - @constant kSCDKeyApply key used when new preferences are to be applied to the - active system configuration. - */ -typedef enum { - kSCPKeyLock = 1, - kSCPKeyCommit = 2, - kSCPKeyApply = 3, -} SCPKeyType; - - -/*! - @typedef SCPSessionRef - @discussion This is the type of a handle to an open "session" for - accessing system configuration preferences. - */ -typedef void * SCPSessionRef; - - -__BEGIN_DECLS - -/*! - @function SCPOpen - @discussion Initiates access to the per-system set of configuration - preferences. - - This function will ensure that the current state of the prefsID is - retrieved (by reading the whole thing into memory, or at least, - open()'ing the file and keeping it open) - @param session A pointer to memory which will be filled with an - SCPSessionRef handle to be used for all subsequent requests. - If a session cannot be established, the contents of - memory pointed to by this parameter are undefined. - @param name Pass a string which describes the name of the calling - process. - @param prefsID Pass a string which identifies the name of the - group of preferences to be accessed/updated. A NULL value - specifies the default system configuration preferences. - @param options Pass a bitfield of type SCPOpenOption containing - one or more flags describing how the preferences should - be accessed. - - @result A constant of type SCPStatus indicating the success (or - failure) of the call. - */ -SCPStatus SCPOpen (SCPSessionRef *session, - CFStringRef name, - CFStringRef prefsID, - int options); - -/*! - @function SCPUserOpen - @discussion Initiates access to the per-user set of configuration - preferences. - - This function will ensure that the current state of the prefsID is - retrieved (by reading the whole thing into memory, or at least, - open()'ing the file and keeping it open) - @param session A pointer to memory which will be filled with an - SCPSessionRef handle to be used for all subsequent requests. - If a session cannot be established, the contents of - memory pointed to by this parameter are undefined. - @param name Pass a string which describes the name of the calling - process. - @param prefsID Pass a string which identifies the name of the - group of preferences to be accessed/updated. - @param user Pass a string which identifies the user/login who's - preferences should be accessed. A NULL value specifies - the current console user. - @param options Pass a bitfield of type SCPOpenOption containing - one or more flags describing how the preferences should - be accessed. - - @result A constant of type SCPStatus indicating the success (or - failure) of the call. - */ -SCPStatus SCPUserOpen (SCPSessionRef *session, - CFStringRef name, - CFStringRef prefsID, - CFStringRef user, - int options); - -/*! - @function SCPClose - @discussion Terminates access to a set of configuration preferences. - - This function frees/closes all allocated/opened resources. Any - uncommitted changes are NOT written. - @param session Pass a pointer to the SCPSessionRef handle which should - be closed. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. - */ -SCPStatus SCPClose (SCPSessionRef *session); - -/*! - @function SCPLock - @discussion Locks access to the configuration preferences. - - This function obtains exclusive access to the configuration - preferences associated with this prefsID. Clients attempting - to obtain exclusive access the preferences will either receive - an SCP_BUSY error or block waiting for the lock to be released. - @param session Pass an SCPSessionRef handle which should be used for - all API calls. - @param wait Pass a boolean flag indicating whether the calling process - should block waiting for another process to complete its update - operation and release its lock. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_BUSY, SCP_EACCESS, SCP_STALE. - */ -SCPStatus SCPLock (SCPSessionRef session, - boolean_t wait); - -/*! - @function SCPCommit - @discussion Commits changes made to the configuration preferences to - persitent storage. - - This function commits the any changes to permanent storage. An - implicit call to SCPLock/SCPUnlock will be made if exclusive - access had not been established. - @param session Pass an SCPSessionRef handle which should be used for - all API calls. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_BUSY, SCP_EACCESS, SCP_STALE. - */ -SCPStatus SCPCommit (SCPSessionRef session); - -/*! - @function SCPApply - @discussion Requests that the currently stored configuration - preferences be applied to the active configuration. - @param session Pass an SCPSessionRef handle which should be used for - all API calls. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_EACCESS. - */ -SCPStatus SCPApply (SCPSessionRef session); - -/*! - @function SCPUnlock - @discussion Releases exclusive access to the configuration preferences. - - This function releases the exclusive access "lock" fr this prefsID. - Other clients will be now be able to establish exclusive access to - the preferences. - @param session Pass an SCPSessionRef handle which should be used for - all API calls. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. - */ -SCPStatus SCPUnlock (SCPSessionRef session); - -/*! - @function SCPGetSignature - @discussion Returns an sequence of bytes which can be used to determine - if the saved configuration preferences have changed. - @param session Pass an SCPSessionRef handle which should be used for - all API calls. - @param signature Pass a pointer to a CFDataRef which will be reflect - the signature of the configuration preferences at the time - of the call to SCPOpen(). - @result A constant of type SCPStatus indicating the success (or - failure) of the call. - */ -SCPStatus SCPGetSignature (SCPSessionRef session, - CFDataRef *signature); - -/*! - @function SCPList - @discussion Returns an array of currently defined preference keys. - @param session Pass an SCPSessionRef handle which should be used for - all API calls. - @param keys Pass a pointer to a CFArrayRef which will be set to a new - array of currently defined preference keys. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. - */ -SCPStatus SCPList (SCPSessionRef session, - CFArrayRef *keys); - -/*! - @function SCPGet - @discussion Returns the data associated with a preference key. - - This function retrieves data associated with a key for the prefsID. - You "could" read stale data and not know it, unless you first call - SCPLock(). - @param session Pass an SCPSessionRef handle which should be used for - all API calls. - @param key Pass a reference to the preference key to be returned. - @param data Pass a pointer to a CFPropertyListRef which will be set to a - new object containing the data associated with the - configuration preference. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_NOKEY. - */ -SCPStatus SCPGet (SCPSessionRef session, - CFStringRef key, - CFPropertyListRef *data); - -/*! - @function SCPAdd - @discussion Adds data for a preference key. - - This function associates new data with the specified key. In order - to commit these changes to permanent storage a call must be made to - SCDPCommit(). - @param session Pass the SCPSessionRef handle which should be used to - communicate with the APIs. - @param key Pass a reference to the preference key to be updated. - @param data Pass a reference to the CFPropertyListRef object containing the - data to be associated with the configuration preference. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_EXISTS. - */ -SCPStatus SCPAdd (SCPSessionRef session, - CFStringRef key, - CFPropertyListRef data); - -/*! - @function SCPSet - @discussion Updates the data associated with a preference key. - - This function creates (or updates) the data associated with the - specified key. In order to commit these changes to permanent - storage a call must be made to SCDPCommit(). - @param session Pass the SCPSessionRef handle which should be used to - communicate with the APIs. - @param key Pass a reference to the preference key to be updated. - @param data Pass a reference to the CFPropertyListRef object containing the - data to be associated with the configuration preference. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK. - */ -SCPStatus SCPSet (SCPSessionRef session, - CFStringRef key, - CFPropertyListRef data); - -/*! - @function SCPRemove - @discussion Removes the data associated with a preference key. - - This function removes the data associated with the specified - key. In order to commit these changes to permanent storage a - call must be made to SCDPCommit(). - @param session Pass the SCPSessionRef handle which should be used to - communicate with the APIs. - @param key Pass a reference to the preference key to be removed. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_NOKEY. - */ -SCPStatus SCPRemove (SCPSessionRef session, - CFStringRef key); - -/*! - @function SCPNotificationKeyCreate - @discussion Creates a key which can be used by the SCDNotifierAdd() - function to receive notifications of changes to the saved - preferences. - @param prefsID Pass a string which identifies the name of the - preferences to be accessed/updated. A NULL value specifies - the default system configuration preferences. - @param keyType Pass a kSCPKeyType indicating the type a notification - key to be returned. - @result A notification string for the specified preference identifier. - */ -CFStringRef SCPNotificationKeyCreate (CFStringRef prefsID, - int keyType); - -/*! - @function SCPUserNotificationKeyCreate - @discussion Creates a key which can be used by the SCDNotifierAdd() - function to receive notifications of changes to the saved - preferences. - @param prefsID Pass a string which identifies the name of the - preferences to be accessed/updated. A NULL value specifies - the default system configuration preferences. - @param user Pass a string which identifies the user/login who's - preferences should be accessed. A NULL value specifies - the current console user. - @param keyType Pass a kSCPKeyType indicating the type a notification - key to be returned. - @result A notification string for the specified preference identifier. - */ -CFStringRef SCPUserNotificationKeyCreate (CFStringRef prefsID, - CFStringRef user, - int keyType); - -/*! - @function SCPError - @discussion - @param status - @result - */ -const char * SCPError (SCPStatus status); - -__END_DECLS +#ifndef _SYSTEMCONFIGURATION_H +#warning Your code has directly included the (old) +#warning header file. Please dont do that. Use the top-level header file: +#warning +#warning +#warning +#warning Note: the configuration preference APIs have been moved out of +#warning the SCP.h header file. +#include /* ...and try to keep everyone happy */ +#endif #endif /* _SCP_H */ diff --git a/SystemConfiguration.fproj/SCPAdd.c b/SystemConfiguration.fproj/SCPAdd.c index eaba463..70bc7a7 100644 --- a/SystemConfiguration.fproj/SCPAdd.c +++ b/SystemConfiguration.fproj/SCPAdd.c @@ -20,31 +20,37 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include "SCPPrivate.h" - -#include - -#include -#include -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ +#include +#include +#include "SCPreferencesInternal.h" -SCPStatus -SCPAdd(SCPSessionRef session, CFStringRef key, CFPropertyListRef data) +Boolean +SCPreferencesAddValue(SCPreferencesRef session, CFStringRef key, CFPropertyListRef value) { - SCPSessionPrivateRef sessionPrivate; + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; - if (session == NULL) { - return SCP_FAILED; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCPSessionPrivateRef)session; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesAddValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); + + sessionPrivate->accessed = TRUE; if (CFDictionaryContainsKey(sessionPrivate->prefs, key)) { - return SCP_EXISTS; + _SCErrorSet(kSCStatusKeyExists); + return FALSE; } - CFDictionaryAddValue(sessionPrivate->prefs, key, data); - sessionPrivate->changed = TRUE; - return SCP_OK; + CFDictionaryAddValue(sessionPrivate->prefs, key, value); + sessionPrivate->changed = TRUE; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCPApply.c b/SystemConfiguration.fproj/SCPApply.c index 8c42762..c0b9695 100644 --- a/SystemConfiguration.fproj/SCPApply.c +++ b/SystemConfiguration.fproj/SCPApply.c @@ -20,28 +20,27 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include "SCPPrivate.h" - -#include - -#include -#include -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ +#include +#include +#include "SCPreferencesInternal.h" -SCPStatus -SCPApply(SCPSessionRef session) +Boolean +SCPreferencesApplyChanges(SCPreferencesRef session) { - SCPSessionPrivateRef sessionPrivate; - SCPStatus scp_status = SCP_OK; - SCDStatus scd_status; - boolean_t wasLocked; + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; + Boolean wasLocked; - if (session == NULL) { - return SCP_FAILED; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCPSessionPrivateRef)session; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesApplyChanges:")); /* * Determine if the we have exclusive access to the preferences @@ -49,41 +48,41 @@ SCPApply(SCPSessionRef session) */ wasLocked = sessionPrivate->locked; if (!wasLocked) { - scp_status = SCPLock(session, TRUE); - if (scp_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" SCPLock(): %s"), SCPError(scp_status)); - return scp_status; + if (!SCPreferencesLock(session, TRUE)) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" SCPreferencesLock() failed")); + return FALSE; } } if (!sessionPrivate->isRoot) { /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */ - goto notRoot; + goto perUser; } /* if necessary, create the session "apply" key */ if (sessionPrivate->sessionKeyApply == NULL) { - sessionPrivate->sessionKeyApply = _SCPNotificationKey(sessionPrivate->prefsID, + sessionPrivate->sessionKeyApply = _SCPNotificationKey(NULL, + sessionPrivate->prefsID, sessionPrivate->perUser, sessionPrivate->user, - kSCPKeyApply); + kSCPreferencesKeyApply); } /* post notification */ - scd_status = SCDLock(sessionPrivate->session); - if (scd_status == SCD_OK) { - (void) SCDTouch (sessionPrivate->session, sessionPrivate->sessionKeyApply); - (void) SCDRemove(sessionPrivate->session, sessionPrivate->sessionKeyApply); - (void) SCDUnlock(sessionPrivate->session); - } else { - SCDLog(LOG_DEBUG, CFSTR(" SCDLock(): %s"), SCDError(scd_status)); - scp_status = SCP_FAILED; + if (!SCDynamicStoreNotifyValue(sessionPrivate->session, + sessionPrivate->sessionKeyApply)) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" SCDynamicStoreNotifyValue() failed")); + _SCErrorSet(kSCStatusFailed); + goto error; } - notRoot: + perUser : + + if (!wasLocked) (void) SCPreferencesUnlock(session); + return TRUE; - if (!wasLocked) - (void) SCPUnlock(session); + error : - return scp_status; + if (!wasLocked) (void) SCPreferencesUnlock(session); + return FALSE; } diff --git a/SystemConfiguration.fproj/SCPClose.c b/SystemConfiguration.fproj/SCPClose.c deleted file mode 100644 index 8ad50cf..0000000 --- a/SystemConfiguration.fproj/SCPClose.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright(c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1(the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include "SCPPrivate.h" - -#include - -#include -#include -#include - - -SCPStatus -SCPClose(SCPSessionRef *session) -{ - SCPSessionPrivateRef sessionPrivate; - - if ((session == NULL) || (*session == NULL)) { - return SCP_FAILED; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCPSessionPrivateRef)*session; - - /* release resources */ - if (sessionPrivate->name) CFRelease(sessionPrivate->name); - if (sessionPrivate->prefsID) CFRelease(sessionPrivate->prefsID); - if (sessionPrivate->user) CFRelease(sessionPrivate->user); - if (sessionPrivate->path) CFAllocatorDeallocate(NULL, sessionPrivate->path); - if (sessionPrivate->signature) CFRelease(sessionPrivate->signature); - if (sessionPrivate->session) { - SCDStatus scd_status; - - scd_status = SCDClose(&sessionPrivate->session); - if (scd_status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDClose() failed: %s"), SCDError(scd_status)); - } - } - if (sessionPrivate->sessionKeyLock) CFRelease(sessionPrivate->sessionKeyLock); - if (sessionPrivate->sessionKeyCommit) CFRelease(sessionPrivate->sessionKeyCommit); - if (sessionPrivate->sessionKeyApply) CFRelease(sessionPrivate->sessionKeyApply); - if (sessionPrivate->prefs) CFRelease(sessionPrivate->prefs); - - /* release session */ - CFAllocatorDeallocate(NULL, sessionPrivate); - *session = NULL; - return SCP_OK; -} diff --git a/SystemConfiguration.fproj/SCPCommit.c b/SystemConfiguration.fproj/SCPCommit.c index 7ea5a5e..fe6f435 100644 --- a/SystemConfiguration.fproj/SCPCommit.c +++ b/SystemConfiguration.fproj/SCPCommit.c @@ -20,28 +20,31 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include "SCPPrivate.h" +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ -#include +#include +#include +#include "SCPreferencesInternal.h" #include #include #include - -SCPStatus -SCPCommit(SCPSessionRef session) +Boolean +SCPreferencesCommitChanges(SCPreferencesRef session) { - SCPSessionPrivateRef sessionPrivate; - SCPStatus scp_status = SCP_OK; - SCDStatus scd_status; - boolean_t wasLocked; + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; + Boolean wasLocked; - if (session == NULL) { - return SCP_FAILED; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCPSessionPrivateRef)session; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesCommitChanges:")); /* * Determine if the we have exclusive access to the preferences @@ -49,10 +52,9 @@ SCPCommit(SCPSessionRef session) */ wasLocked = sessionPrivate->locked; if (!wasLocked) { - scp_status = SCPLock(session, TRUE); - if (scp_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" SCPLock(): %s"), SCPError(scp_status)); - return scp_status; + if (!SCPreferencesLock(session, TRUE)) { + SCLog(_sc_verbose, LOG_ERR, CFSTR(" SCPreferencesLock() failed")); + return FALSE; } } @@ -73,9 +75,8 @@ SCPCommit(SCPSessionRef session) statBuf.st_uid = geteuid(); statBuf.st_gid = getegid(); } else { - SCDLog(LOG_DEBUG, CFSTR("stat() failed: %s"), strerror(errno)); - scp_status = SCP_FAILED; - goto done; + SCLog(_sc_verbose, LOG_ERR, CFSTR("stat() failed: %s"), strerror(errno)); + goto error; } } @@ -104,70 +105,76 @@ SCPCommit(SCPSessionRef session) } } } - SCDLog(LOG_DEBUG, CFSTR("SCPCommit open() failed: %s"), strerror(errno)); + SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPCommit open() failed: %s"), strerror(errno)); CFAllocatorDeallocate(NULL, newPath); - scp_status = SCP_FAILED; - goto done; + goto error; } /* preserve permissions */ - (void)fchown(fd, statBuf.st_uid, statBuf.st_gid); + (void) fchown(fd, statBuf.st_uid, statBuf.st_gid); /* write the new preferences */ newPrefs = CFPropertyListCreateXMLData(NULL, sessionPrivate->prefs); + if (!newPrefs) { + _SCErrorSet(kSCStatusFailed); + SCLog(_sc_verbose, LOG_ERR, CFSTR(" CFPropertyListCreateXMLData() failed")); + CFAllocatorDeallocate(NULL, newPath); + (void) close(fd); + goto error; + } (void) write(fd, CFDataGetBytePtr(newPrefs), CFDataGetLength(newPrefs)); (void) close(fd); CFRelease(newPrefs); /* rename new->old */ if (rename(newPath, sessionPrivate->path) == -1) { - SCDLog(LOG_DEBUG, CFSTR("rename() failed: %s"), strerror(errno)); + _SCErrorSet(errno); + SCLog(_sc_verbose, LOG_ERR, CFSTR("rename() failed: %s"), strerror(errno)); CFAllocatorDeallocate(NULL, newPath); - scp_status = SCP_FAILED; - goto done; + goto error; } CFAllocatorDeallocate(NULL, newPath); /* update signature */ if (stat(sessionPrivate->path, &statBuf) == -1) { - SCDLog(LOG_DEBUG, CFSTR("stat() failed: %s"), strerror(errno)); - scp_status = SCP_FAILED; - goto done; + _SCErrorSet(errno); + SCLog(_sc_verbose, LOG_ERR, CFSTR("stat() failed: %s"), strerror(errno)); + goto error; } CFRelease(sessionPrivate->signature); - sessionPrivate->signature = _SCPSignatureFromStatbuf(&statBuf); + sessionPrivate->signature = __SCPSignatureFromStatbuf(&statBuf); } if (!sessionPrivate->isRoot) { /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */ - goto done; + goto perUser; } /* if necessary, create the session "commit" key */ if (sessionPrivate->sessionKeyCommit == NULL) { - sessionPrivate->sessionKeyCommit = _SCPNotificationKey(sessionPrivate->prefsID, + sessionPrivate->sessionKeyCommit = _SCPNotificationKey(NULL, + sessionPrivate->prefsID, sessionPrivate->perUser, sessionPrivate->user, - kSCPKeyCommit); + kSCPreferencesKeyCommit); } /* post notification */ - scd_status = SCDLock(sessionPrivate->session); - if (scd_status == SCD_OK) { - (void) SCDTouch (sessionPrivate->session, sessionPrivate->sessionKeyCommit); - (void) SCDRemove(sessionPrivate->session, sessionPrivate->sessionKeyCommit); - (void) SCDUnlock(sessionPrivate->session); - } else { - SCDLog(LOG_DEBUG, CFSTR(" SCDLock(): %s"), SCDError(scd_status)); - scp_status = SCP_FAILED; + if (!SCDynamicStoreNotifyValue(sessionPrivate->session, + sessionPrivate->sessionKeyCommit)) { + SCLog(_sc_verbose, LOG_ERR, CFSTR(" SCDynamicStoreNotifyValue() failed")); + _SCErrorSet(kSCStatusFailed); + goto error; } - done : - - if (!wasLocked) - (void) SCPUnlock(session); + perUser : + if (!wasLocked) (void) SCPreferencesUnlock(session); sessionPrivate->changed = FALSE; + return TRUE; + + error : - return scp_status; + if (!wasLocked) (void) SCPreferencesUnlock(session); + return FALSE; } diff --git a/SystemConfiguration.fproj/SCPGet.c b/SystemConfiguration.fproj/SCPGet.c index bd0a50a..50f7cd4 100644 --- a/SystemConfiguration.fproj/SCPGet.c +++ b/SystemConfiguration.fproj/SCPGet.c @@ -20,32 +20,39 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include "SCPPrivate.h" - -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ #include #include #include +#include +#include +#include "SCPreferencesInternal.h" -SCPStatus -SCPGet(SCPSessionRef session, CFStringRef key, CFPropertyListRef *data) +CFPropertyListRef +SCPreferencesGetValue(SCPreferencesRef session, CFStringRef key) { - SCPSessionPrivateRef sessionPrivate; - CFPropertyListRef val; + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; + CFPropertyListRef value; - if (session == NULL) { - return SCP_FAILED; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCPSessionPrivateRef)session; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesGetValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - val = CFDictionaryGetValue(sessionPrivate->prefs, key); - if (val == NULL) { - return SCP_NOKEY; + sessionPrivate->accessed = TRUE; + value = CFDictionaryGetValue(sessionPrivate->prefs, key); + if (!value) { + _SCErrorSet(kSCStatusNoKey); } - *data = val; - return SCP_OK; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); + return value; } diff --git a/SystemConfiguration.fproj/SCPList.c b/SystemConfiguration.fproj/SCPList.c index 3fb1a89..d66ed6e 100644 --- a/SystemConfiguration.fproj/SCPList.c +++ b/SystemConfiguration.fproj/SCPList.c @@ -20,51 +20,39 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include "SCPPrivate.h" - -#include - -#include -#include -#include - - -static CFComparisonResult -sort_keys(const void *p1, const void *p2, void *context) { - CFStringRef key1 = (CFStringRef)p1; - CFStringRef key2 = (CFStringRef)p2; - return CFStringCompare(key1, key2, 0); -} +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ +#include +#include +#include "SCPreferencesInternal.h" -SCPStatus -SCPList(SCPSessionRef session, CFArrayRef *keys) +CFArrayRef +SCPreferencesCopyKeyList(SCPreferencesRef session) { - SCPSessionPrivateRef sessionPrivate; + CFAllocatorRef allocator = CFGetAllocator(session); + CFArrayRef keys; + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; CFIndex prefsCnt; void **prefsKeys; - CFArrayRef allKeys; - CFMutableArrayRef sortedKeys; - if (session == NULL) { - return SCP_FAILED; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCPSessionPrivateRef)session; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesCopyKeyList:")); prefsCnt = CFDictionaryGetCount(sessionPrivate->prefs); - prefsKeys = CFAllocatorAllocate(NULL, prefsCnt * sizeof(CFStringRef), 0); + prefsKeys = CFAllocatorAllocate(allocator, prefsCnt * sizeof(CFStringRef), 0); CFDictionaryGetKeysAndValues(sessionPrivate->prefs, prefsKeys, NULL); - allKeys = CFArrayCreate(NULL, prefsKeys, prefsCnt, &kCFTypeArrayCallBacks); - CFAllocatorDeallocate(NULL, prefsKeys); + keys = CFArrayCreate(allocator, prefsKeys, prefsCnt, &kCFTypeArrayCallBacks); + CFAllocatorDeallocate(allocator, prefsKeys); - sortedKeys = CFArrayCreateMutableCopy(NULL, prefsCnt, allKeys); - CFRelease(allKeys); - CFArraySortValues(sortedKeys, - CFRangeMake(0, prefsCnt), - sort_keys, - NULL); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" keys = %@"), keys); - *keys = sortedKeys; - return SCP_OK; + sessionPrivate->accessed = TRUE; + return keys; } diff --git a/SystemConfiguration.fproj/SCPLock.c b/SystemConfiguration.fproj/SCPLock.c index 760de8d..a153f33 100644 --- a/SystemConfiguration.fproj/SCPLock.c +++ b/SystemConfiguration.fproj/SCPLock.c @@ -20,126 +20,135 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include "SCPPrivate.h" +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ -#include +#include +#include +#include "SCPreferencesInternal.h" #include #include #include - -SCPStatus -SCPLock(SCPSessionRef session, boolean_t wait) +Boolean +SCPreferencesLock(SCPreferencesRef session, Boolean wait) { - SCPStatus scp_status; - SCDStatus scd_status; - SCPSessionPrivateRef sessionPrivate; - SCDHandleRef handle = NULL; - CFDateRef value; CFArrayRef changes; + CFDataRef currentSignature = NULL; + Boolean haveLock = FALSE; + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; struct stat statBuf; - CFDataRef currentSignature; + CFDateRef value = NULL; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesLock:")); - if (session == NULL) { - return SCP_FAILED; /* you can't do anything with a closed session */ + if (sessionPrivate->locked) { + /* sorry, you already have the lock */ + _SCErrorSet(kSCStatusLocked); + return FALSE; } - sessionPrivate = (SCPSessionPrivateRef)session; if (!sessionPrivate->isRoot) { - /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */ - goto notRoot; + if (!sessionPrivate->perUser) { + _SCErrorSet(kSCStatusAccessError); + return FALSE; + } else { + /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */ + goto perUser; + } } if (sessionPrivate->session == NULL) { /* open a session */ - scd_status = SCDOpen(&sessionPrivate->session, sessionPrivate->name); - if (scd_status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDOpen() failed: %s"), SCDError(scd_status)); - return SCP_FAILED; + sessionPrivate->session = SCDynamicStoreCreate(NULL, + CFSTR("SCPreferencesLock"), + NULL, + NULL); + if (!sessionPrivate->session) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + return FALSE; } } if (sessionPrivate->sessionKeyLock == NULL) { /* create the session "lock" key */ - sessionPrivate->sessionKeyLock = _SCPNotificationKey(sessionPrivate->prefsID, + sessionPrivate->sessionKeyLock = _SCPNotificationKey(NULL, + sessionPrivate->prefsID, sessionPrivate->perUser, sessionPrivate->user, - kSCPKeyLock); + kSCPreferencesKeyLock); } - scd_status = SCDNotifierAdd(sessionPrivate->session, - sessionPrivate->sessionKeyLock, - 0); - if (scd_status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDNotifierAdd() failed: %s"), SCDError(scd_status)); - scp_status = SCP_FAILED; + if (!SCDynamicStoreAddWatchedKey(sessionPrivate->session, + sessionPrivate->sessionKeyLock, + FALSE)) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreAddWatchedKey() failed")); goto error; } - handle = SCDHandleInit(); value = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); - SCDHandleSetData(handle, value); - CFRelease(value); while (TRUE) { + CFArrayRef changedKeys; + /* * Attempt to acquire the lock */ - scd_status = SCDAddSession(sessionPrivate->session, - sessionPrivate->sessionKeyLock, - handle); - switch (scd_status) { - case SCD_OK : - scp_status = SCP_OK; - goto done; - case SCD_EXISTS : - if (!wait) { - scp_status = SCP_BUSY; - goto error; - } - break; - default : - SCDLog(LOG_INFO, CFSTR("SCDAddSession() failed: %s"), SCDError(scd_status)); - scp_status = SCP_FAILED; + if (SCDynamicStoreAddTemporaryValue(sessionPrivate->session, + sessionPrivate->sessionKeyLock, + value)) { + haveLock = TRUE; + goto done; + } else { + if (!wait) { + _SCErrorSet(kSCStatusPrefsBusy); goto error; + } } /* * Wait for the lock to be released */ - scd_status = SCDNotifierWait(sessionPrivate->session); - if (scd_status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDAddSession() failed: %s"), SCDError(scd_status)); - scp_status = SCP_FAILED; + if (!SCDynamicStoreNotifyWait(sessionPrivate->session)) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreNotifyWait() failed")); goto error; } + changedKeys = SCDynamicStoreCopyNotifiedKeys(sessionPrivate->session); + if (!changedKeys) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCopyNotifiedKeys() failed")); + goto error; + } + CFRelease(changedKeys); } done : - SCDHandleRelease(handle); - handle = NULL; + CFRelease(value); + value = NULL; - scd_status = SCDNotifierRemove(sessionPrivate->session, - sessionPrivate->sessionKeyLock, - 0); - if (scd_status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDNotifierRemove() failed: %s"), SCDError(scd_status)); - scp_status = SCP_FAILED; + if (!SCDynamicStoreRemoveWatchedKey(sessionPrivate->session, + sessionPrivate->sessionKeyLock, + 0)) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreRemoveWatchedKey() failed")); goto error; } - scd_status = SCDNotifierGetChanges(sessionPrivate->session, &changes); - if (scd_status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDNotifierGetChanges() failed: %s"), SCDError(scd_status)); - scp_status = SCP_FAILED; + changes = SCDynamicStoreCopyNotifiedKeys(sessionPrivate->session); + if (!changes) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCopyNotifiedKeys() failed")); goto error; } CFRelease(changes); - notRoot: + perUser: /* * Check the signature @@ -148,25 +157,65 @@ SCPLock(SCPSessionRef session, boolean_t wait) if (errno == ENOENT) { bzero(&statBuf, sizeof(statBuf)); } else { - SCDLog(LOG_DEBUG, CFSTR("stat() failed: %s"), strerror(errno)); - scp_status = SCP_STALE; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("stat() failed: %s"), strerror(errno)); + _SCErrorSet(kSCStatusStale); goto error; } } - currentSignature = _SCPSignatureFromStatbuf(&statBuf); + currentSignature = __SCPSignatureFromStatbuf(&statBuf); if (!CFEqual(sessionPrivate->signature, currentSignature)) { - CFRelease(currentSignature); - scp_status = SCP_STALE; - goto error; + if (sessionPrivate->accessed) { + /* + * the preferences have been accessed since the + * session was created so we've got no choice + * but to deny the lock request. + */ + _SCErrorSet(kSCStatusStale); + goto error; + } else { + /* + * the file contents have changed but since we + * haven't accessed any of the preferences we + * don't need to return an error. Simply reload + * the stored data and proceed. + */ + SCPreferencesRef newPrefs; + SCPreferencesPrivateRef newPrivate; + + newPrefs = __SCPreferencesCreate(NULL, + sessionPrivate->name, + sessionPrivate->prefsID, + sessionPrivate->perUser, + sessionPrivate->user); + if (!newPrefs) { + /* if updated preferences could not be loaded */ + _SCErrorSet(kSCStatusStale); + goto error; + } + + /* synchronize this sessions prefs/signature */ + newPrivate = (SCPreferencesPrivateRef)newPrefs; + CFRelease(sessionPrivate->prefs); + sessionPrivate->prefs = CFRetain(newPrivate->prefs); + CFRelease(sessionPrivate->signature); + sessionPrivate->signature = CFRetain(newPrivate->signature); + CFRelease(newPrefs); + } } CFRelease(currentSignature); sessionPrivate->locked = TRUE; - return SCD_OK; + return TRUE; error : - if (handle) SCDHandleRelease(handle); - return scp_status; + if (haveLock) { + SCDynamicStoreRemoveValue(sessionPrivate->session, + sessionPrivate->sessionKeyLock); + } + if (currentSignature) CFRelease(currentSignature); + if (value) CFRelease(value); + + return FALSE; } diff --git a/SystemConfiguration.fproj/SCPOpen.c b/SystemConfiguration.fproj/SCPOpen.c index dd3e772..6a13925 100644 --- a/SystemConfiguration.fproj/SCPOpen.c +++ b/SystemConfiguration.fproj/SCPOpen.c @@ -20,79 +20,177 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include -#include "SCPPrivate.h" +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ -#include +#include +#include +#include "SCPreferencesInternal.h" #include +#include #include #include +static CFStringRef +__SCPreferencesCopyDescription(CFTypeRef cf) { + CFAllocatorRef allocator = CFGetAllocator(cf); + CFMutableStringRef result; + + result = CFStringCreateMutable(allocator, 0); + CFStringAppendFormat(result, NULL, CFSTR(" {\n"), cf, allocator); + CFStringAppendFormat(result, NULL, CFSTR("}")); + + return result; +} + + +static void +__SCPreferencesDeallocate(CFTypeRef cf) +{ + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)cf; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesDeallocate:")); + + /* release resources */ + if (sessionPrivate->name) CFRelease(sessionPrivate->name); + if (sessionPrivate->prefsID) CFRelease(sessionPrivate->prefsID); + if (sessionPrivate->user) CFRelease(sessionPrivate->user); + if (sessionPrivate->path) CFAllocatorDeallocate(NULL, sessionPrivate->path); + if (sessionPrivate->signature) CFRelease(sessionPrivate->signature); + if (sessionPrivate->session) CFRelease(sessionPrivate->session); + if (sessionPrivate->sessionKeyLock) CFRelease(sessionPrivate->sessionKeyLock); + if (sessionPrivate->sessionKeyCommit) CFRelease(sessionPrivate->sessionKeyCommit); + if (sessionPrivate->sessionKeyApply) CFRelease(sessionPrivate->sessionKeyApply); + if (sessionPrivate->prefs) CFRelease(sessionPrivate->prefs); + + return; +} + + +static CFTypeID __kSCPreferencesTypeID = _kCFRuntimeNotATypeID; + + +static const CFRuntimeClass __SCPreferencesClass = { + 0, // version + "SCPreferences", // className + NULL, // init + NULL, // copy + __SCPreferencesDeallocate, // dealloc + NULL, // equal + NULL, // hash + NULL, // copyFormattingDesc + __SCPreferencesCopyDescription // copyDebugDesc +}; + + +static pthread_once_t initialized = PTHREAD_ONCE_INIT; + + +static void +__SCPreferencesInitialize(void) { + __kSCPreferencesTypeID = _CFRuntimeRegisterClass(&__SCPreferencesClass); + return; +} + -static SCPStatus -_SCPOpen(SCPSessionRef *session, - CFStringRef name, - CFStringRef prefsID, - boolean_t perUser, - CFStringRef user, - int options) +SCPreferencesRef +__SCPreferencesCreatePrivate(CFAllocatorRef allocator) { - SCPStatus scp_status; - SCPSessionPrivateRef newSession; - int fd = -1; - struct stat statBuf; - CFMutableDataRef xmlData; - CFStringRef xmlError; - - newSession = (SCPSessionPrivateRef)CFAllocatorAllocate(NULL, sizeof(SCPSessionPrivate), 0); - newSession->name = NULL; - newSession->prefsID = NULL; - newSession->perUser = perUser; - newSession->user = NULL; - newSession->path = NULL; - newSession->signature = NULL; - newSession->session = NULL; - newSession->sessionKeyLock = NULL; - newSession->sessionKeyCommit = NULL; - newSession->sessionKeyApply = NULL; - newSession->prefs = NULL; - newSession->changed = FALSE; - newSession->locked = FALSE; - newSession->isRoot = (geteuid() == 0); + SCPreferencesPrivateRef prefs; + UInt32 size; + + /* initialize runtime */ + pthread_once(&initialized, __SCPreferencesInitialize); + + /* allocate session */ + size = sizeof(SCPreferencesPrivate) - sizeof(CFRuntimeBase); + prefs = (SCPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator, + __kSCPreferencesTypeID, + size, + NULL); + if (!prefs) { + return NULL; + } + + prefs->name = NULL; + prefs->prefsID = NULL; + prefs->perUser = FALSE; + prefs->user = NULL; + prefs->path = NULL; + prefs->signature = NULL; + prefs->session = NULL; + prefs->sessionKeyLock = NULL; + prefs->sessionKeyCommit = NULL; + prefs->sessionKeyApply = NULL; + prefs->prefs = NULL; + prefs->accessed = FALSE; + prefs->changed = FALSE; + prefs->locked = FALSE; + prefs->isRoot = (geteuid() == 0); + + return (SCPreferencesRef)prefs; +} + + +__private_extern__ SCPreferencesRef +__SCPreferencesCreate(CFAllocatorRef allocator, + CFStringRef name, + CFStringRef prefsID, + Boolean perUser, + CFStringRef user) +{ + int fd = -1; + SCPreferencesRef prefs; + SCPreferencesPrivateRef prefsPrivate; + int sc_status = kSCStatusOK; + struct stat statBuf; + CFMutableDataRef xmlData; + CFStringRef xmlError; + + /* + * allocate and initialize a new session + */ + prefs = __SCPreferencesCreatePrivate(allocator); + if (!prefs) { + return NULL; + } + prefsPrivate = (SCPreferencesPrivateRef)prefs; /* * convert prefsID to path */ - newSession->path = _SCPPrefsPath(prefsID, perUser, user); - if (newSession->path == NULL) { - scp_status = SCP_FAILED; + prefsPrivate->path = __SCPreferencesPath(NULL, prefsID, perUser, user); + if (prefsPrivate->path == NULL) { + sc_status = kSCStatusFailed; goto error; } /* * open file */ - fd = open(newSession->path, O_RDONLY, 0644); + fd = open(prefsPrivate->path, O_RDONLY, 0644); if (fd == -1) { - char *errmsg = strerror(errno); - switch (errno) { case ENOENT : - if (options & kSCPOpenCreatePrefs) { - bzero(&statBuf, sizeof(statBuf)); - goto create_1; - } - scp_status = SCP_ENOENT; - break; + /* no prefs file, start fresh */ + bzero(&statBuf, sizeof(statBuf)); + goto create_1; case EACCES : - scp_status = SCP_EACCESS; + sc_status = kSCStatusAccessError; break; default : - scp_status = SCP_FAILED; + sc_status = kSCStatusFailed; + break; } - SCDLog(LOG_DEBUG, CFSTR("open() failed: %s"), errmsg); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("open() failed: %s"), strerror(errno)); goto error; } @@ -100,14 +198,14 @@ _SCPOpen(SCPSessionRef *session, * check file, create signature */ if (fstat(fd, &statBuf) == -1) { - SCDLog(LOG_DEBUG, CFSTR("fstat() failed: %s"), strerror(errno)); - scp_status = SCP_FAILED; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("fstat() failed: %s"), strerror(errno)); + sc_status = kSCStatusFailed; goto error; } create_1 : - newSession->signature = _SCPSignatureFromStatbuf(&statBuf); + prefsPrivate->signature = __SCPSignatureFromStatbuf(&statBuf); if (statBuf.st_size > 0) { /* @@ -116,46 +214,42 @@ _SCPOpen(SCPSessionRef *session, xmlData = CFDataCreateMutable(NULL, statBuf.st_size); CFDataSetLength(xmlData, statBuf.st_size); if (read(fd, (void *)CFDataGetBytePtr(xmlData), statBuf.st_size) != statBuf.st_size) { - SCDLog(LOG_DEBUG, CFSTR("_SCPOpen read(): could not load preference data.")); + /* corrupt prefs file, start fresh */ + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen read(): could not load preference data.")); CFRelease(xmlData); xmlData = NULL; - if (options & kSCPOpenCreatePrefs) { - goto create_2; - } - scp_status = SCP_BADCF; - goto error; + goto create_2; } /* * load preferences */ - newSession->prefs = (CFMutableDictionaryRef) + prefsPrivate->prefs = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData(NULL, xmlData, kCFPropertyListMutableContainers, &xmlError); CFRelease(xmlData); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %s"), xmlError); - if (options & kSCPOpenCreatePrefs) { - goto create_2; + if (!prefsPrivate->prefs) { + /* corrupt prefs file, start fresh */ + if (xmlError) { + SCLog(_sc_verbose, LOG_DEBUG, + CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %@"), + xmlError); + CFRelease(xmlError); } - scp_status = SCP_BADCF; - goto error; + goto create_2; } /* * make sure that we've got a dictionary */ - if (CFGetTypeID(newSession->prefs) != CFDictionaryGetTypeID()) { - SCDLog(LOG_DEBUG, CFSTR("_SCPOpen CFGetTypeID(): not a dictionary.")); - CFRelease(newSession->prefs); - newSession->prefs = NULL; - if (options & kSCPOpenCreatePrefs) { - goto create_2; - } - scp_status = SCP_BADCF; - goto error; + if (CFGetTypeID(prefsPrivate->prefs) != CFDictionaryGetTypeID()) { + /* corrupt prefs file, start fresh */ + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen CFGetTypeID(): not a dictionary.")); + CFRelease(prefsPrivate->prefs); + prefsPrivate->prefs = NULL; + goto create_2; } } @@ -166,58 +260,71 @@ _SCPOpen(SCPSessionRef *session, fd = -1; } - if (newSession->prefs == NULL) { + if (prefsPrivate->prefs == NULL) { /* * new file, create empty preferences */ - SCDLog(LOG_DEBUG, CFSTR("_SCPOpen(): creating new dictionary.")); - newSession->prefs = CFDictionaryCreateMutable(NULL, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - newSession->changed = TRUE; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen(): creating new dictionary.")); + prefsPrivate->prefs = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + prefsPrivate->changed = TRUE; } /* * all OK */ - newSession->name = CFRetain(name); + prefsPrivate->name = CFRetain(name); if (prefsID) { - newSession->prefsID = CFRetain(prefsID); + prefsPrivate->prefsID = CFRetain(prefsID); } - newSession->perUser = perUser; + prefsPrivate->perUser = perUser; if (user) { - newSession->user = CFRetain(user); + prefsPrivate->user = CFRetain(user); } - *session = (SCPSessionRef)newSession; - return SCP_OK; + return prefs; error : if (fd != -1) { - (void)close(fd); + (void) close(fd); } - (void) SCPClose((SCPSessionRef *)&newSession); - return scp_status; + CFRelease(prefs); + _SCErrorSet(sc_status); + return NULL; } -SCPStatus -SCPOpen(SCPSessionRef *session, - CFStringRef name, - CFStringRef prefsID, - int options) +SCPreferencesRef +SCPreferencesCreate(CFAllocatorRef allocator, + CFStringRef name, + CFStringRef prefsID) { - return _SCPOpen(session, name, prefsID, FALSE, NULL, options); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesCreate:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" name = %@"), name); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" prefsID = %@"), prefsID); + + return __SCPreferencesCreate(allocator, name, prefsID, FALSE, NULL); } -SCPStatus -SCPUserOpen(SCPSessionRef *session, - CFStringRef name, - CFStringRef prefsID, - CFStringRef user, - int options) +SCPreferencesRef +SCUserPreferencesCreate(CFAllocatorRef allocator, + CFStringRef name, + CFStringRef prefsID, + CFStringRef user) { - return _SCPOpen(session, name, prefsID, TRUE, user, options); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCUserPreferencesCreate:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" name = %@"), name); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" prefsID = %@"), prefsID); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" user = %@"), user); + + return __SCPreferencesCreate(allocator, name, prefsID, TRUE, user); +} + + +CFTypeID +SCPreferencesGetTypeID(void) { + return __kSCPreferencesTypeID; } diff --git a/SystemConfiguration.fproj/SCPPath.c b/SystemConfiguration.fproj/SCPPath.c index aee9cf8..ea2c3f4 100644 --- a/SystemConfiguration.fproj/SCPPath.c +++ b/SystemConfiguration.fproj/SCPPath.c @@ -20,11 +20,18 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include -#include "SCPPrivate.h" -#include -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 16, 2000 Allan Nathanson + * - initial revision + */ + +#include +#include static CFArrayRef normalizePath(CFStringRef path) @@ -64,34 +71,30 @@ normalizePath(CFStringRef path) } -static SCPStatus -getPath(SCPSessionRef session, CFStringRef path, CFMutableDictionaryRef *entity) +static int +getPath(SCPreferencesRef session, CFStringRef path, CFMutableDictionaryRef *entity) { CFArrayRef elements; CFIndex i; CFIndex nElements; - SCPStatus status; + int status = kSCStatusFailed; CFMutableDictionaryRef value = NULL; - if (session == NULL) { - return SCP_NOSESSION; /* you can't do anything with a closed session */ - } - elements = normalizePath(path); if (elements == NULL) { - return SCP_NOKEY; + return kSCStatusNoKey; } /* get preferences key */ - status = SCPGet(session, - CFArrayGetValueAtIndex(elements, 0), - (CFPropertyListRef *)&value); - if (status != SCP_OK) { + value = (CFMutableDictionaryRef)SCPreferencesGetValue(session, + CFArrayGetValueAtIndex(elements, 0)); + if (!value) { + status = kSCStatusNoKey; goto done; } if (CFGetTypeID(value) != CFDictionaryGetTypeID()) { - status = SCP_NOKEY; + status = kSCStatusNoKey; goto done; } @@ -103,19 +106,19 @@ getPath(SCPSessionRef session, CFStringRef path, CFMutableDictionaryRef *entity) value = (CFMutableDictionaryRef)CFDictionaryGetValue(value, element); if (value == NULL) { /* if (parent) path component does not exist */ - status = SCP_NOKEY; + status = kSCStatusNoKey; goto done; } if (CFGetTypeID(value) != CFDictionaryGetTypeID()) { - status = SCP_NOKEY; + status = kSCStatusNoKey; goto done; } } *entity = value; - status = SCP_OK; + status = kSCStatusOK; done : @@ -124,27 +127,25 @@ getPath(SCPSessionRef session, CFStringRef path, CFMutableDictionaryRef *entity) } -SCPStatus -SCPPathCreateUniqueChild(SCPSessionRef session, - CFStringRef prefix, - CFStringRef *newPath) +CFStringRef +SCPreferencesPathCreateUniqueChild(SCPreferencesRef session, + CFStringRef prefix) { - SCPStatus status; + int status; CFMutableDictionaryRef value; - boolean_t newValue = FALSE; + CFStringRef newPath = NULL; + Boolean newValue = FALSE; CFIndex i; - CFStringRef path; - CFMutableDictionaryRef newDict; + CFMutableDictionaryRef newDict = NULL; - if (session == NULL) { - return SCP_NOSESSION; /* you can't do anything with a closed session */ - } + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathCreateUniqueChild:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" prefix = %@"), prefix); status = getPath(session, prefix, &value); switch (status) { - case SCP_OK : + case kSCStatusOK : break; - case SCP_NOKEY : + case kSCStatusNoKey : value = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, @@ -152,19 +153,19 @@ SCPPathCreateUniqueChild(SCPSessionRef session, newValue = TRUE; break; default : - return status; + return NULL; } if (CFGetTypeID(value) != CFDictionaryGetTypeID()) { /* if specified path is not a dictionary */ - status = SCP_NOKEY; - goto done; + status = kSCStatusNoKey; + goto error; } if (CFDictionaryContainsKey(value, kSCResvLink)) { /* the path is a link... */ - status = SCP_FAILED; - goto done; + status = kSCStatusFailed; + goto error; } i = 0; @@ -178,11 +179,11 @@ SCPPathCreateUniqueChild(SCPSessionRef session, if (!found) { /* if we've identified the next unique key */ - path = CFStringCreateWithFormat(NULL, - NULL, - CFSTR("%@/%i"), - prefix, - i); + newPath = CFStringCreateWithFormat(NULL, + NULL, + CFSTR("%@/%i"), + prefix, + i); break; } i++; @@ -193,38 +194,38 @@ SCPPathCreateUniqueChild(SCPSessionRef session, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - status = SCPPathSetValue(session, path, newDict); - CFRelease(newDict); - if (status != SCP_OK) { - CFRelease(path); - goto done; + if (!SCPreferencesPathSetValue(session, newPath, newDict)) { + goto error; } + CFRelease(newDict); - *newPath = path; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" child = %@"), newPath); + if (newValue) CFRelease(value); + return newPath; - done : + error : + if (newDict) CFRelease(newDict); if (newValue) CFRelease(value); - return status; + if (newPath) CFRelease(newPath); + return NULL; } -SCPStatus -SCPPathGetValue(SCPSessionRef session, - CFStringRef path, - CFDictionaryRef *value) +CFDictionaryRef +SCPreferencesPathGetValue(SCPreferencesRef session, + CFStringRef path) { - SCPStatus status; + int status; CFMutableDictionaryRef entity; CFStringRef entityLink; - if (session == NULL) { - return SCP_NOSESSION; /* you can't do anything with a closed session */ - } + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathGetValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" path = %@"), path); status = getPath(session, path, &entity); - if (status != SCP_OK) { - return status; + if (status != kSCStatusOK) { + return NULL; } /* XXXX Add code here to chase multiple links XXXXX */ @@ -233,71 +234,71 @@ SCPPathGetValue(SCPSessionRef session, (CFDictionaryGetValueIfPresent(entity, kSCResvLink, (void **)&entityLink))) { /* if this is a dictionary AND it is a link */ status = getPath(session, entityLink, &entity); - if (status != SCP_OK) { + if (status != kSCStatusOK) { /* if it was a bad link */ - return status; + return NULL; } } - *value = entity; - return status; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), entity); + return entity; } -SCPStatus -SCPPathGetLink(SCPSessionRef session, - CFStringRef path, - CFStringRef *link) +CFStringRef +SCPreferencesPathGetLink(SCPreferencesRef session, + CFStringRef path) { - SCPStatus status; + int status; CFMutableDictionaryRef entity; CFStringRef entityLink; - if (session == NULL) { - return SCP_NOSESSION; /* you can't do anything with a closed session */ - } + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathGetLink:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" path = %@"), path); status = getPath(session, path, &entity); - if (status != SCP_OK) { - return status; + if (status != kSCStatusOK) { + return NULL; } if ((CFGetTypeID(entity) == CFDictionaryGetTypeID()) && (CFDictionaryGetValueIfPresent(entity, kSCResvLink, (void **)&entityLink))) { /* if this is a dictionary AND it is a link */ - *link = entityLink; - return status; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" link = %@"), entityLink); + return entityLink; } - return SCP_NOKEY; + return NULL; } -SCPStatus -SCPPathSetValue(SCPSessionRef session, CFStringRef path, CFDictionaryRef value) +Boolean +SCPreferencesPathSetValue(SCPreferencesRef session, + CFStringRef path, + CFDictionaryRef value) { CFMutableDictionaryRef element; CFArrayRef elements = NULL; CFIndex i; CFIndex nElements; - boolean_t newRoot = FALSE; + Boolean newRoot = FALSE; + Boolean ok; CFMutableDictionaryRef root = NULL; - SCPStatus status = SCP_NOKEY; - if (session == NULL) { - return SCP_NOSESSION; /* you can't do anything with a closed session */ - } + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathSetValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" path = %@"), path); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); elements = normalizePath(path); if (elements == NULL) { - return SCP_NOKEY; + _SCErrorSet(kSCStatusNoKey); + return FALSE; } /* get preferences key */ - status = SCPGet(session, - CFArrayGetValueAtIndex(elements, 0), - (CFPropertyListRef *)&root); - if (status != SCP_OK) { + root = (CFMutableDictionaryRef)SCPreferencesGetValue(session, + CFArrayGetValueAtIndex(elements, 0)); + if (!root) { root = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, @@ -339,67 +340,68 @@ SCPPathSetValue(SCPSessionRef session, CFStringRef path, CFDictionaryRef value) CFArrayGetValueAtIndex(elements, nElements-1), value); } - status = SCPSet(session, CFArrayGetValueAtIndex(elements, 0), root); - + ok = SCPreferencesSetValue(session, CFArrayGetValueAtIndex(elements, 0), root); if (newRoot) CFRelease(root); CFRelease(elements); - return status; + return ok; } -SCPStatus -SCPPathSetLink(SCPSessionRef session, CFStringRef path, CFStringRef link) +Boolean +SCPreferencesPathSetLink(SCPreferencesRef session, + CFStringRef path, + CFStringRef link) { CFMutableDictionaryRef dict; - SCPStatus status; + Boolean ok; - if (session == NULL) { - return SCP_NOSESSION; /* you can't do anything with a closed session */ - } + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathSetLink:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" path = %@"), path); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" link = %@"), link); dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(dict, kSCResvLink, link); - status = SCPPathSetValue(session, path, dict); + ok = SCPreferencesPathSetValue(session, path, dict); CFRelease(dict); - return status; + return ok; } -SCPStatus -SCPPathRemove(SCPSessionRef session, CFStringRef path) +Boolean +SCPreferencesPathRemoveValue(SCPreferencesRef session, + CFStringRef path) { CFMutableDictionaryRef element; CFArrayRef elements = NULL; CFIndex i; CFIndex nElements; + Boolean ok = FALSE; CFMutableDictionaryRef root = NULL; - SCPStatus status = SCP_NOKEY; - if (session == NULL) { - return SCP_NOSESSION; /* you can't do anything with a closed session */ - } + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathRemoveValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" path = %@"), path); elements = normalizePath(path); if (elements == NULL) { - return SCP_NOKEY; + _SCErrorSet(kSCStatusNoKey); + return FALSE; } /* get preferences key */ - status = SCPGet(session, - CFArrayGetValueAtIndex(elements, 0), - (CFPropertyListRef *)&root); - if (status != SCP_OK) { + root = (CFMutableDictionaryRef)SCPreferencesGetValue(session, + CFArrayGetValueAtIndex(elements, 0)); + if (!root) { goto done; } nElements = CFArrayGetCount(elements); if (nElements == 1) { /* if we are removing the data associated with the preference key */ - status = SCPRemove(session, CFArrayGetValueAtIndex(elements, 0)); + ok = SCPreferencesRemoveValue(session, CFArrayGetValueAtIndex(elements, 0)); goto done; } @@ -411,7 +413,6 @@ SCPPathRemove(SCPSessionRef session, CFStringRef path) pathComponent = CFArrayGetValueAtIndex(elements, i); tmpElement = (void *)CFDictionaryGetValue(element, pathComponent); if (tmpElement == NULL) { - status = SCP_NOKEY; goto done; } element = tmpElement; @@ -419,10 +420,10 @@ SCPPathRemove(SCPSessionRef session, CFStringRef path) CFDictionaryRemoveValue(element, CFArrayGetValueAtIndex(elements, nElements-1)); - status = SCPSet(session, CFArrayGetValueAtIndex(elements, 0), root); + ok = SCPreferencesSetValue(session, CFArrayGetValueAtIndex(elements, 0), root); done : CFRelease(elements); - return status; + return ok; } diff --git a/SystemConfiguration.fproj/SCPPath.h b/SystemConfiguration.fproj/SCPPath.h index f400518..8febc65 100644 --- a/SystemConfiguration.fproj/SCPPath.h +++ b/SystemConfiguration.fproj/SCPPath.h @@ -23,153 +23,15 @@ #ifndef _SCPPATH_H #define _SCPPATH_H -#include -#include - -/*! - @header SCPPath.h - The SystemConfiguration framework provides access to the data used - to configure a running system. - - Specifically, the SCPPathXXX() API's allow an application to - load and store XML configuration data in a controlled - manner and provides the necessary notifications to other - applications which need to be aware of configuration - changes. - - The SCPPathXXX() API's make certain assumptions about the layout - of the preferences data. These APIs view the data as a - collection of dictionaries of key/value pairs and an - associated path name. The root path ("/") identifies - the top-level dictionary. Additional path components - specify the keys for sub-dictionaries. - - For example, the following dictionary can be access via - two paths. The root ("/") path would return a property - list with all keys and values. The path "/path1" would - only return the dictionary with the "key3" and "key4" - properties. - - - key1 - val1 - key2 - val2 - path1 - - key3 - val3 - key4 - val4 - - - - The APIs provided by this framework communicate with the "configd" - daemon for any tasks requiring synchronization and/or - notification. - */ - - -__BEGIN_DECLS - -/*! - @function SCPPathCreateUniqueChild - @discussion Creates a new path component within the dictionary - hierarchy. - @param session Pass the SCPSessionRef handle which should be used to - communicate with the APIs. - @param prefix Pass a string which represents the parent path. - @param newPath A pointer to memory which will be filled with an - string representing the new child path. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_NOKEY. - */ -SCPStatus SCPPathCreateUniqueChild (SCPSessionRef session, - CFStringRef prefix, - CFStringRef *newPath); - -/*! - @function SCPPathGetValue - @discussion Returns the dictionary associated with the specified - path. - @param session Pass the SCPSessionRef handle which should be used to - communicate with the APIs. - @param path Pass a string whcih represents the path to be returned. - @param value A pointer to memory which will be filled with an - dictionary associated with the specified path. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_NOKEY. - */ -SCPStatus SCPPathGetValue (SCPSessionRef session, - CFStringRef path, - CFDictionaryRef *value); - -/*! - @function SCPPathGetLink - @discussion Returns the link (if one exists) associatd with the - specified path. - @param session Pass the SCPSessionRef handle which should be used to - communicate with the APIs. - @param path Pass a string whcih represents the path to be returned. - @param link A pointer to memory which will be filled with a - string reflecting the link found at the specified path. - If no link was present at the specified path a status - value of SCP_NOKEY will be returned. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_NOKEY. - */ -SCPStatus SCPPathGetLink (SCPSessionRef session, - CFStringRef path, - CFStringRef *link); - -/*! - @function SCPPathSetValue - @discussion Associates a dictionary with the specified path. - @param session Pass the SCPSessionRef handle which should be used to - communicate with the APIs. - @param path Pass a string whcih represents the path to be returned. - @param value Pass a dictionary which represents the data to be - stored at the specified path. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK. - */ -SCPStatus SCPPathSetValue (SCPSessionRef session, - CFStringRef path, - CFDictionaryRef value); - -/*! - @function SCPPathSetLink - @discussion Associates a link to a second dictionary at the - specified path. - @param session Pass the SCPSessionRef handle which should be used to - communicate with the APIs. - @param path Pass a string whcih represents the path to be returned. - @param value Pass a string which represents the path to be stored - at the specified path. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_NOKEY. - */ -SCPStatus SCPPathSetLink (SCPSessionRef session, - CFStringRef path, - CFStringRef link); - -/*! - @function SCPPathRemove - @discussion Removes the data associated with the specified path. - @param session Pass the SCPSessionRef handle which should be used to - communicate with the APIs. - @param path Pass a string whcih represents the path to be returned. - @result A constant of type SCPStatus indicating the success (or - failure) of the call. Possible return values include: SCP_OK, - SCP_NOKEY. - */ -SCPStatus SCPPathRemove (SCPSessionRef session, - CFStringRef path); - -__END_DECLS +#ifndef _SYSTEMCONFIGURATION_H +#warning Your code has directly included the (old) +#warning header file. Please dont do that. Use the top-level header file: +#warning +#warning +#warning +#warning Note: the configuration preference APIs have been moved out of the +#warning SCPPath.h header file. +#include /* ...and try to keep everyone happy */ +#endif #endif /* _SCPPATH_H */ diff --git a/SystemConfiguration.fproj/SCPRemove.c b/SystemConfiguration.fproj/SCPRemove.c index a861973..8532004 100644 --- a/SystemConfiguration.fproj/SCPRemove.c +++ b/SystemConfiguration.fproj/SCPRemove.c @@ -20,31 +20,36 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include "SCPPrivate.h" - -#include - -#include -#include -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ +#include +#include +#include "SCPreferencesInternal.h" -SCPStatus -SCPRemove(SCPSessionRef session, CFStringRef key) +Boolean +SCPreferencesRemoveValue(SCPreferencesRef session, CFStringRef key) { - SCPSessionPrivateRef sessionPrivate; + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; - if (session == NULL) { - return SCP_FAILED; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCPSessionPrivateRef)session; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesRemoveValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + + sessionPrivate->accessed = TRUE; if (!CFDictionaryContainsKey(sessionPrivate->prefs, key)) { - return SCP_NOKEY; + _SCErrorSet(kSCStatusNoKey); + return FALSE; } CFDictionaryRemoveValue(sessionPrivate->prefs, key); - sessionPrivate->changed = TRUE; - return SCP_OK; + sessionPrivate->changed = TRUE; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCPSet.c b/SystemConfiguration.fproj/SCPSet.c index 6b875ae..28d5df5 100644 --- a/SystemConfiguration.fproj/SCPSet.c +++ b/SystemConfiguration.fproj/SCPSet.c @@ -20,27 +20,31 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include "SCPPrivate.h" - -#include - -#include -#include -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ +#include +#include +#include "SCPreferencesInternal.h" -SCPStatus -SCPSet(SCPSessionRef session, CFStringRef key, CFPropertyListRef data) +Boolean +SCPreferencesSetValue(SCPreferencesRef session, CFStringRef key, CFPropertyListRef value) { - SCPSessionPrivateRef sessionPrivate; + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; - if (session == NULL) { - return SCP_FAILED; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCPSessionPrivateRef)session; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesSetValue:")); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); - CFDictionarySetValue(sessionPrivate->prefs, key, data); - sessionPrivate->changed = TRUE; - return SCP_OK; + CFDictionarySetValue(sessionPrivate->prefs, key, value); + sessionPrivate->accessed = TRUE; + sessionPrivate->changed = TRUE; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCPUnlock.c b/SystemConfiguration.fproj/SCPUnlock.c index 4d808a8..112a459 100644 --- a/SystemConfiguration.fproj/SCPUnlock.c +++ b/SystemConfiguration.fproj/SCPUnlock.c @@ -20,44 +20,45 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include "SCPPrivate.h" - -#include - -#include -#include -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ +#include +#include +#include "SCPreferencesInternal.h" -SCPStatus -SCPUnlock(SCPSessionRef session) +Boolean +SCPreferencesUnlock(SCPreferencesRef session) { - SCPSessionPrivateRef sessionPrivate; - SCDStatus scd_status; + SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; - if (session == NULL) { - return SCP_FAILED; /* you can't do anything with a closed session */ - } - sessionPrivate = (SCPSessionPrivateRef)session; + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesUnlock:")); if (!sessionPrivate->locked) { - return SCP_NEEDLOCK; /* sorry, you don't have the lock */ + /* sorry, you don't have the lock */ + _SCErrorSet(kSCStatusNeedLock); + return FALSE; } if (!sessionPrivate->isRoot) { /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */ - goto notRoot; + goto perUser; } - scd_status = SCDRemove(sessionPrivate->session, sessionPrivate->sessionKeyLock); - if (scd_status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDRemove() failed: %s"), SCDError(scd_status)); - return SCP_FAILED; + if (!SCDynamicStoreRemoveValue(sessionPrivate->session, sessionPrivate->sessionKeyLock)) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreRemoveValue() failed")); + return FALSE; } - notRoot: + perUser: sessionPrivate->locked = FALSE; - return SCP_OK; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCPreferences.h b/SystemConfiguration.fproj/SCPreferences.h new file mode 100644 index 0000000..854ed87 --- /dev/null +++ b/SystemConfiguration.fproj/SCPreferences.h @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCPREFERENCES_H +#define _SCPREFERENCES_H + + +#include +#include +#include + + +/*! + @header SCPreferences + The SCPreferencesXXX() APIs allow an application to load and + store XML configuration data in a controlled manner and provide + the necessary notifications to other applications that need to + be aware of configuration changes. + + The stored XML configuration data is accessed using a prefsID. A + NULL value indicates that the default system preferences are to + be accessed. + A string which starts with a leading "/" character specifies the + path to the file containing te preferences to be accessed. + A string which does not start with a leading "/" character + specifies a file relative to the default system preferences + directory. + + The APIs provided by this framework communicate with the "configd" + daemon for any tasks requiring synchronization and/or notification. + */ + + +/*! + @typedef SCPreferencesRef + @discussion This is the handle to an open "session" for + accessing system configuration preferences. + */ +typedef const struct __SCPreferences * SCPreferencesRef; + + +__BEGIN_DECLS + +/*! + @function SCPreferencesGetTypeID + Returns the type identifier of all SCPreferences instances. + */ +CFTypeID +SCPreferencesGetTypeID (void); + + +/*! + @function SCPreferencesCreate + @discussion Initiates access to the per-system set of configuration + preferences. + @param allocator ... + @param name A string that describes the name of the calling + process. + @param prefsID A string that identifies the name of the + group of preferences to be accessed/updated. + @result prefs A pointer to memory that will be filled with an + SCPreferencesRef handle to be used for all subsequent requests. + If a session cannot be established, the contents of + memory pointed to by this parameter are undefined. + */ +SCPreferencesRef +SCPreferencesCreate ( + CFAllocatorRef allocator, + CFStringRef name, + CFStringRef prefsID + ); + +/*! + @function SCPreferencesLock + @discussion Locks access to the configuration preferences. + + This function obtains exclusive access to the configuration + preferences associated with this prefsID. Clients attempting + to obtain exclusive access to the preferences will either receive + an kSCStatusPrefsBusy error or block waiting for the lock to be + released. + @param session An SCPreferencesRef handle that should be used for + all API calls. + @param wait A boolean flag indicating whether the calling process + should block waiting for another process to complete its update + operation and release its lock. + @result TRUE if the lock was obtained; FALSE if an error occurred. + + XXXXX: old API error codes included kSCStatusPrefsBusy, kSCStatusAccessError, and kSCStatusStale + */ +Boolean +SCPreferencesLock ( + SCPreferencesRef session, + Boolean wait + ); + +/*! + @function SCPreferencesCommitChanges + @discussion Commits changes made to the configuration preferences to + persitent storage. + + This function commits any changes to permanent storage. An + implicit call to SCPreferencesLock/SCPreferencesUnlock will + be made if exclusive access has not already been established. + @param session An SCPreferencesRef handle that should be used for + all API calls. + @result TRUE if the lock was obtained; FALSE if an error occurred. + + XXXXX: old API error codes included kSCStatusAccessError, kSCStatusStale + */ +Boolean +SCPreferencesCommitChanges ( + SCPreferencesRef session + ); + +/*! + @function SCPreferencesApplyChanges + @discussion Requests that the currently stored configuration + preferences be applied to the active configuration. + @param session An SCPreferencesRef handle that should be used for + all API calls. + @result TRUE if the lock was obtained; FALSE if an error occurred. + */ +Boolean +SCPreferencesApplyChanges ( + SCPreferencesRef session + ); + +/*! + @function SCPreferencesUnlock + @discussion Releases exclusive access to the configuration preferences. + + This function releases the exclusive access "lock" for this prefsID. + Other clients will be now be able to establish exclusive access to + the preferences. + @param session An SCPreferencesRef handle that should be used for + all API calls. + @result TRUE if the lock was obtained; FALSE if an error occurred. + */ +Boolean +SCPreferencesUnlock ( + SCPreferencesRef session + ); + +/*! + @function SCPreferencesGetSignature + @discussion Returns a sequence of bytes that can be used to determine + if the saved configuration preferences have changed. + @param session An SCPreferencesRef handle that should be used for + all API calls. + @param signature A pointer to a CFDataRef that will reflect + the signature of the configuration preferences at the time + of the call to SCPreferencesCreate(). + @result A CFDataRef that reflects the signature of the configuration + preferences at the time of the call to SCPreferencesCreate(). + */ +CFDataRef +SCPreferencesGetSignature ( + SCPreferencesRef session + ); + +/*! + @function SCPreferencesCopyKeyList + @discussion Returns an array of currently defined preference keys. + @param session An SCPreferencesRef handle that should be used for + all API calls. + @result The list of keys. You must release the returned value. + */ +CFArrayRef +SCPreferencesCopyKeyList ( + SCPreferencesRef session + ); + +/*! + @function SCPreferencesGetValue + @discussion Returns the data associated with a preference key. + + This function retrieves data associated with a key for the prefsID. + + Note: You could read stale data and not know it, unless you + first call SCPreferencesLock(). + @param session An SCPreferencesRef handle that should be used for + all API calls. + @param key The preference key to be returned. + @result The value associated with the specified preference key; If no + value was located, NULL is returned. + */ +CFPropertyListRef +SCPreferencesGetValue ( + SCPreferencesRef session, + CFStringRef key + ); + +/*! + @function SCPreferencesAddValue + @discussion Adds data for a preference key. + + This function associates new data with the specified key. In order + to commit these changes to permanent storage a call must be made to + SCPreferencesCommitChanges(). + @param session The SCPreferencesRef handle that should be used to + communicate with the APIs. + @param key The preference key to be updated. + @param value The CFPropertyListRef object containing the + value to be associated with the specified preference key. + @result TRUE if the value was added; FALSE if the key already exists or + if an error occurred. + */ +Boolean +SCPreferencesAddValue ( + SCPreferencesRef session, + CFStringRef key, + CFPropertyListRef value + ); + +/*! + @function SCPreferencesSetValue + @discussion Updates the data associated with a preference key. + + This function adds or replaces the value associated with the + specified key. In order to commit these changes to permanent + storage a call must be made to SCPreferencesCommitChanges(). + @param session The SCPreferencesRef handle that should be used to + communicate with the APIs. + @param key The preference key to be updated. + @param value The CFPropertyListRef object containing the + data to be associated with the specified preference key. + @result TRUE if the value was set; FALSE if an error occurred. + */ +Boolean +SCPreferencesSetValue ( + SCPreferencesRef session, + CFStringRef key, + CFPropertyListRef value + ); + +/*! + @function SCPreferencesRemoveValue + @discussion Removes the data associated with a preference key. + + This function removes the data associated with the specified + key. In order to commit these changes to permanent storage a + call must be made to SCPreferencesCommitChanges(). + @param session The SCPreferencesRef handle that should be used to + communicate with the APIs. + @param key The preference key to be removed. + @result TRUE if the value was removed; FALSE if the key did not exist or + if an error occurred. + */ +Boolean +SCPreferencesRemoveValue ( + SCPreferencesRef session, + CFStringRef key + ); + +__END_DECLS + +#endif /* _SCPREFERENCES_H */ diff --git a/SystemConfiguration.fproj/SCPPrivate.h b/SystemConfiguration.fproj/SCPreferencesInternal.h similarity index 59% rename from SystemConfiguration.fproj/SCPPrivate.h rename to SystemConfiguration.fproj/SCPreferencesInternal.h index 707279c..82e3aa3 100644 --- a/SystemConfiguration.fproj/SCPPrivate.h +++ b/SystemConfiguration.fproj/SCPreferencesInternal.h @@ -20,15 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ -#ifndef _SCPPRIVATE_H -#define _SCPPRIVATE_H - -#include -#include +#ifndef _SCPREFERENCESINTERNAL_H +#define _SCPREFERENCESINTERNAL_H #include #include #include +#include +#include +#include +#include #define PREFS_DEFAULT_DIR CFSTR("/var/db/SystemConfiguration") @@ -39,6 +40,10 @@ /* Define the per-preference-handle structure */ typedef struct { + + /* base CFType information */ + CFRuntimeBase cfBase; + /* session name */ CFStringRef name; @@ -46,7 +51,7 @@ typedef struct { CFStringRef prefsID; /* per-user preference info */ - boolean_t perUser; + Boolean perUser; CFStringRef user; /* configuration file path */ @@ -56,7 +61,7 @@ typedef struct { CFDataRef signature; /* configd session */ - SCDSessionRef session; + SCDynamicStoreRef session; /* configd session keys */ CFStringRef sessionKeyLock; @@ -67,35 +72,48 @@ typedef struct { CFMutableDictionaryRef prefs; /* flags */ - boolean_t changed; - boolean_t locked; - boolean_t isRoot; + Boolean accessed; + Boolean changed; + Boolean locked; + Boolean isRoot; -} SCPSessionPrivate, *SCPSessionPrivateRef; +} SCPreferencesPrivate, *SCPreferencesPrivateRef; /* Define signature data */ typedef struct { - dev_t st_dev; /* inode's device */ - ino_t st_ino; /* inode's number */ - struct timespec st_mtimespec; /* time of last data modification */ - off_t st_size; /* file size, in bytes */ + dev_t st_dev; /* inode's device */ + ino_t st_ino; /* inode's number */ + struct timespec st_mtimespec; /* time of last data modification */ + off_t st_size; /* file size, in bytes */ } SCPSignatureData, *SCPSignatureDataRef; __BEGIN_DECLS -CFDataRef _SCPSignatureFromStatbuf (const struct stat *statBuf); - -char * _SCPPrefsPath (CFStringRef prefsID, - boolean_t perUser, - CFStringRef user); - -CFStringRef _SCPNotificationKey (CFStringRef prefsID, - boolean_t perUser, - CFStringRef user, - int keyType); +SCPreferencesRef +__SCPreferencesCreate (CFAllocatorRef allocator, + CFStringRef name, + CFStringRef prefsID, + Boolean perUser, + CFStringRef user); + +CFDataRef +__SCPSignatureFromStatbuf (const struct stat *statBuf); + +char * +__SCPreferencesPath (CFAllocatorRef allocator, + CFStringRef prefsID, + Boolean perUser, + CFStringRef user); + +CFStringRef +_SCPNotificationKey (CFAllocatorRef allocator, + CFStringRef prefsID, + Boolean perUser, + CFStringRef user, + int keyType); __END_DECLS -#endif /* _SCPPRIVATE_H */ +#endif /* _SCPREFERENCESINTERNAL_H */ diff --git a/SystemConfiguration.fproj/SCPreferencesPath.h b/SystemConfiguration.fproj/SCPreferencesPath.h new file mode 100644 index 0000000..3cf71dd --- /dev/null +++ b/SystemConfiguration.fproj/SCPreferencesPath.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCPREFERENCESPATH_H +#define _SCPREFERENCESPATH_H + +#include +#include +#include + + +/*! + @header SCPreferencesPath + The SCPreferencesPathXXX() APIs allow an application to + load and store XML configuration data in a controlled + manner and provide the necessary notifications to other + applications that need to be aware of configuration + changes. + + The SCPreferencesPathXXX() APIs make certain assumptions + about the layout of the preferences data. These APIs view + the data as a collection of dictionaries of key/value pairs + and an associated path name. The root path ("/") identifies + the top-level dictionary. Additional path components + specify the keys for sub-dictionaries. + + For example, the following dictionary can be accessed via + two paths. The root ("/") path would return a dictionary + with all keys and values. The path "/path1" would only + return the dictionary with the "key3" and "key4" properties. + +
+	
<dict> +
<key>key1</key> +
<string>val1</string> +
<key>key2</key> +
<string>val2</string> +
<key>path1</key> +
<dict> +
<key>key3</key> +
<string>val3</string> +
<key>key4</key> +
<string>val4</string> +
</dict> +
</dict> +
+ + Each dictionary can also include the kSCResvLink key. The + value associated with this key is interpreted as a "link" to + another path. If this key is present, a call to the + SCPreferencesPathGetValue() API will return the dictionary + specified by the link. + + The APIs provided by this framework communicate with the "configd" + daemon for any tasks requiring synchronization and/or notification. + */ + + +__BEGIN_DECLS + +/*! + @function SCPreferencesPathCreateUniqueChild + @discussion Creates a new path component within the dictionary + hierarchy. + @param session The SCPreferencesRef handle that should be used to + communicate with the APIs. + @param prefix A string that represents the parent path. + @param newPath A pointer to memory that will be filled with a + string representing the new child path. + @result A string representing the new (unique) child path; NULL + if the specified path does not exist. + */ +CFStringRef +SCPreferencesPathCreateUniqueChild ( + SCPreferencesRef session, + CFStringRef prefix + ); + +/*! + @function SCPreferencesPathGetValue + @discussion Returns the dictionary associated with the specified + path. + @param session The SCPreferencesRef handle that should be used to + communicate with the APIs. + @param path A string that represents the path to be returned. + @result The dictionary associated with the specified path; NULL + if the path does not exist. + */ +CFDictionaryRef +SCPreferencesPathGetValue ( + SCPreferencesRef session, + CFStringRef path + ); + +/*! + @function SCPreferencesPathGetLink + @discussion Returns the link (if one exists) associated with the + specified path. + @param session The SCPreferencesRef handle that should be used to + communicate with the APIs. + @param path A string that represents the path to be returned. + @result The dictionary associated with the specified path; NULL + if the path is not a link or does not exist. + */ +CFStringRef +SCPreferencesPathGetLink ( + SCPreferencesRef session, + CFStringRef path + ); + +/*! + @function SCPreferencesPathSetValue + @discussion Associates a dictionary with the specified path. + @param session The SCPreferencesRef handle that should be used to + communicate with the APIs. + @param path A string that represents the path to be updated. + @param value A dictionary that represents the data to be + stored at the specified path. + @result A boolean indicating the success (or failure) of the call. + */ +Boolean +SCPreferencesPathSetValue ( + SCPreferencesRef session, + CFStringRef path, + CFDictionaryRef value + ); + +/*! + @function SCPreferencesPathSetLink + @discussion Associates a link to a second dictionary at the + specified path. + @param session The SCPreferencesRef handle that should be used to + communicate with the APIs. + @param path A string that represents the path to be updated. + @param link A string that represents the link to be stored + at the specified path. + @result A boolean indicating the success (or failure) of the call. + */ +Boolean +SCPreferencesPathSetLink ( + SCPreferencesRef session, + CFStringRef path, + CFStringRef link + ); + +/*! + @function SCPreferencesPathRemoveValue + @discussion Removes the data associated with the specified path. + @param session The SCPreferencesRef handle that should be used to + communicate with the APIs. + @param path A string that represents the path to be returned. + @result A boolean indicating the success (or failure) of the call. + */ +Boolean +SCPreferencesPathRemoveValue ( + SCPreferencesRef session, + CFStringRef path + ); + +__END_DECLS + +#endif /* _SCPREFERENCESPATH_H */ diff --git a/SystemConfiguration.fproj/SCPreferencesPrivate.h b/SystemConfiguration.fproj/SCPreferencesPrivate.h new file mode 100644 index 0000000..5ee8c21 --- /dev/null +++ b/SystemConfiguration.fproj/SCPreferencesPrivate.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCPREFERENCESPRIVATE_H +#define _SCPREFERENCESPRIVATE_H + +#include +#include + + +/*! + @enum SCPreferencesKeyType + @discussion Used with the SCDynamicStoreKeyCreatePreferences() function + to describe the resulting CFStringRef argument. + @constant kSCPreferencesKeyLock Key used when exclusive access to the + stored preferences is obtained or released. + @constant kSCPreferencesKeyCommit Key used when new preferences are + committed to the store + @constant kSCPreferencesKeyApply Key used when new preferences are + to be applied to the active system configuration. + */ +typedef enum { + kSCPreferencesKeyLock = 1, + kSCPreferencesKeyCommit = 2, + kSCPreferencesKeyApply = 3, +} SCPreferencesKeyType; + + +__BEGIN_DECLS + +/*! + @function SCDynamicStoreKeyCreatePreferences + @discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys() + function to receive notifications of changes to the saved + preferences. + @param allocator ... + @param prefsID A string that identifies the name of the + group of preferences to be accessed/updated. + @param keyType A kSCPreferencesKeyType indicating the type a notification + key to be returned. + @result A notification string for the specified preference identifier. + */ +CFStringRef +SCDynamicStoreKeyCreatePreferences (CFAllocatorRef allocator, + CFStringRef prefsID, + int keyType); + +SCPreferencesRef +SCUserPreferencesCreate (CFAllocatorRef allocator, + CFStringRef name, + CFStringRef prefsID, + CFStringRef user); + +CFStringRef +SCDynamicStoreKeyCreateUserPreferences (CFAllocatorRef allocator, + CFStringRef prefsID, + CFStringRef user, + int keyType); + +__END_DECLS + +#endif /* _SCPREFERENCESPRIVATE_H */ diff --git a/SystemConfiguration.fproj/SCPreferencesSetSpecific.h b/SystemConfiguration.fproj/SCPreferencesSetSpecific.h new file mode 100644 index 0000000..a0a6b3d --- /dev/null +++ b/SystemConfiguration.fproj/SCPreferencesSetSpecific.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCPREFERENCESSETSPECIFIC_H +#define _SCPREFERENCESSETSPECIFIC_H + +#include +#include +#include + + +/*! + @header SCPreferencesSetSpecific + The following APIs allow an application to set specific + configuration information about the current system (e.g. the + computer/sharing name). + */ + + +__BEGIN_DECLS + +/*! + @function SCPreferencesSetComputerName + @discussion Updates the computer/host name in the system preferences. + + Note: In order to commit these changes to permanent storage a call + must be made to SCPreferencesCommitChanges(). + @param prefs An SCPreferencesRef that should be used for all API calls. + @param name The computer/host name to be set. + @param nameEncoding The encoding associated with the computer/host name. + @result A boolean indicating the success (or failure) of the call. + */ +Boolean +SCPreferencesSetComputerName ( + SCPreferencesRef prefs, + CFStringRef name, + CFStringEncoding nameEncoding + ); + +__END_DECLS + +#endif /* _SCPREFERENCESSETSPECIFIC_H */ diff --git a/SystemConfiguration.fproj/SCPrivate.h b/SystemConfiguration.fproj/SCPrivate.h new file mode 100644 index 0000000..57f2e62 --- /dev/null +++ b/SystemConfiguration.fproj/SCPrivate.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCPRIVATE_H +#define _SCPRIVATE_H + +#include + +#include + +#include +#include + +#include + +/* framework variables */ +extern Boolean _sc_debug; /* TRUE if debugging enabled */ +extern Boolean _sc_verbose; /* TRUE if verbose logging enabled */ +extern Boolean _sc_log; /* TRUE if SCLog() output goes to syslog */ + +__BEGIN_DECLS + +/*! + @function _SCErrorSet + @discussion Returns a last SystemConfiguration.framework API error code. + @result The last error encountered. + */ +void _SCErrorSet (int error); + +/* + @function SCLog + @discussion Conditionally issue a log message. + @param condition A boolean value indicating if the message should be logged + @param level A syslog(3) logging priority. + @param formatString The format string + @result The specified message will be written to the system message + logger (See syslogd(8)). + */ +void SCLog (Boolean condition, + int level, + CFStringRef formatString, + ...); + +/* + @function SCPrint + @discussion Conditionally issue a debug message. + @param condition A boolean value indicating if the message should be written + @param stream The output stream for the log message. + @param formatString The format string + @result The specified message will be written to the specified output + stream. + */ +void SCPrint (Boolean condition, + FILE *stream, + CFStringRef formatString, + ...); + +__END_DECLS + +#endif /* _SCPRIVATE_H */ diff --git a/SystemConfiguration.fproj/SCProxies.c b/SystemConfiguration.fproj/SCProxies.c new file mode 100644 index 0000000..d31c826 --- /dev/null +++ b/SystemConfiguration.fproj/SCProxies.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Modification History + * + * May 18, 2001 Allan Nathanson + * - initial revision + */ + +#include +#include +#include + +CFStringRef +SCDynamicStoreKeyCreateProxies(CFAllocatorRef allocator) +{ + return SCDynamicStoreKeyCreateNetworkGlobalEntity(allocator, + kSCDynamicStoreDomainState, + kSCEntNetProxies); +} + + +CFDictionaryRef +SCDynamicStoreCopyProxies(SCDynamicStoreRef store) +{ + CFDictionaryRef dict = NULL; + CFStringRef key; + SCDynamicStoreRef mySession = store; + CFDictionaryRef proxies = NULL; + + if (!store) { + mySession = SCDynamicStoreCreate(NULL, + CFSTR("SCDynamicStoreCopyConsoleUser"), + NULL, + NULL); + if (!mySession) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + return NULL; + } + } + + key = SCDynamicStoreKeyCreateProxies(NULL); + dict = SCDynamicStoreCopyValue(mySession, key); + CFRelease(key); + if (!isA_CFDictionary(dict)) { + _SCErrorSet(kSCStatusNoKey); + goto done; + } + + proxies = CFRetain(dict); + + done : + + if (!store && mySession) CFRelease(mySession); + if (dict) CFRelease(dict); + return proxies; +} diff --git a/SystemConfiguration.fproj/SCValidation.h b/SystemConfiguration.fproj/SCValidation.h new file mode 100644 index 0000000..09f1aaf --- /dev/null +++ b/SystemConfiguration.fproj/SCValidation.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCVALIDATION_H +#define _SCVALIDATION_H + +#include +#include + +__BEGIN_DECLS + +static __inline__ CFTypeRef +isA_CFType(CFTypeRef obj, CFTypeID type) +{ + if (obj == NULL) + return (NULL); + + if (CFGetTypeID(obj) != type) + return (NULL); + + return (obj); +} + +static __inline__ CFTypeRef +isA_CFArray(CFTypeRef obj) +{ + return (isA_CFType(obj, CFArrayGetTypeID())); +} + +static __inline__ CFTypeRef +isA_CFBoolean(CFTypeRef obj) +{ + return (isA_CFType(obj, CFBooleanGetTypeID())); +} + +static __inline__ CFTypeRef +isA_CFData(CFTypeRef obj) +{ + return (isA_CFType(obj, CFDataGetTypeID())); +} + +static __inline__ CFTypeRef +isA_CFDate(CFTypeRef obj) +{ + return (isA_CFType(obj, CFDateGetTypeID())); +} + +static __inline__ CFTypeRef +isA_CFDictionary(CFTypeRef obj) +{ + return (isA_CFType(obj, CFDictionaryGetTypeID())); +} + +static __inline__ CFTypeRef +isA_CFNumber(CFTypeRef obj) +{ + return (isA_CFType(obj, CFNumberGetTypeID())); +} + +static __inline__ CFTypeRef +isA_CFPropertyList(CFTypeRef obj) +{ + CFTypeID type; + + if (obj == NULL) + return (NULL); + + type = CFGetTypeID(obj); + if (type == CFArrayGetTypeID() || + type == CFBooleanGetTypeID() || + type == CFDataGetTypeID() || + type == CFDateGetTypeID() || + type == CFDictionaryGetTypeID() || + type == CFNumberGetTypeID() || + type == CFStringGetTypeID()) + return (obj); + + return (NULL); +} + + +static __inline__ CFTypeRef +isA_CFString(CFTypeRef obj) +{ + return (isA_CFType(obj, CFStringGetTypeID())); +} + +__END_DECLS + +#endif /* _SCVALIDATION_H */ + diff --git a/SystemConfiguration.fproj/SystemConfiguration.h b/SystemConfiguration.fproj/SystemConfiguration.h index 9d4ef22..13b8503 100644 --- a/SystemConfiguration.fproj/SystemConfiguration.h +++ b/SystemConfiguration.fproj/SystemConfiguration.h @@ -23,32 +23,122 @@ #ifndef _SYSTEMCONFIGURATION_H #define _SYSTEMCONFIGURATION_H +#include +#include + + /*! @header SystemConfiguration.h - The SystemConfiguration framework provides access to the data used to configure a running system. The APIs provided by this framework communicate with the "configd" daemon. + The SystemConfiguration framework provides access to the + data used to configure a running system. The APIs provided + by this framework communicate with the "configd" daemon. -The "configd" daemon manages a "cache" reflecting the desired configuration settings as well as the current state of the system. The daemon provides a notification mechanism for user-level processes which need to be aware of changes made to the "cache" data. Lastly, the daemon loads a number of bundles(or plug-ins) which monitor low-level kernel events and, via a set of policy modules, keep this cached data up to date. + The "configd" daemon manages a "dynamic store" reflecting the + desired configuration settings as well as the current state + of the system. The daemon provides a notification mechanism + for user-level processes which need to be aware of changes + made to the data. Lastly, the daemon loads a number of + bundles (or plug-ins) that monitor low-level kernel events + and, via a set of policy modules, keep the state data up + to date. + */ -The "configd" daemon also provides an address space/task/process which can be used by other CFRunLoop based functions which would otherwise require their own process/daemon for execution. +/*! + @enum + @discussion Returned status codes. + + @constant kSCStatusOK Success + @constant kSCStatusFailed Non-specific Failure + @constant kSCStatusInvalidArgument Invalid argument + @constant kSCStatusAccessError Permission denied + @constant kSCStatusNoKey No such key + @constant kSCStatusKeyExists Data associated with key already defined + @constant kSCStatusLocked Lock already held + @constant kSCStatusNeedLock Lock required for this operation + + @constant kSCStatusNoStoreSession Configuration daemon session not active + @constant kSCStatusNoStoreServer Configuration daemon not (no longer) available + @constant kSCStatusNotifierActive Notifier is currently active + + @constant kSCStatusNoPrefsSession Preference session not active + @constant kSCStatusPrefsBusy Preferences update currently in progress + @constant kSCStatusNoConfigFile Configuration file not found + @constant kSCStatusNoLink No such link + @constant kSCStatusStale Write attempted on stale version of object + + @constant kSCStatusReachabilityUnknown + A determination could not be made regarding the reachability + of the specified nodename/address. +*/ +enum { + /* + * Generic status codes + */ + kSCStatusOK = 0, /* Success */ + kSCStatusFailed = 1001, /* Non-specific failure */ + kSCStatusInvalidArgument = 1002, /* Invalid argument */ + kSCStatusAccessError = 1003, /* Permission denied + - must be root to obtain lock + - could not create access/create preferences + */ + kSCStatusNoKey = 1004, /* No such key */ + kSCStatusKeyExists = 1005, /* Key already defined */ + kSCStatusLocked = 1006, /* Lock already held */ + kSCStatusNeedLock = 1007, /* Lock required for this operation */ + /* + * SCDynamicStore status codes + */ + kSCStatusNoStoreSession = 2001, /* Configuration daemon session not active */ + kSCStatusNoStoreServer = 2002, /* Configuration daemon not (no longer) available */ + kSCStatusNotifierActive = 2003, /* Notifier is currently active */ + /* + * SCPreferences status codes + */ + kSCStatusNoPrefsSession = 3001, /* Preference session not active */ + kSCStatusPrefsBusy = 3002, /* Preferences update currently in progress */ + kSCStatusNoConfigFile = 3003, /* Configuration file not found */ + kSCStatusNoLink = 3004, /* No such link */ + kSCStatusStale = 3005, /* Write attempted on stale version of object */ + /* + * SCNetwork status codes + */ + kSCStatusReachabilityUnknown = 4001, /* Network reachability cannot be determined */ +}; - */ -/* cache access APIs */ -#include -#include +/* store access APIs */ +#include +#include +#include /* preference access APIs */ -#include -#include #include +#include -/* "console user" APIs */ -#include - -/* "computer/host name" APIs */ -#include +/* store and preference scheme definitions */ +#include /* "network reachability" APIs */ #include +__BEGIN_DECLS + +/*! + @function SCError + @discussion Returns a last SystemConfiguration.framework API error code. + @result The last error encountered. + */ +int SCError (); + +/*! + @function SCErrorString + @discussion Returns a pointer to the error message string associated + with the specified status. + @param status The SCDynamicStoreStatus to be returned. + @result The error message string. + */ +const char * SCErrorString (int status); + +__END_DECLS + #endif /* _SYSTEMCONFIGURATION_H */ diff --git a/SystemConfiguration.fproj/config.defs b/SystemConfiguration.fproj/config.defs index 7449dea..af98b56 100644 --- a/SystemConfiguration.fproj/config.defs +++ b/SystemConfiguration.fproj/config.defs @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include @@ -73,12 +83,12 @@ routine configunlock ( server : mach_port_t; skip; /* reserved for future use */ /* - * Cache access API's + * Dynamic store access API's */ routine configlist ( server : mach_port_t; xmlData : xmlData; - regexOptions : int; + isRegex : int; out list : xmlDataOut, dealloc; out status : int); @@ -115,9 +125,21 @@ routine configadd_s ( server : mach_port_t; out newInstance : int; out status : int); - skip; /* reserved for future use */ - skip; /* reserved for future use */ - skip; /* reserved for future use */ +routine confignotify ( server : mach_port_t; + key : xmlData; + out status : int); + +routine configget_m ( server : mach_port_t; + keys : xmlData; + patterns : xmlData; + out data : xmlDataOut, dealloc; + out status : int); + +routine configset_m ( server : mach_port_t; + data : xmlData; + remove : xmlData; + notify : xmlData; + out status : int); /* * Notification API's @@ -125,12 +147,12 @@ routine configadd_s ( server : mach_port_t; routine notifyadd ( server : mach_port_t; key : xmlData; - regexOptions : int; + isRegex : int; out status : int); routine notifyremove ( server : mach_port_t; key : xmlData; - regexOptions : int; + isRegex : int; out status : int); routine notifychanges ( server : mach_port_t; diff --git a/SystemConfiguration.fproj/genSCPreferences.c b/SystemConfiguration.fproj/genSCPreferences.c index 78bc8e4..c4eb32f 100644 --- a/SystemConfiguration.fproj/genSCPreferences.c +++ b/SystemConfiguration.fproj/genSCPreferences.c @@ -29,8 +29,15 @@ /* * Modification History - * 3 Nov 2000 Dieter Siegmund (dieter@apple) - * - created + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * 27 Apr 2001 Allan Nathanson (ajn@apple.com) + * - switch from "extern const CFStringRef ..." to "#define ..." + * + * 3 Nov 2000 Dieter Siegmund (dieter@apple) + * - created */ #include #include @@ -61,68 +68,90 @@ char copyright_string[] = " */\n"; -#define REGULAR 0 -#define COMMENT 1 -#define END 2 - -#define STRING_MACRO_NAME "STRING_DECL" - -#define KEY_PREFIX "kSC" - -#define CACHE "Cache" -#define COMP "Comp" -#define PREF "Pref" -#define PROP "Prop" -#define PATH "Path" -#define NETENT "EntNet" -#define NETPROP "PropNet" -#define NETVAL "ValNet" -#define SETUPENT "EntSetup" -#define SETUPPROP "PropSetup" -#define SYSTEMENT "EntSystem" -#define SYSTEMPROP "PropSystem" -#define RESV "Resv" -#define USERSENT "EntUsers" -#define USERSPROP "PropUsers" - -#define CFNUMBER "CFNumber" -#define CFSTRING "CFString" -#define CFNUMBER_BOOL "CFNumber (0 or 1)" -#define CFARRAY_CFSTRING "CFArray[CFString]" +typedef enum { + COMMENT, + OBSOLETE, + REGULAR, + DEFINE , + FUTURE, + END +} controlType; + +#define KEY_PREFIX "kSC" + +#define COMP "Comp" +#define DYNAMICSTORE "DynamicStore" +#define PREF "Pref" +#define PROP "Prop" +#define PATH "Path" +#define NETENT "EntNet" +#define NETPROP "PropNet" +#define NETVAL "ValNet" +#define SETUPENT "EntSetup" +#define SETUPPROP "PropSetup" +#define SYSTEMENT "EntSystem" +#define SYSTEMPROP "PropSystem" +#define RESV "Resv" +#define USERSENT "EntUsers" +#define USERSPROP "PropUsers" +#define VERSION "Version" + +#define CFARRAY_CFNUMBER "CFArray[CFNumber]" +#define CFARRAY_CFSTRING "CFArray[CFString]" +#define CFBOOLEAN "CFBoolean" +#define CFDICTIONARY "CFDictionary" +#define CFNUMBER "CFNumber" +#define CFNUMBER_BOOL "CFNumber (0 or 1)" +#define CFSTRING "CFString" #define ACTIVE "Active" #define ADDRESSES "Addresses" #define AIRPORT "AirPort" #define ALERT "Alert" +#define ALTERNATEREMOTEADDRESS "AlternateRemoteAddress" #define ANYREGEX "AnyRegex" -#define AUTOMATIC "Automatic" #define APPLETALK "AppleTalk" #define AUTH "Auth" +#define AUTOMATIC "Automatic" #define BINDINGMETHODS "BindingMethods" #define BOOTP "BOOTP" #define BROADCAST "Broadcast" #define BROADCASTADDRESSES "BroadcastAddresses" #define BROADCASTSERVERTAG "BroadcastServerTag" +#define CHAP "CHAP" #define COMM "Comm" -#define COMPONENTSEPARATOR "ComponentSeparator" +#define COMPRESSIONACFIELD "CompressionACField" +#define COMPRESSIONPFIELD "CompressionPField" +#define COMPRESSIONVJ "CompressionVJ" #define COMPUTERNAME "ComputerName" #define CONFIGMETHOD "ConfigMethod" +#define CONNECTDELAY "ConnectDelay" +#define CONNECTIONSCRIPT "ConnectionScript" #define CONSOLEUSER "ConsoleUser" #define CURRENTSET "CurrentSet" +#define DATACOMPRESSION "DataCompression" #define DEFAULTSERVERTAG "DefaultServerTag" #define DEFAULTZONE "DefaultZone" #define DESTADDRESSES "DestAddresses" +#define DEVICENAME "DeviceName" #define DHCP "DHCP" #define DHCPCLIENTID "DHCPClientID" -#define DEVICENAME "DeviceName" #define DIALMODE "DialMode" +#define DIALONDEMAND "DialOnDemand" +#define DISCONNECTONIDLE "DisconnectOnIdle" +#define DISCONNECTONIDLETIMER "DisconnectOnIdleTimer" +#define DISCONNECTONLOGOUT "DisconnectOnLogout" +#define DISPLAYTERMINALWINDOW "DisplayTerminalWindow" #define DNS "DNS" #define DOMAIN "Domain" #define DOMAINNAME "DomainName" #define DOMAINSEPARATOR "DomainSeparator" -#define DUPLEX "Duplex" +#define ECHOENABLED "EchoEnabled" +#define ECHOFAILURE "EchoFailure" +#define ECHOINTERVAL "EchoInterval" #define ENCODING "Encoding" #define ENCRYPTION "Encryption" +#define ERRORCORRECTION "ErrorCorrection" #define ETHERNET "Ethernet" #define EXCEPTIONSLIST "ExceptionsList" #define FILE "File" @@ -139,10 +168,16 @@ char copyright_string[] = #define HTTPENABLE "HTTPEnable" #define HTTPPORT "HTTPPort" #define HTTPPROXY "HTTPProxy" +#define HTTPSENABLE "HTTPSEnable" +#define HTTPSPORT "HTTPSPort" +#define HTTPSPROXY "HTTPSProxy" +#define IDLEREMINDER "IdleReminder" +#define IDLEREMINDERTIMER "IdleReminderTimer" +#define IGNOREDIALTONE "IgnoreDialTone" #define INACTIVE "Inactive" -#define INCLUDEPRIVATENETS "IncludePrivateNets" #define INFORM "INFORM" #define INTERFACE "Interface" +#define INTERFACENAME "InterfaceName" #define INTERFACES "Interfaces" #define IPCP "IPCP" #define IPV4 "IPv4" @@ -150,29 +185,41 @@ char copyright_string[] = #define LASTUPDATED "LastUpdated" #define LCP "LCP" #define LINK "Link" +#define LOGFILE "Logfile" #define MACADDRESS "MACAddress" #define MANUAL "Manual" #define MEDIA "Media" #define MODEM "Modem" +#define MRU "MRU" +#define MTU "MTU" #define NAME "Name" #define NETINFO "NetInfo" #define NETWORK "Network" -#define NETWORKSERVICES "NetworkServices" #define NETWORKID "NetworkID" +#define NETWORKSERVICES "NetworkServices" #define NIS "NIS" #define NODE "Node" #define NODEID "NodeID" +#define PAP "PAP" #define PASSWORD "Password" #define PLUGIN "Plugin" -#define PORTNAME "PortName" +#define POWERENABLED "PowerEnabled" #define PPP "PPP" #define PPPOE "PPPoE" -#define PPPSERIAL "PPPSerial" #define PPPOVERRIDEPRIMARY "PPPOverridePrimary" +#define PPPSERIAL "PPPSerial" +#define PREFERREDNETWORK "PreferredNetwork" #define PREFS "Prefs" #define PRIMARYINTERFACE "PrimaryInterface" +#define PRIMARYSERVICE "PrimaryService" #define PROTOCOL "Protocol" #define PROXIES "Proxies" +#define PULSEDIAL "PulseDial" +#define RECEIVEACCM "ReceiveACCM" +#define REDIALCOUNT "RedialCount" +#define REDIALENABLED "RedialEnabled" +#define REDIALINTERVAL "RedialInterval" +#define REMOTEADDRESS "RemoteAddress" #define ROOTSEPARATOR "RootSeparator" #define ROUTER "Router" #define RTSPENABLE "RTSPEnable" @@ -182,26 +229,32 @@ char copyright_string[] = #define SEEDNETWORKRANGE "SeedNetworkRange" #define SEEDROUTER "SeedRouter" #define SEEDZONES "SeedZones" -#define SERVICE "Service" #define SERVERADDRESSES "ServerAddresses" #define SERVERTAGS "ServerTags" -#define SERVICEORDER "ServiceOrder" +#define SERVICE "Service" #define SERVICEIDS "ServiceIDs" +#define SERVICEORDER "ServiceOrder" +#define SESSIONTIMER "SessionTimer" #define SETS "Sets" #define SETUP "Setup" -#define SPEED "Speed" -#define STATE "State" #define SOCKSENABLE "SOCKSEnable" #define SOCKSPORT "SOCKSPort" #define SOCKSPROXY "SOCKSProxy" +#define SORTLIST "SortList" +#define SPEAKER "Speaker" +#define SPEED "Speed" +#define STATE "State" #define SUBNETMASKS "SubnetMasks" #define SUBTYPE "SubType" #define SYSTEM "System" +#define TERMINALSCRIPT "TerminalScript" +#define TRANSMITACCM "TransmitACCM" #define TYPE "Type" #define UID "UID" -#define USERS "Users" #define USERDEFINEDNAME "UserDefinedName" +#define USERS "Users" #define VERBOSELOGGING "VerboseLogging" +#define WAITFORDIALTONE "WaitForDialTone" struct { int control; @@ -216,16 +269,17 @@ struct { { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/*\n * Generic Keys\n */", NULL }, + { DEFINE , PROP, INTERFACENAME, NULL, CFSTRING }, { REGULAR, PROP, MACADDRESS, NULL, CFSTRING }, { REGULAR, PROP, USERDEFINEDNAME, NULL, CFSTRING }, + { DEFINE , PROP, VERSION, NULL, CFSTRING }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/*\n * Preference Keys\n */", NULL }, - { REGULAR, PREF, CURRENTSET, NULL, NULL }, - { REGULAR, PREF, HARDWARE, NULL, NULL }, - { REGULAR, PREF, NETWORKSERVICES, NULL, NULL }, - { REGULAR, PREF, SETS, NULL, NULL }, - { REGULAR, PREF, SYSTEM, NULL, NULL }, + { REGULAR, PREF, CURRENTSET, NULL, CFSTRING }, + { REGULAR, PREF, NETWORKSERVICES, NULL, CFDICTIONARY }, + { REGULAR, PREF, SETS, NULL, CFDICTIONARY }, + { REGULAR, PREF, SYSTEM, NULL, CFDICTIONARY }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/*\n * Component Keys\n */", NULL }, @@ -234,7 +288,7 @@ struct { { REGULAR, COMP, GLOBAL, NULL, NULL }, { REGULAR, COMP, INTERFACE, NULL, NULL }, { REGULAR, COMP, SYSTEM, NULL, NULL }, - { REGULAR, COMP, USERS, "users", NULL }, /* FIX ME! */ + { REGULAR, COMP, USERS, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/*\n * Regex key which matches any component\n */", NULL }, @@ -242,42 +296,43 @@ struct { { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/*\n * Network Entity Keys\n */", NULL }, - { REGULAR, NETENT, AIRPORT, NULL, NULL }, - { REGULAR, NETENT, APPLETALK, NULL, NULL }, - { REGULAR, NETENT, DNS, NULL, NULL }, - { REGULAR, NETENT, ETHERNET, NULL, NULL }, - { REGULAR, NETENT, INTERFACE, NULL, NULL }, - { REGULAR, NETENT, IPV4, NULL, NULL }, - { REGULAR, NETENT, IPV6, NULL, NULL }, - { REGULAR, NETENT, LINK, NULL, NULL }, - { REGULAR, NETENT, MODEM, NULL, NULL }, - { REGULAR, NETENT, NETINFO, NULL, NULL }, - { REGULAR, NETENT, NIS, NULL, NULL }, - { REGULAR, NETENT, PPP, NULL, NULL }, - { REGULAR, NETENT, PPPOE, NULL, NULL }, - { REGULAR, NETENT, PROXIES, NULL, NULL }, - { COMMENT, "", NULL, NULL, NULL }, - - { COMMENT, "/*\n * " NETWORK " Properties\n */", NULL }, + { REGULAR, NETENT, AIRPORT, NULL, CFDICTIONARY }, + { REGULAR, NETENT, APPLETALK, NULL, CFDICTIONARY }, + { DEFINE , NETENT, DHCP, NULL, CFDICTIONARY }, + { REGULAR, NETENT, DNS, NULL, CFDICTIONARY }, + { REGULAR, NETENT, ETHERNET, NULL, CFDICTIONARY }, + { REGULAR, NETENT, INTERFACE, NULL, CFDICTIONARY }, + { REGULAR, NETENT, IPV4, NULL, CFDICTIONARY }, + { REGULAR, NETENT, IPV6, NULL, CFDICTIONARY }, + { REGULAR, NETENT, LINK, NULL, CFDICTIONARY }, + { REGULAR, NETENT, MODEM, NULL, CFDICTIONARY }, + { REGULAR, NETENT, NETINFO, NULL, CFDICTIONARY }, + { FUTURE , NETENT, NIS, NULL, CFDICTIONARY }, + { REGULAR, NETENT, PPP, NULL, CFDICTIONARY }, + { REGULAR, NETENT, PPPOE, NULL, CFDICTIONARY }, + { REGULAR, NETENT, PROXIES, NULL, CFDICTIONARY }, + { COMMENT, "", NULL, NULL, NULL }, + + { COMMENT, "/*\n * " KEY_PREFIX COMP NETWORK " Properties\n */", NULL }, { REGULAR, NETPROP, SERVICEORDER, NULL, CFARRAY_CFSTRING }, { REGULAR, NETPROP, PPPOVERRIDEPRIMARY, NULL, CFNUMBER_BOOL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " AIRPORT " (Hardware) Entity Keys\n */", NULL, NULL, NULL }, - { REGULAR, NETPROP AIRPORT, "PowerEnabled", NULL, CFNUMBER_BOOL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT AIRPORT " (Hardware) Entity Keys\n */", NULL, NULL, NULL }, + { REGULAR, NETPROP AIRPORT, POWERENABLED, NULL, CFNUMBER_BOOL }, { REGULAR, NETPROP AIRPORT, AUTH PASSWORD, NULL, CFSTRING }, { REGULAR, NETPROP AIRPORT, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING }, - { REGULAR, NETPROP AIRPORT, "PreferredNetwork", NULL, CFSTRING }, + { REGULAR, NETPROP AIRPORT, PREFERREDNETWORK, NULL, CFSTRING }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " APPLETALK " Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT APPLETALK " Entity Keys\n */", NULL, NULL, NULL }, { REGULAR, NETPROP APPLETALK, COMPUTERNAME, NULL, CFSTRING }, { REGULAR, NETPROP APPLETALK, COMPUTERNAME ENCODING, NULL, CFNUMBER }, { REGULAR, NETPROP APPLETALK, CONFIGMETHOD, NULL, CFSTRING }, { REGULAR, NETPROP APPLETALK, DEFAULTZONE, NULL, CFSTRING }, { REGULAR, NETPROP APPLETALK, NETWORKID, NULL, CFNUMBER }, { REGULAR, NETPROP APPLETALK, NODEID, NULL, CFNUMBER }, - { REGULAR, NETPROP APPLETALK, SEEDNETWORKRANGE, NULL, CFARRAY_CFSTRING }, + { REGULAR, NETPROP APPLETALK, SEEDNETWORKRANGE, NULL, CFARRAY_CFNUMBER }, { REGULAR, NETPROP APPLETALK, SEEDZONES, NULL, CFARRAY_CFSTRING }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/* " KEY_PREFIX NETPROP APPLETALK CONFIGMETHOD " values */", NULL, NULL, NULL }, @@ -286,16 +341,17 @@ struct { { REGULAR, NETVAL APPLETALK CONFIGMETHOD, SEEDROUTER, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " DNS " Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT DNS " Entity Keys\n */", NULL, NULL, NULL }, { REGULAR, NETPROP DNS, DOMAINNAME, NULL, CFSTRING }, { REGULAR, NETPROP DNS, SEARCHDOMAINS, NULL, CFARRAY_CFSTRING}, { REGULAR, NETPROP DNS, SERVERADDRESSES, NULL, CFARRAY_CFSTRING }, + { DEFINE , NETPROP DNS, SORTLIST, NULL, CFARRAY_CFSTRING }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " ETHERNET " (Hardware) Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT ETHERNET " (Hardware) Entity Keys\n */", NULL, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " INTERFACE " Entity Keys\n */", NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT INTERFACE " Entity Keys\n */", NULL }, { REGULAR, NETPROP INTERFACE, DEVICENAME, NULL, CFSTRING }, { REGULAR, NETPROP INTERFACE, HARDWARE, NULL, CFSTRING }, { REGULAR, NETPROP INTERFACE, TYPE, NULL, CFSTRING }, @@ -310,7 +366,7 @@ struct { { REGULAR, NETVAL INTERFACE SUBTYPE, PPPSERIAL, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " IPV4 " Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT IPV4 " Entity Keys\n */", NULL, NULL, NULL }, { REGULAR, NETPROP IPV4, ADDRESSES, NULL, CFARRAY_CFSTRING }, { REGULAR, NETPROP IPV4, CONFIGMETHOD, NULL, CFSTRING }, { REGULAR, NETPROP IPV4, DHCPCLIENTID, NULL, CFSTRING }, @@ -327,28 +383,31 @@ struct { { REGULAR, NETVAL IPV4 CONFIGMETHOD, PPP, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " IPV6 " Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT IPV6 " Entity Keys\n */", NULL, NULL, NULL }, { REGULAR, NETPROP IPV6, ADDRESSES, NULL, CFARRAY_CFSTRING }, { REGULAR, NETPROP IPV6, CONFIGMETHOD, NULL, CFSTRING }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " LINK " Entity Keys\n */", NULL, NULL, NULL }, - { REGULAR, NETPROP LINK, ACTIVE, NULL, CFNUMBER_BOOL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT LINK " Entity Keys\n */", NULL, NULL, NULL }, + { REGULAR, NETPROP LINK, ACTIVE, NULL, CFBOOLEAN }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " MODEM " (Hardware) Entity Keys\n */", NULL, NULL, NULL }, - { REGULAR, NETPROP MODEM, "ConnectionScript", NULL, CFSTRING }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT MODEM " (Hardware) Entity Keys\n */", NULL, NULL, NULL }, + { REGULAR, NETPROP MODEM, CONNECTIONSCRIPT, NULL, CFSTRING }, + { DEFINE , NETPROP MODEM, DATACOMPRESSION, NULL, CFNUMBER_BOOL }, { REGULAR, NETPROP MODEM, DIALMODE, NULL, CFSTRING }, - { REGULAR, NETPROP MODEM, "PulseDial", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP MODEM, "Speaker", NULL, CFNUMBER_BOOL }, + { DEFINE , NETPROP MODEM, ERRORCORRECTION, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP MODEM, PULSEDIAL, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP MODEM, SPEAKER, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP MODEM, SPEED, NULL, CFNUMBER }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/* " KEY_PREFIX NETPROP MODEM DIALMODE " values */", NULL, NULL, NULL }, - { REGULAR, NETVAL MODEM DIALMODE, "IgnoreDialTone", NULL, NULL }, + { REGULAR, NETVAL MODEM DIALMODE, IGNOREDIALTONE, NULL, NULL }, { REGULAR, NETVAL MODEM DIALMODE, MANUAL, NULL, NULL }, - { REGULAR, NETVAL MODEM DIALMODE, "WaitForDialTone", NULL, NULL }, + { REGULAR, NETVAL MODEM DIALMODE, WAITFORDIALTONE, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " NETINFO " Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT NETINFO " Entity Keys\n */", NULL, NULL, NULL }, { REGULAR, NETPROP NETINFO, BINDINGMETHODS, NULL, CFSTRING }, { REGULAR, NETPROP NETINFO, SERVERADDRESSES, NULL, CFARRAY_CFSTRING }, { REGULAR, NETPROP NETINFO, SERVERTAGS, NULL, CFARRAY_CFSTRING }, @@ -363,18 +422,19 @@ struct { { REGULAR, NETVAL NETINFO, DEFAULTSERVERTAG, "network", NULL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " NIS " Entity Keys\n */", NULL, NULL, NULL }, - { REGULAR, NETPROP NIS, DOMAINNAME, NULL, CFSTRING }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT NIS " Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " PPP " Entity Keys\n */", NULL, NULL, NULL }, - { REGULAR, NETPROP PPP, "DialOnDemand", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, "DisconnectOnIdle", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, "DisconnectOnIdleTimer", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, "DisconnectOnLogout", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, "IdleReminderTimer", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, "IdleReminder", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, "Logfile", NULL, CFSTRING }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT PPP " Entity Keys\n */", NULL, NULL, NULL }, + { REGULAR, NETPROP PPP, DIALONDEMAND, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP PPP, DISCONNECTONIDLE, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP PPP, DISCONNECTONIDLETIMER, NULL, CFNUMBER }, + { REGULAR, NETPROP PPP, DISCONNECTONLOGOUT, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP PPP, IDLEREMINDERTIMER, NULL, CFNUMBER }, + { REGULAR, NETPROP PPP, IDLEREMINDER, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP PPP, LOGFILE, NULL, CFSTRING }, + { DEFINE , NETPROP PPP, SESSIONTIMER, NULL, CFNUMBER }, { REGULAR, NETPROP PPP, VERBOSELOGGING, NULL, CFNUMBER_BOOL }, { COMMENT, "", NULL, NULL, NULL }, @@ -385,43 +445,43 @@ struct { { REGULAR, NETPROP PPP, AUTH PROTOCOL, NULL, CFARRAY_CFSTRING }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/* " KEY_PREFIX NETPROP PPP AUTH PROTOCOL " values */", NULL, NULL, NULL }, - { REGULAR, NETVAL PPP AUTH PROTOCOL, "CHAP", NULL, CFSTRING }, - { REGULAR, NETVAL PPP AUTH PROTOCOL, "PAP", NULL, CFSTRING }, + { REGULAR, NETVAL PPP AUTH PROTOCOL, CHAP, NULL, CFSTRING }, + { REGULAR, NETVAL PPP AUTH PROTOCOL, PAP, NULL, CFSTRING }, { COMMENT, "\n/* " COMM ": */", NULL, NULL, NULL }, - { REGULAR, NETPROP PPP, COMM "AlternateRemoteAddress", NULL, CFSTRING }, - { REGULAR, NETPROP PPP, COMM "ConnectDelay", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, COMM "DisplayTerminalWindow", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, COMM "RedialCount", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, COMM "RedialEnabled", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, COMM "RedialInterval", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, COMM "RemoteAddress", NULL, CFSTRING }, - { REGULAR, NETPROP PPP, COMM "TerminalScript", NULL, CFSTRING }, + { REGULAR, NETPROP PPP, COMM ALTERNATEREMOTEADDRESS, NULL, CFSTRING }, + { REGULAR, NETPROP PPP, COMM CONNECTDELAY, NULL, CFNUMBER }, + { REGULAR, NETPROP PPP, COMM DISPLAYTERMINALWINDOW, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP PPP, COMM REDIALCOUNT, NULL, CFNUMBER }, + { REGULAR, NETPROP PPP, COMM REDIALENABLED, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP PPP, COMM REDIALINTERVAL, NULL, CFNUMBER }, + { REGULAR, NETPROP PPP, COMM REMOTEADDRESS, NULL, CFSTRING }, + { REGULAR, NETPROP PPP, COMM TERMINALSCRIPT, NULL, CFSTRING }, { COMMENT, "\n/* " IPCP ": */", NULL, NULL, NULL }, - { REGULAR, NETPROP PPP, IPCP "CompressionVJ", NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP PPP, IPCP COMPRESSIONVJ, NULL, CFNUMBER_BOOL }, { COMMENT, "\n/* " LCP ": */", NULL, NULL, NULL }, - { REGULAR, NETPROP PPP, LCP "EchoEnabled", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, LCP "EchoFailure", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, LCP "EchoInterval", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, LCP "CompressionACField", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, LCP "CompressionPField", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, LCP "MRU", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, LCP "MTU", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, LCP "ReceiveACCM", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, LCP "TransmitACCM", NULL, CFNUMBER }, - { COMMENT, "", NULL, NULL, NULL }, - - { COMMENT, "/*\n * " PPPOE " Entity Keys\n */", NULL, NULL, NULL }, + { REGULAR, NETPROP PPP, LCP ECHOENABLED, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP PPP, LCP ECHOFAILURE, NULL, CFNUMBER }, + { REGULAR, NETPROP PPP, LCP ECHOINTERVAL, NULL, CFNUMBER }, + { REGULAR, NETPROP PPP, LCP COMPRESSIONACFIELD, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP PPP, LCP COMPRESSIONPFIELD, NULL, CFNUMBER_BOOL }, + { REGULAR, NETPROP PPP, LCP MRU, NULL, CFNUMBER }, + { REGULAR, NETPROP PPP, LCP MTU, NULL, CFNUMBER }, + { REGULAR, NETPROP PPP, LCP RECEIVEACCM, NULL, CFNUMBER }, + { REGULAR, NETPROP PPP, LCP TRANSMITACCM, NULL, CFNUMBER }, + { COMMENT, "", NULL, NULL, NULL }, + + { COMMENT, "/*\n * " KEY_PREFIX NETENT PPPOE " Entity Keys\n */", NULL, NULL, NULL }, { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " PPPSERIAL " Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT PPPSERIAL " Entity Keys\n */", NULL, NULL, NULL }, { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " PROXIES " Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT PROXIES " Entity Keys\n */", NULL, NULL, NULL }, { REGULAR, NETPROP PROXIES, EXCEPTIONSLIST, NULL, CFARRAY_CFSTRING }, { REGULAR, NETPROP PROXIES, FTPENABLE, NULL, CFNUMBER_BOOL }, { REGULAR, NETPROP PROXIES, FTPPASSIVE, NULL, CFNUMBER_BOOL }, @@ -433,6 +493,9 @@ struct { { REGULAR, NETPROP PROXIES, HTTPENABLE, NULL, CFNUMBER_BOOL }, { REGULAR, NETPROP PROXIES, HTTPPORT, NULL, CFNUMBER }, { REGULAR, NETPROP PROXIES, HTTPPROXY, NULL, CFSTRING }, + { DEFINE , NETPROP PROXIES, HTTPSENABLE, NULL, CFNUMBER_BOOL }, + { DEFINE , NETPROP PROXIES, HTTPSPORT, NULL, CFNUMBER }, + { DEFINE , NETPROP PROXIES, HTTPSPROXY, NULL, CFSTRING }, { REGULAR, NETPROP PROXIES, RTSPENABLE, NULL, CFNUMBER_BOOL }, { REGULAR, NETPROP PROXIES, RTSPPORT, NULL, CFNUMBER }, { REGULAR, NETPROP PROXIES, RTSPPROXY, NULL, CFSTRING }, @@ -441,99 +504,53 @@ struct { { REGULAR, NETPROP PROXIES, SOCKSPROXY, NULL, CFSTRING }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * Users Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/*\n " KEY_PREFIX COMP USERS " Entity Keys\n */", NULL, NULL, NULL }, { REGULAR, USERSENT, CONSOLEUSER, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n " CONSOLEUSER " Entity Keys\n */", NULL, NULL, NULL }, - { REGULAR, USERSPROP CONSOLEUSER, NAME, "username", CFSTRING }, /* FIX ME! */ - { REGULAR, USERSPROP CONSOLEUSER, UID, "uid", CFSTRING }, /* FIX ME! */ - { REGULAR, USERSPROP CONSOLEUSER, GID, "gid", CFSTRING }, /* FIX ME! */ + { COMMENT, "/*\n " KEY_PREFIX USERSPROP CONSOLEUSER " Properties\n */", NULL, NULL, NULL }, + { REGULAR, USERSPROP CONSOLEUSER, NAME, NULL, CFSTRING }, + { REGULAR, USERSPROP CONSOLEUSER, UID, NULL, CFSTRING }, + { REGULAR, USERSPROP CONSOLEUSER, GID, NULL, CFSTRING }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * " SYSTEM " Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX COMP SYSTEM " Properties\n */", NULL, NULL, NULL }, { REGULAR, SYSTEMPROP, COMPUTERNAME, NULL, CFSTRING }, { REGULAR, SYSTEMPROP, COMPUTERNAME ENCODING, NULL, CFNUMBER }, { COMMENT, "", NULL, NULL, NULL }, - { COMMENT, "/*\n * Configuration Cache Definitions\n */", NULL }, + { COMMENT, "/*\n * Configuration Store Definitions\n */", NULL }, { COMMENT, "/* domain prefixes */", NULL }, - { REGULAR, CACHE DOMAIN, FILE, "File:", NULL }, - { REGULAR, CACHE DOMAIN, PLUGIN, "Plugin:", NULL }, - { REGULAR, CACHE DOMAIN, SETUP, "Setup:", NULL }, - { REGULAR, CACHE DOMAIN, STATE, "State:", NULL }, - { REGULAR, CACHE DOMAIN, PREFS, "Prefs:", NULL }, - { COMMENT, "", NULL, NULL, NULL }, - - { COMMENT, "/* Setup: properties */", NULL }, - { REGULAR, CACHE SETUPPROP, CURRENTSET, NULL, NULL }, - { REGULAR, CACHE SETUPPROP, LASTUPDATED, NULL, NULL }, - { COMMENT, "", NULL, NULL, NULL }, - - { COMMENT, "/* properties */", NULL }, - { REGULAR, CACHE NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING }, - { REGULAR, CACHE NETPROP, PRIMARYINTERFACE, NULL, CFSTRING }, - { REGULAR, CACHE NETPROP, SERVICEIDS, NULL, CFARRAY_CFSTRING }, - { COMMENT, "", NULL, NULL, NULL }, - -// XXX OBSOLETE XXX - { COMMENT, "/* OBSOLETE " NETPROP AIRPORT ": */", NULL, NULL, NULL }, - { REGULAR, NETPROP AIRPORT, INCLUDEPRIVATENETS, NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP AIRPORT, "PreferredAirportNetwork", NULL, CFSTRING }, - - { COMMENT, "/* OBSOLETE " NETPROP ETHERNET ": */", NULL, NULL, NULL }, - { REGULAR, NETPROP ETHERNET, SPEED, NULL, CFNUMBER }, - { REGULAR, NETPROP ETHERNET, DUPLEX, NULL, CFSTRING }, - { REGULAR, NETPROP ETHERNET, "WakeOnSignal", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP ETHERNET, "WakeOnTraffic", NULL, CFNUMBER_BOOL }, - { COMMENT, "/* " KEY_PREFIX NETPROP ETHERNET DUPLEX " values */", NULL, NULL, NULL }, - { REGULAR, NETVAL ETHERNET DUPLEX, AUTOMATIC, NULL, NULL }, - { REGULAR, NETVAL ETHERNET DUPLEX, "FULL", NULL, NULL }, - { REGULAR, NETVAL ETHERNET DUPLEX, "HALF", NULL, NULL }, - - { COMMENT, "/* OBSOLETE " NETPROP INTERFACE ": */", NULL, NULL, NULL }, - { REGULAR, NETPROP INTERFACE, INTERFACE NAME, NULL, CFSTRING }, - { REGULAR, NETPROP INTERFACE, MACADDRESS, NULL, CFSTRING }, - { REGULAR, NETPROP INTERFACE, PORTNAME, NULL, CFSTRING }, - - { COMMENT, "/* OBSOLETE " NETPROP MODEM ": */", NULL, NULL, NULL }, - { REGULAR, NETPROP MODEM, "IgnoreDialTone", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP MODEM, "InitString", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP MODEM, "Port", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP MODEM, PORTNAME, NULL, CFSTRING }, - { REGULAR, NETPROP MODEM, "RedialCount", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP MODEM, "RedialEnabled", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP MODEM, "RedialTimeout", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP MODEM, "Script", NULL, CFSTRING }, - { REGULAR, NETPROP MODEM, "SpeakerEnable", NULL, CFNUMBER }, - { REGULAR, NETPROP MODEM, SPEED, NULL, CFNUMBER }, - { REGULAR, NETPROP MODEM, "ToneDial", NULL, CFNUMBER }, - { REGULAR, NETPROP MODEM, "WaitForTone", NULL, CFNUMBER }, - - { COMMENT, "/* OBSOLETE " NETPROP PPP ": */", NULL, NULL, NULL }, - { REGULAR, NETPROP PPP, ALERT, NULL, CFARRAY_CFSTRING }, - { REGULAR, NETVAL PPP ALERT, "Password", NULL, CFSTRING }, - { REGULAR, NETVAL PPP ALERT, "Reminder", NULL, CFSTRING }, - { REGULAR, NETVAL PPP ALERT, "Status", NULL, CFSTRING }, - { REGULAR, NETPROP PPP, "CompressionEnable", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, "DeviceEntity", NULL, CFSTRING }, - { REGULAR, NETPROP PPP, "HeaderCompression", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, "IdleDisconnect", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, "IdlePrompt", NULL, CFNUMBER_BOOL }, - { REGULAR, NETPROP PPP, "IdleTimeout", NULL, CFSTRING }, - { REGULAR, NETPROP PPP, "PromptTimeout", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, "ReminderTimer", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, "SessionTimer", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, COMM "IdleTimer", NULL, CFNUMBER }, - { REGULAR, NETPROP PPP, IPCP "LocalAddress", NULL, CFSTRING }, - { REGULAR, NETPROP PPP, IPCP "RemoteAddress", NULL, CFSTRING }, - { REGULAR, NETPROP PPP, IPCP "UseServerDNS", NULL, CFNUMBER_BOOL }, - - { COMMENT, "/* OBSOLETE " NETPROP PPPOE ": */", NULL, NULL, NULL }, - { REGULAR, NETPROP PPPOE, PORTNAME, NULL, CFSTRING }, - - { COMMENT, "", NULL, NULL, NULL }, -// XXX OBSOLETE XXX + { DEFINE , DYNAMICSTORE DOMAIN, FILE, "File:", NULL }, + { DEFINE , DYNAMICSTORE DOMAIN, PLUGIN, "Plugin:", NULL }, + { DEFINE , DYNAMICSTORE DOMAIN, SETUP, "Setup:", NULL }, + { DEFINE , DYNAMICSTORE DOMAIN, STATE, "State:", NULL }, + { DEFINE , DYNAMICSTORE DOMAIN, PREFS, "Prefs:", NULL }, + { COMMENT, "", NULL, NULL, NULL }, + + { COMMENT, "/* " KEY_PREFIX DYNAMICSTORE DOMAIN SETUP " Properties */", NULL }, + { DEFINE , DYNAMICSTORE SETUPPROP, CURRENTSET, NULL, CFSTRING }, + { DEFINE , DYNAMICSTORE SETUPPROP, LASTUPDATED, NULL, NULL }, + { COMMENT, "", NULL, NULL, NULL }, + + { COMMENT, "/* Properties */", NULL }, + { DEFINE , DYNAMICSTORE NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING }, + { DEFINE , DYNAMICSTORE NETPROP, PRIMARYINTERFACE, NULL, CFSTRING }, + { DEFINE , DYNAMICSTORE NETPROP, PRIMARYSERVICE, NULL, CFSTRING }, + { DEFINE , DYNAMICSTORE NETPROP, SERVICEIDS, NULL, CFARRAY_CFSTRING }, + { COMMENT, "", NULL, NULL, NULL }, + + /* obsolete keys */ + { OBSOLETE, "Cache" DOMAIN, FILE, "File:", NULL }, + { OBSOLETE, "Cache" DOMAIN, PLUGIN, "Plugin:", NULL }, + { OBSOLETE, "Cache" DOMAIN, SETUP, "Setup:", NULL }, + { OBSOLETE, "Cache" DOMAIN, STATE, "State:", NULL }, + { OBSOLETE, "Cache" DOMAIN, PREFS, "Prefs:", NULL }, + { OBSOLETE, "Cache" SETUPPROP, CURRENTSET, NULL, CFSTRING }, + { OBSOLETE, "Cache" SETUPPROP, LASTUPDATED, NULL, NULL }, + { OBSOLETE, "Cache" NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING }, + { OBSOLETE, "Cache" NETPROP, PRIMARYINTERFACE, NULL, CFSTRING }, + { OBSOLETE, "Cache" NETPROP, SERVICEIDS, NULL, CFARRAY_CFSTRING }, { END, NULL, NULL, NULL, NULL }, }; @@ -562,40 +579,118 @@ dump_names(int type) } break; } + case DEFINE: { + char kbuf[256]; + char vbuf[256]; + + switch (type) { + case gen_header_e: + snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", + names[i].prefix, names[i].key); + + if (names[i].value) + snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")", + names[i].value); + else + snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")", + names[i].key); + + if (names[i].type) + printf("#define %-40s %-40s /* %s */\n", + kbuf, vbuf, names[i].type); + else + printf("#define %-40s %-40s\n", + kbuf, vbuf); + break; + default: + break; + } + break; + } case REGULAR: { - char buf[256]; + char kbuf[256]; + char vbuf[256]; switch (type) { case gen_header_e: - snprintf(buf, sizeof(buf), KEY_PREFIX "%s%s;", + snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", names[i].prefix, names[i].key); + if (names[i].value) + snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")", + names[i].value); + else + snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")", + names[i].key); + if (names[i].type) - printf(STRING_MACRO_NAME " %-40s /* %s */\n", - buf, names[i].type); + printf("#define %-40s %-40s /* %s */\n", + kbuf, vbuf, names[i].type); else - printf(STRING_MACRO_NAME " %s\n", buf); + printf("#define %-40s %-40s\n", + kbuf, vbuf); break; case gen_extern_e: - snprintf(buf, sizeof(buf), KEY_PREFIX "%s%s", + snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", names[i].prefix, names[i].key); printf("volatile CFStringRef " KEY_PREFIX "%s%s = NULL;\n", names[i].prefix, names[i].key); break; case gen_init_e: - snprintf(buf, sizeof(buf), KEY_PREFIX "%s%s", + snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", names[i].prefix, names[i].key); if (names[i].value) printf(" *((void **)&%s) = (void *)CFSTR(\"%s\");\n", - buf, names[i].value); + kbuf, names[i].value); else printf(" *((void **)&%s) = (void *)CFSTR(\"%s\");\n", - buf, names[i].key); + kbuf, names[i].key); break; default: break; } + break; + } + case OBSOLETE: { + char kbuf[256]; + + switch (type) { + case gen_extern_e: + snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", + names[i].prefix, names[i].key); + + printf("volatile CFStringRef " KEY_PREFIX "%s%s = NULL;\n", + names[i].prefix, names[i].key); + break; + case gen_init_e: + snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", + names[i].prefix, names[i].key); + if (names[i].value) + printf(" *((void **)&%s) = (void *)CFSTR(\"%s\");\n", + kbuf, names[i].value); + else + printf(" *((void **)&%s) = (void *)CFSTR(\"%s\");\n", + kbuf, names[i].key); + break; + default: + break; + } + break; + } + case FUTURE: { + char kbuf[256]; + + if (type == gen_header_e) { + snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", + names[i].prefix, names[i].key); + + printf("/* #define %-37s %-40s /* %s */\n", + kbuf, + "SCSTR(\"???\") */", + "RESERVED FOR FUTURE USE"); + } + break; } default: { break; @@ -617,24 +712,47 @@ main(int argc, char * argv[]) if (strcmp(type, "header") == 0) { printf("%s\n", copyright_string); printf("/*\n * This file is automatically generated\n * DO NOT EDIT!\n */\n\n"); - printf("#ifndef _SCPREFERENCES_H\n#define _SCPREFERENCES_H\n\n"); - //printf("#ifndef " STRING_MACRO_NAME "\n"); - printf("#ifndef __OBJC__\n"); - printf("#define " STRING_MACRO_NAME "\t\textern const CFStringRef\n"); - printf("#else\n"); - printf("#define " STRING_MACRO_NAME "\t\textern NSString *\n"); + + printf("/*\n"); + printf(" * Note: For Cocoa/Obj-C/Foundation programs accessing these preference\n"); + printf(" * keys you may want to consider the following:\n"); + printf(" *\n"); + printf(" * #define SCSTR(s) (NSString *)CFSTR(s)\n"); + printf(" * #import \n"); + printf(" */\n\n"); + + printf("#ifndef _SCSCHEMADEFINITIONS_H\n#define _SCSCHEMADEFINITIONS_H\n\n"); + + printf("#ifndef SCSTR\n"); + printf("#include \n"); + printf("#define SCSTR(s) CFSTR(s)\n"); printf("#endif\n"); - //printf("#endif " STRING_MACRO_NAME "\n"); + printf("\n"); dump_names(gen_header_e); - printf("#endif /* _SCPREFERENCES_H */\n"); + printf("#endif /* _SCSCHEMADEFINITIONS_H */\n"); } else if (strcmp(type, "cfile") == 0) { - printf("/*\n * This file is automatically generated\n * DO NOT EDIT!\n */\n\n"); - printf("\n#include \n\n"); + printf("/*\n"); + printf(" * This file is automatically generated\n"); + printf(" * DO NOT EDIT!\n"); + printf(" */\n"); + printf("\n"); + printf("#include \n"); + printf("\n"); dump_names(gen_extern_e); - printf("\n\nvoid\n__private_extern__\n__Initialize(void)\n{\n"); + printf("\n"); + printf("__private_extern__\nvoid\n__Initialize(void)\n"); + printf("{\n"); + printf(" static Boolean initialized = FALSE;\n"); + printf("\n"); + printf(" if (initialized)\n"); + printf(" return;\n"); + printf("\n"); dump_names(gen_init_e); + printf("\n"); + printf(" initialized = TRUE;\n"); + printf(" return;\n"); printf("}\n"); } exit(0); diff --git a/SystemConfiguration.fproj/ppp.c b/SystemConfiguration.fproj/ppp.c index 2af5760..f0c109f 100644 --- a/SystemConfiguration.fproj/ppp.c +++ b/SystemConfiguration.fproj/ppp.c @@ -21,21 +21,19 @@ */ #include -//#include -//#include #include #include #include #include #include #include -#include +#include +#include #include "ppp_msg.h" #include "ppp.h" - __private_extern__ int PPPInit(int *ref) @@ -93,20 +91,20 @@ PPPExec(int ref, // send the command n = write(ref, &msg, sizeof(msg)); if (n == -1) { - SCDLog(LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno)); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno)); return errno; } else if (n != sizeof(msg)) { - SCDLog(LOG_ERR, CFSTR("PPPExec write() failed: wrote=%d"), n); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: wrote=%d"), n); return -1; } if ((request != NULL) && (requestLen > 0)) { n = write(ref, request, requestLen); if (n == -1) { - SCDLog(LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno)); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno)); return errno; } else if (n != requestLen) { - SCDLog(LOG_ERR, CFSTR("PPPExec write() failed: wrote=%d"), n); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: wrote=%d"), n); return -1; } } @@ -114,10 +112,10 @@ PPPExec(int ref, // always expect a reply n = read(ref, &msg, sizeof(msg)); if (n == -1) { - SCDLog(LOG_ERR, CFSTR("PPPExec read() failed: error=%s"), strerror(errno)); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec read() failed: error=%s"), strerror(errno)); return errno; } else if (n != sizeof(msg)) { - SCDLog(LOG_ERR, CFSTR("PPPExec read() failed: insufficent data, read=%d"), n); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec read() failed: insufficent data, read=%d"), n); return -1; } @@ -127,11 +125,11 @@ PPPExec(int ref, // read reply n = read(ref, buf, msg.m_len); if (n == -1) { - SCDLog(LOG_ERR, CFSTR("PPPExec read() failed: error=%s"), strerror(errno)); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec read() failed: error=%s"), strerror(errno)); CFAllocatorDeallocate(NULL, buf); return errno; } else if (n != msg.m_len) { - SCDLog(LOG_ERR, CFSTR("PPPExec read() failed: insufficent data, read=%d"), n); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec read() failed: insufficent data, read=%d"), n); CFAllocatorDeallocate(NULL, buf); return -1; } @@ -150,6 +148,92 @@ PPPExec(int ref, } +#ifdef NOT_NEEDED +int +PPPConnect(int ref, u_long link) +{ + int status; + + status = PPPExec(ref, + link, + PPP_CONNECT, + NULL, + 0, + NULL, + NULL); + if (status != 0) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_CONNECT) failed: status = %d"), status); + return status; + } + + return status; +} + + +int +PPPDisconnect(int ref, u_long link) +{ + int status; + + status = PPPExec(ref, + link, + PPP_DISCONNECT, + NULL, + 0, + NULL, + NULL); + if (status != 0) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_DISCONNECT) failed: status = %d"), status); + return status; + } + + return status; +} + + +int +PPPListen(int ref, u_long link) +{ + int status; + + status = PPPExec(ref, + link, + PPP_LISTEN, + NULL, + 0, + NULL, + NULL); + if (status != 0) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_LISTEN) failed: status = %d"), status); + return status; + } + + return status; +} + + +int +PPPApply(int ref, u_long link) +{ + int status; + + status = PPPExec(ref, + link, + PPP_APPLY, + NULL, + 0, + NULL, + NULL); + if (status != 0) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_APPLY) failed: status = %d"), status); + return status; + } + + return status; +} +#endif /* NOT_NEEDED */ + + __private_extern__ int PPPGetNumberOfLinks(int ref, u_long *nLinks) @@ -166,7 +250,7 @@ PPPGetNumberOfLinks(int ref, u_long *nLinks) &replyBuf, &replyBufLen); if (status != 0) { - SCDLog(LOG_ERR, CFSTR("PPPExec() failed: status = %d"), status); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_GETNBLINKS) failed: status = %d"), status); return status; } @@ -194,7 +278,7 @@ PPPGetLinkByIndex(int ref, int index, u_int32_t *link) &replyBuf, &replyBufLen); if (status != 0) { - SCDLog(LOG_ERR, CFSTR("PPPExec() failed: status = %d"), status); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_GETLINKBYINDEX) failed: status = %d"), status); return status; } @@ -225,7 +309,7 @@ PPPGetLinkByServiceID(int ref, CFStringRef serviceID, u_int32_t *link) status = PPPGetNumberOfLinks(ref, &nLinks); if (status != 0) { - SCDLog(LOG_ERR, CFSTR("PPPGetNumberOfLinks() failed: %d"), status); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPGetNumberOfLinks() failed: %d"), status); goto done; } @@ -238,7 +322,7 @@ PPPGetLinkByServiceID(int ref, CFStringRef serviceID, u_int32_t *link) status = PPPGetLinkByIndex(ref, i, &iLink); if (status != 0) { - SCDLog(LOG_ERR, CFSTR("PPPGetLinkByIndex() failed: %d"), status); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPGetLinkByIndex() failed: %d"), status); goto done; } @@ -248,7 +332,7 @@ PPPGetLinkByServiceID(int ref, CFStringRef serviceID, u_int32_t *link) &data, &dataLen); if (status != 0) { - SCDLog(LOG_ERR, CFSTR("PPPGetOption() failed: %d"), status); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPGetOption(PPP_OPT_SERVICEID) failed: %d"), status); goto done; } @@ -292,7 +376,7 @@ PPPGetOption(int ref, u_long link, u_long option, void **data, u_long *dataLen) &replyBuf, &replyBufLen); if (status != 0) { - SCDLog(LOG_ERR, CFSTR("PPPExec() failed: status = %d"), status); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_GETOPTION) failed: status = %d"), status); *data = NULL; *dataLen = 0; return status; @@ -309,6 +393,40 @@ PPPGetOption(int ref, u_long link, u_long option, void **data, u_long *dataLen) } +#ifdef NOT_NEEDED +__private_extern__ +int +PPPSetOption(int ref, u_long link, u_long option, void *data, u_long dataLen) +{ + void *buf; + u_long bufLen; + int status; + + bufLen = sizeof(struct ppp_opt_hdr) + dataLen; + buf = CFAllocatorAllocate(NULL, bufLen, 0); + + bzero((struct ppp_opt_hdr *)buf, sizeof(struct ppp_opt_hdr)); + ((struct ppp_opt_hdr *)buf)->o_type = option; + bcopy(data, ((struct ppp_opt *)buf)->o_data, dataLen); + + status = PPPExec(ref, + link, + PPP_SETOPTION, + buf, + bufLen, + NULL, + NULL); + if (status != 0) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_SETOPTION) failed: status = %d"), status); + } + + CFAllocatorDeallocate(NULL, buf); + + return status; +} +#endif /* NOT_NEEDED */ + + __private_extern__ int PPPStatus(int ref, u_long link, struct ppp_status **stat) @@ -325,7 +443,7 @@ PPPStatus(int ref, u_long link, struct ppp_status **stat) &replyBuf, &replyBufLen); if (status != 0) { - SCDLog(LOG_ERR, CFSTR("PPPExec() failed: status = %d"), status); + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_STATUS) failed: status = %d"), status); return status; } diff --git a/SystemConfiguration.fproj/ppp.h b/SystemConfiguration.fproj/ppp.h index 8375d1b..33eee18 100644 --- a/SystemConfiguration.fproj/ppp.h +++ b/SystemConfiguration.fproj/ppp.h @@ -23,12 +23,10 @@ #ifndef _PPP_H #define _PPP_H - #include #include #include "ppp_msg.h" - __BEGIN_DECLS int PPPInit (int *ref); @@ -43,6 +41,20 @@ int PPPExec (int ref, void **reply, u_long *replyLen); +#ifdef NOT_NEEDED +int PPPConnect (int ref, + u_long link); + +int PPPDisconnect (int ref, + u_long link); + +int PPPListen (int ref, + u_long link); + +int PPPApply (int ref, + u_long link); +#endif /* NOT_NEEDED */ + int PPPGetNumberOfLinks (int ref, u_long *nLinks); @@ -60,6 +72,14 @@ int PPPGetOption (int ref, void **data, u_long *dataLen); +#ifdef NOT_NEEDED +int PPPSetOption (int ref, + u_long link, + u_long option, + void *data, + u_long dataLen); +#endif /* NOT_NEEDED */ + int PPPStatus (int ref, u_long link, struct ppp_status **stat); diff --git a/SystemConfiguration.fproj/ppp_msg.h b/SystemConfiguration.fproj/ppp_msg.h index 4a3c6da..106817d 100644 --- a/SystemConfiguration.fproj/ppp_msg.h +++ b/SystemConfiguration.fproj/ppp_msg.h @@ -26,7 +26,6 @@ #include - /* local socket path */ #define PPP_PATH "/var/run/pppconfd\0" @@ -118,7 +117,7 @@ enum { PPP_OPT_IPCP_USESERVERDNS, // 4 bytes PPP_OPT_COMM_CONNECTSPEED, // 4 bytes, actual connection speed - PPP_OPT_SERVICEID // string, name of the associated service in the cache + PPP_OPT_SERVICEID // string, name of the associated service in the store }; diff --git a/SystemConfiguration.fproj/v1Compatibility.c b/SystemConfiguration.fproj/v1Compatibility.c new file mode 100644 index 0000000..9a233ab --- /dev/null +++ b/SystemConfiguration.fproj/v1Compatibility.c @@ -0,0 +1,816 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Modification History + * + * March 28, 2001 Allan Nathanson + * - initial revision + */ + +#include +#include +#include "SCDynamicStoreInternal.h" + +#include "v1Compatibility.h" + +extern void __Initialize(); + +typedef struct { + + /* configuration data associated with key */ + CFPropertyListRef data; + + /* instance value of last fetched data */ + int instance; + +} SCDHandlePrivate, *SCDHandlePrivateRef; + + +SCDHandleRef +SCDHandleInit() +{ + SCDHandlePrivateRef privateHandle = CFAllocatorAllocate(NULL, sizeof(SCDHandlePrivate), 0); + + /* set data */ + privateHandle->data = NULL; + + /* set instance */ + privateHandle->instance = 0; + + return (SCDHandleRef)privateHandle; +} + + +void +SCDHandleRelease(SCDHandleRef handle) +{ + SCDHandlePrivateRef privateHandle = (SCDHandlePrivateRef)handle; + + if (privateHandle->data) + CFRelease(privateHandle->data); + + CFAllocatorDeallocate(NULL, privateHandle); + return; +} + + +int +SCDHandleGetInstance(SCDHandleRef handle) +{ + SCDHandlePrivateRef privateHandle = (SCDHandlePrivateRef)handle; + + return privateHandle->instance; +} + + +void +_SCDHandleSetInstance(SCDHandleRef handle, int instance) +{ + SCDHandlePrivateRef privateHandle = (SCDHandlePrivateRef)handle; + + privateHandle->instance = instance; + return; +} + + +CFPropertyListRef +SCDHandleGetData(SCDHandleRef handle) +{ + SCDHandlePrivateRef privateHandle = (SCDHandlePrivateRef)handle; + + if (privateHandle->data == NULL) { + return CFSTR("SCDHandleRef not initialized."); + } + + return privateHandle->data; +} + + +void +SCDHandleSetData(SCDHandleRef handle, CFPropertyListRef data) +{ + SCDHandlePrivateRef privateHandle = (SCDHandlePrivateRef)handle; + + /* remove reference to data previously associated with handle */ + if (privateHandle->data) + CFRelease(privateHandle->data); + + /* associate new data with handle, keep a reference as needed */ + privateHandle->data = data; + if (privateHandle->data) + CFRetain(privateHandle->data); + + return; +} + +static int +convert_SCDStatus_To_SCStatus(SCDStatus status) +{ + switch (status) { + case SCD_OK : return kSCStatusOK; + case SCD_NOSESSION : return kSCStatusNoStoreSession; + case SCD_NOSERVER : return kSCStatusNoStoreServer; + case SCD_LOCKED : return kSCStatusLocked; + case SCD_NEEDLOCK : return kSCStatusNeedLock; + case SCD_EACCESS : return kSCStatusAccessError; + case SCD_NOKEY : return kSCStatusNoKey; + case SCD_EXISTS : return kSCStatusKeyExists; + case SCD_STALE : return kSCStatusStale; + case SCD_INVALIDARGUMENT : return kSCStatusInvalidArgument; + case SCD_NOTIFIERACTIVE : return kSCStatusNotifierActive; + case SCD_FAILED : return kSCStatusFailed; + default : return kSCStatusFailed; + } +} + +SCDStatus +SCDOpen(SCDSessionRef *session, CFStringRef name) +{ + SCDynamicStoreRef newStore; + + __Initialize(); /* initialize framework */ + + newStore = SCDynamicStoreCreate(NULL, name, NULL, NULL); + if (!newStore) { + return SCD_NOSERVER; + } + + *session = (SCDSessionRef)newStore; + return SCD_OK; +} + +SCDStatus +SCDClose(SCDSessionRef *session) +{ + CFRelease(*session); + *session = NULL; + return SCD_OK; +} + +SCDStatus +SCDLock(SCDSessionRef session) +{ + return SCDynamicStoreLock((SCDynamicStoreRef)session) ? SCD_OK : SCD_FAILED; +} + +SCDStatus +SCDUnlock(SCDSessionRef session) +{ + return SCDynamicStoreUnlock((SCDynamicStoreRef)session) ? SCD_OK : SCD_FAILED; +} + +SCDStatus +SCDList(SCDSessionRef session, CFStringRef key, int regexOptions, CFArrayRef *subKeys) +{ + CFMutableStringRef pattern; + + pattern = CFStringCreateMutableCopy(NULL, 0, key); + if ((regexOptions & kSCDRegexKey) != kSCDRegexKey) { + CFStringAppend(pattern, CFSTR(".*")); + } + *subKeys = SCDynamicStoreCopyKeyList((SCDynamicStoreRef)session, pattern); + CFRelease(pattern); + + return (*subKeys) ? SCD_OK : SCD_FAILED; +} + +SCDStatus +SCDAdd(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) +{ + CFTypeRef value = SCDHandleGetData(handle); + return SCDynamicStoreAddValue((SCDynamicStoreRef)session, key, value) ? SCD_OK : SCD_EXISTS; +} + +SCDStatus +SCDAddSession(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) +{ + CFTypeRef value = SCDHandleGetData(handle); + return SCDynamicStoreAddTemporaryValue((SCDynamicStoreRef)session, key, value) ? SCD_OK : SCD_EXISTS; +} + +SCDStatus +SCDGet(SCDSessionRef session, CFStringRef key, SCDHandleRef *handle) +{ + CFTypeRef value; + + value = SCDynamicStoreCopyValue((SCDynamicStoreRef)session, key); + if (value) { + *handle = SCDHandleInit(); + SCDHandleSetData(*handle, value); + CFRelease(value); + return SCD_OK; + } + return SCD_NOKEY; +} + +SCDStatus +SCDSet(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) +{ + CFTypeRef value = SCDHandleGetData(handle); + return SCDynamicStoreSetValue((SCDynamicStoreRef)session, key, value) ? SCD_OK : SCD_EXISTS; +} + +SCDStatus +SCDRemove(SCDSessionRef session, CFStringRef key) +{ + return SCDynamicStoreRemoveValue((SCDynamicStoreRef)session, key) ? SCD_OK : SCD_NOKEY; +} + +SCDStatus +SCDTouch(SCDSessionRef session, CFStringRef key) +{ + return SCDynamicStoreTouchValue((SCDynamicStoreRef)session, key) ? SCD_OK : SCD_FAILED; +} + +SCDStatus +SCDNotifierList(SCDSessionRef session, int regexOptions, CFArrayRef *notifierKeys) +{ + *notifierKeys = SCDynamicStoreCopyWatchedKeyList((SCDynamicStoreRef)session, + ((regexOptions & kSCDRegexKey) == kSCDRegexKey)); + return (*notifierKeys) ? SCD_OK : SCD_FAILED; +} + +SCDStatus +SCDNotifierAdd(SCDSessionRef session, CFStringRef key, int regexOptions) +{ + return SCDynamicStoreAddWatchedKey((SCDynamicStoreRef)session, + key, + ((regexOptions & kSCDRegexKey) == kSCDRegexKey)) ? SCD_OK : SCD_EXISTS; +} + +SCDStatus +SCDNotifierRemove(SCDSessionRef session, CFStringRef key, int regexOptions) +{ + return SCDynamicStoreRemoveWatchedKey((SCDynamicStoreRef)session, + key, + ((regexOptions & kSCDRegexKey) == kSCDRegexKey)) ? SCD_OK : SCD_NOKEY; +} + +SCDStatus +SCDNotifierGetChanges(SCDSessionRef session, CFArrayRef *changedKeys) +{ + *changedKeys = SCDynamicStoreCopyNotifiedKeys((SCDynamicStoreRef)session); + return (*changedKeys) ? SCD_OK : SCD_FAILED; +} + +SCDStatus +SCDNotifierWait(SCDSessionRef session) +{ + return SCDynamicStoreNotifyWait((SCDynamicStoreRef)session) ? SCD_OK : SCD_FAILED; +} + +SCDStatus +SCDNotifierInformViaCallback(SCDSessionRef session, SCDCallbackRoutine_t func, void *arg) +{ + return SCDynamicStoreNotifyCallback((SCDynamicStoreRef)session, + CFRunLoopGetCurrent(), + (SCDynamicStoreCallBack_v1)func, + arg) ? SCD_OK : SCD_NOTIFIERACTIVE; +} + +SCDStatus +SCDNotifierInformViaMachPort(SCDSessionRef session, mach_msg_id_t msgid, mach_port_t *port) +{ + return SCDynamicStoreNotifyMachPort((SCDynamicStoreRef)session, msgid, port) ? SCD_OK : SCD_NOTIFIERACTIVE; +} + +SCDStatus +SCDNotifierInformViaFD(SCDSessionRef session, int32_t identifier, int *fd) +{ + return SCDynamicStoreNotifyFileDescriptor((SCDynamicStoreRef)session, identifier, fd) ? SCD_OK : SCD_NOTIFIERACTIVE; +} + +SCDStatus +SCDNotifierInformViaSignal(SCDSessionRef session, pid_t pid, int sig) +{ + return SCDynamicStoreNotifySignal((SCDynamicStoreRef)session, pid, sig) ? SCD_OK : SCD_NOTIFIERACTIVE; +} + +SCDStatus +SCDNotifierCancel(SCDSessionRef session) +{ + return SCDynamicStoreNotifyCancel((SCDynamicStoreRef)session) ? SCD_OK : SCD_NOTIFIERACTIVE; +} + +SCDStatus +SCDSnapshot(SCDSessionRef session) +{ + return SCDynamicStoreSnapshot((SCDynamicStoreRef)session) ? SCD_OK : SCD_NOTIFIERACTIVE; +} + +int +SCDOptionGet(SCDSessionRef session, int option) +{ + int value = 0; + + if (session) { + static Boolean warned = FALSE; + if (!warned) { + SCLog(TRUE, LOG_NOTICE, CFSTR("per-session options are no longer supported, using global options.")); + warned = TRUE; + } + } + + switch (option) { + case kSCDOptionDebug : + value = _sc_debug ? 1 : 0; + break; + + case kSCDOptionVerbose : + value = _sc_verbose ? 1 : 0; + break; + + case kSCDOptionUseSyslog : + value = _sc_log ? 1 : 0; + break; + + case kSCDOptionUseCFRunLoop : + value = 1; /* always TRUE */ + break; + } + + return value; +} + +void +SCDOptionSet(SCDSessionRef session, int option, int value) +{ + if (session) { + static Boolean warned = FALSE; + if (!warned) { + SCLog(TRUE, LOG_NOTICE, CFSTR("per-session options are no longer supported, using global options.")); + warned = TRUE; + } + } + + switch (option) { + case kSCDOptionDebug : + _sc_debug = (value != 0); + _sc_log = (value == 0); + break; + + case kSCDOptionVerbose : + _sc_verbose = (value != 0); + break; + + case kSCDOptionUseSyslog : + { + _sc_log = (value != 0); + break; + } + + case kSCDOptionUseCFRunLoop : + { + static Boolean warned = FALSE; + if ((value == FALSE) && !warned) { + SCLog(TRUE, LOG_NOTICE, CFSTR("The kSCDOptionUseCFRunLoop option can no longer be set FALSE. The")); + SCLog(TRUE, LOG_NOTICE, CFSTR("SCDNotifierInformViaCallback requires the use of a CFRunLoop.")); + warned = TRUE; + } + break; + } + } + + return; +} + +void +SCDSessionLog(SCDSessionRef session, int level, CFStringRef formatString, ...) +{ + va_list argList; + FILE *f = (LOG_PRI(level) > LOG_NOTICE) ? stderr : stdout; + CFStringRef resultString; + + if ((LOG_PRI(level) == LOG_DEBUG) && !SCDOptionGet(session, kSCDOptionVerbose)) { + /* it's a debug message and we haven't requested verbose logging */ + return; + } + + va_start(argList, formatString); + resultString = CFStringCreateWithFormatAndArguments(NULL, NULL, formatString, argList); + va_end(argList); + + if (SCDOptionGet(session, kSCDOptionUseSyslog)) { + __SCLog(level, resultString); + } else { + CFStringRef newString; + + /* add a new-line */ + newString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@\n"), resultString); + __SCPrint(f, newString); + CFRelease(newString); + } + CFRelease(resultString); +} + +void +SCDLog(int level, CFStringRef formatString, ...) +{ + va_list argList; + FILE *f = (LOG_PRI(level) > LOG_NOTICE) ? stderr : stdout; + CFStringRef resultString; + + if ((LOG_PRI(level) == LOG_DEBUG) && !SCDOptionGet(NULL, kSCDOptionVerbose)) { + /* it's a debug message and we haven't requested verbose logging */ + return; + } + + va_start(argList, formatString); + resultString = CFStringCreateWithFormatAndArguments(NULL, NULL, formatString, argList); + va_end(argList); + + if (SCDOptionGet(NULL, kSCDOptionUseSyslog)) { + __SCLog(level, resultString); + } else { + CFStringRef newString; + + /* add a new-line */ + newString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@\n"), resultString); + __SCPrint(f, newString); + CFRelease(newString); + } + CFRelease(resultString); +} + +const char * +SCDError(SCDStatus status) +{ + return SCErrorString(convert_SCDStatus_To_SCStatus(status)); +} + +CFStringRef +SCDKeyCreate(CFStringRef fmt, ...) +{ + va_list args; + va_start(args, fmt); + return (CFStringCreateWithFormatAndArguments(NULL, + NULL, + fmt, + args)); +} + +CFStringRef +SCDKeyCreateNetworkGlobalEntity(CFStringRef domain, CFStringRef entity) +{ + return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, domain, entity); +} + +CFStringRef +SCDKeyCreateNetworkInterface(CFStringRef domain) +{ + return SCDynamicStoreKeyCreateNetworkInterface(NULL, domain); +} + +CFStringRef +SCDKeyCreateNetworkInterfaceEntity(CFStringRef domain, CFStringRef ifname, CFStringRef entity) +{ + return SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, domain, ifname, entity); +} + +CFStringRef +SCDKeyCreateNetworkServiceEntity(CFStringRef domain, CFStringRef serviceID, CFStringRef entity) +{ + return SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, domain, serviceID, entity); +} + +static int +convert_SCPStatus_To_SCStatus(SCPStatus status) +{ + switch (status) { + case SCP_OK : return kSCStatusOK; + case SCP_NOSESSION : return kSCStatusNoPrefsSession; + case SCP_BUSY : return kSCStatusPrefsBusy; + case SCP_NEEDLOCK : return kSCStatusNeedLock; + case SCP_EACCESS : return kSCStatusAccessError; + case SCP_ENOENT : return kSCStatusNoConfigFile; + case SCP_BADCF : return kSCStatusFailed; + case SCP_NOKEY : return kSCStatusNoKey; + case SCP_NOLINK : return kSCStatusNoLink; + case SCP_EXISTS : return kSCStatusKeyExists; + case SCP_STALE : return kSCStatusStale; + case SCP_INVALIDARGUMENT : return kSCStatusInvalidArgument; + case SCP_FAILED : return kSCStatusFailed; + default : return kSCStatusFailed; + } +} + +SCPStatus +SCPOpen(SCPSessionRef *session, CFStringRef name, CFStringRef prefsID, int options) +{ + CFArrayRef keys; + CFIndex nKeys; + + __Initialize(); /* initialize framework */ + + *session = (SCPSessionRef)SCPreferencesCreate(NULL, name, prefsID); + if (*session == NULL) { + return SCP_EACCESS; + } + + keys = SCPreferencesCopyKeyList(*session); + nKeys = CFArrayGetCount(keys); + CFRelease(keys); + + if ((nKeys == 0) && + ((options & kSCPOpenCreatePrefs) != kSCPOpenCreatePrefs)) { + /* if no keys and not requesting the file be created */ + return SCP_ENOENT; + } + + return SCP_OK; +} + +SCPStatus +SCPUserOpen(SCPSessionRef *session, CFStringRef name, CFStringRef prefsID, CFStringRef user, int options) +{ + CFArrayRef keys; + CFIndex nKeys; + + __Initialize(); /* initialize framework */ + + *session = (SCPSessionRef)SCUserPreferencesCreate(NULL, name, prefsID, user); + if (*session == NULL) { + return SCP_EACCESS; + } + + keys = SCPreferencesCopyKeyList(*session); + nKeys = CFArrayGetCount(keys); + CFRelease(keys); + + if ((nKeys == 0) && + ((options & kSCPOpenCreatePrefs) != kSCPOpenCreatePrefs)) { + /* if no keys and not requesting the file be created */ + return SCP_ENOENT; + } + + return SCP_OK; +} + +SCPStatus +SCPClose(SCPSessionRef *session) +{ + CFRelease(*session); + *session = NULL; + return SCD_OK; +} + +SCPStatus +SCPLock(SCPSessionRef session, boolean_t wait) +{ + /* XXXXX: old API error codes included kSCStatusPrefsBusy, kSCStatusAccessError, and kSCStatusStale */ + return SCPreferencesLock((SCPreferencesRef)session, wait) ? SCP_OK : SCP_FAILED; +} + +SCPStatus +SCPCommit(SCPSessionRef session) +{ + /* XXXXX: old API error codes included kSCStatusAccessError, kSCStatusStale */ + return SCPreferencesCommitChanges((SCPreferencesRef)session) ? SCP_OK : SCP_FAILED; +} + +SCPStatus +SCPApply(SCPSessionRef session) +{ + return SCPreferencesApplyChanges((SCPreferencesRef)session) ? SCP_OK : SCP_EACCESS; +} + +SCPStatus +SCPUnlock(SCPSessionRef session) +{ + return SCPreferencesUnlock((SCPreferencesRef)session) ? SCP_OK : SCP_FAILED; +} + +SCPStatus +SCPGetSignature(SCPSessionRef session, CFDataRef *signature) +{ + *signature = SCPreferencesGetSignature((SCPreferencesRef)session); + return (*signature) ? SCP_OK : SCP_FAILED; +} + +SCPStatus +SCPList(SCPSessionRef session, CFArrayRef *keys) +{ + *keys = SCPreferencesCopyKeyList((SCPreferencesRef)session); + return (*keys) ? SCP_OK : SCP_FAILED; +} + +SCPStatus +SCPGet(SCPSessionRef session, CFStringRef key, CFPropertyListRef *data) +{ + *data = SCPreferencesGetValue((SCPreferencesRef)session, key); + return (*data) ? SCP_OK : SCP_NOKEY; +} + +SCPStatus +SCPAdd(SCPSessionRef session, CFStringRef key, CFPropertyListRef data) +{ + return SCPreferencesAddValue((SCPreferencesRef)session, key, data) ? SCP_OK : SCP_EXISTS; +} + +SCPStatus +SCPSet(SCPSessionRef session, CFStringRef key, CFPropertyListRef data) +{ + return SCPreferencesSetValue((SCPreferencesRef)session, key, data) ? SCP_OK : SCP_FAILED; +} + +SCPStatus +SCPRemove(SCPSessionRef session, CFStringRef key) +{ + return SCPreferencesRemoveValue((SCPreferencesRef)session, key) ? SCP_OK : SCP_NOKEY; +} + +CFStringRef +SCPNotificationKeyCreate(CFStringRef prefsID, int keyType) +{ + return SCDynamicStoreKeyCreatePreferences(NULL, prefsID, keyType); +} + +CFStringRef +SCPUserNotificationKeyCreate(CFStringRef prefsID, CFStringRef user, int keyType) +{ + return SCDynamicStoreKeyCreateUserPreferences(NULL, prefsID, user, keyType); +} + +SCPStatus +SCPPathCreateUniqueChild(SCPSessionRef session, CFStringRef prefix, CFStringRef *newPath) +{ + *newPath = SCPreferencesPathCreateUniqueChild((SCPreferencesRef)session, prefix); + return (*newPath) ? SCP_OK : SCP_NOKEY; +} + +SCPStatus +SCPPathGetValue(SCPSessionRef session, CFStringRef path, CFDictionaryRef *value) +{ + *value = SCPreferencesPathGetValue((SCPreferencesRef)session, path); + return (*value) ? SCP_OK : SCP_NOKEY; +} + +SCPStatus +SCPPathGetLink(SCPSessionRef session, CFStringRef path, CFStringRef *link) +{ + *link = SCPreferencesPathGetLink((SCPreferencesRef)session, path); + return (*link) ? SCP_OK : SCP_NOKEY; +} + +SCPStatus +SCPPathSetValue(SCPSessionRef session, CFStringRef path, CFDictionaryRef value) +{ + return SCPreferencesPathSetValue((SCPreferencesRef)session, path, value) ? SCP_OK : SCP_FAILED; +} + +SCPStatus +SCPPathSetLink(SCPSessionRef session, CFStringRef path, CFStringRef link) +{ + return SCPreferencesPathSetLink((SCPreferencesRef)session, path, link) ? SCP_OK : SCP_FAILED; +} + +SCPStatus +SCPPathRemove(SCPSessionRef session, CFStringRef path) +{ + return SCPreferencesPathRemoveValue((SCPreferencesRef)session, path) ? SCP_OK : SCP_NOKEY; +} + +const char * +SCPError(SCPStatus status) +{ + return SCErrorString(convert_SCPStatus_To_SCStatus(status)); +} + +CFStringRef +SCDKeyCreateConsoleUser() +{ + return SCDynamicStoreKeyCreateConsoleUser(NULL); +} + +SCDStatus +SCDConsoleUserGet(char *user, int userlen, uid_t *uid, gid_t *gid) +{ + CFStringRef consoleUser; + + consoleUser = SCDynamicStoreCopyConsoleUser(NULL, uid, gid); + if (!consoleUser) { + return SCD_NOKEY; + } + + if (user && (userlen > 0)) { + CFIndex len; + CFRange range; + + bzero(user, userlen); + range = CFRangeMake(0, CFStringGetLength(consoleUser)); + (void) CFStringGetBytes(consoleUser, + range, + kCFStringEncodingMacRoman, + 0, + FALSE, + user, + userlen, + &len); + } + CFRelease(consoleUser); + return SCD_OK; +} + +SCDStatus +SCDConsoleUserSet(const char *user, uid_t uid, gid_t gid) +{ + return SCDynamicStoreSetConsoleUser(NULL, user, uid, gid) ? SCD_OK : SCD_FAILED; +} + +CFStringRef +SCDKeyCreateHostName() +{ + return SCDynamicStoreKeyCreateComputerName(NULL); +} + +SCDStatus +SCDHostNameGet(CFStringRef *name, CFStringEncoding *nameEncoding) +{ + *name = SCDynamicStoreCopyComputerName(NULL, nameEncoding); + return (*name) ? SCD_OK : SCD_FAILED; +} + +static SCNStatus +convertReachability(int newFlags, int *oldFlags) +{ + SCNStatus scn_status = SCN_REACHABLE_NO; + + if (newFlags & kSCNetworkFlagsTransientConnection) { + if (oldFlags) { + *oldFlags |= kSCNFlagsTransientConnection; + } + } + + if (newFlags & kSCNetworkFlagsReachable) { + scn_status = SCN_REACHABLE_YES; + + if (newFlags & kSCNetworkFlagsConnectionRequired) { + scn_status = SCN_REACHABLE_CONNECTION_REQUIRED; + } + + if (newFlags & kSCNetworkFlagsConnectionAutomatic) { + if (oldFlags) { + *oldFlags |= kSCNFlagsConnectionAutomatic; + } + } + + if (newFlags & kSCNetworkFlagsInterventionRequired) { + if (oldFlags) { + *oldFlags |= kSCNFlagsInterventionRequired; + } + } + } + + return scn_status; +} + +SCNStatus +SCNIsReachableByAddress(const struct sockaddr *address, const int addrlen, int *flags, const char **errorMessage) +{ + SCNetworkConnectionFlags newFlags; + + if (!SCNetworkCheckReachabilityByAddress(address, addrlen, &newFlags)) { + if (errorMessage) { + *errorMessage = SCErrorString(kSCStatusReachabilityUnknown); + } + return SCN_REACHABLE_UNKNOWN; + } + + return convertReachability(newFlags, flags); + +} + +SCNStatus +SCNIsReachableByName(const char *nodename, int *flags, const char **errorMessage) +{ + SCNetworkConnectionFlags newFlags; + + if (!SCNetworkCheckReachabilityByName(nodename, &newFlags)) { + if (errorMessage) { + *errorMessage = SCErrorString(kSCStatusReachabilityUnknown); + } + return SCN_REACHABLE_UNKNOWN; + } + + return convertReachability(newFlags, flags); +} diff --git a/SystemConfiguration.fproj/v1Compatibility.h b/SystemConfiguration.fproj/v1Compatibility.h new file mode 100644 index 0000000..a99e435 --- /dev/null +++ b/SystemConfiguration.fproj/v1Compatibility.h @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _V1COMPATIBILITY_H +#define _V1COMPATIBILITY_H + +#include +#include +#include +#include +#include +#include + + +#define kSCCacheDomainFile kSCDynamicStoreDomainFile +#define kSCCacheDomainPlugin kSCDynamicStoreDomainPlugin +#define kSCCacheDomainSetup kSCDynamicStoreDomainSetup +#define kSCCacheDomainState kSCDynamicStoreDomainState +#define kSCCacheDomainPrefs kSCDynamicStoreDomainPrefs +#define kSCCachePropSetupCurrentSet kSCDynamicStorePropSetupCurrentSet +#define kSCCachePropSetupLastUpdated kSCDynamicStorePropSetupLastUpdated +#define kSCCachePropNetInterfaces kSCDynamicStorePropNetInterfaces +#define kSCCachePropNetPrimaryInterface kSCDynamicStorePropNetPrimaryInterface +#define kSCCachePropNetPrimaryService kSCDynamicStorePropNetPrimaryService +#define kSCCachePropNetServiceIDs kSCDynamicStorePropNetServiceIDs + + +typedef enum { + SCD_OK = 0, /* Success */ + SCD_NOSESSION = 1, /* Configuration daemon session not active */ + SCD_NOSERVER = 2, /* Configuration daemon not (no longer) available */ + SCD_LOCKED = 3, /* Lock already held */ + SCD_NEEDLOCK = 4, /* Lock required for this operation */ + SCD_EACCESS = 5, /* Permission denied (must be root to obtain lock) */ + SCD_NOKEY = 6, /* No such key */ + SCD_EXISTS = 7, /* Data associated with key already defined */ + SCD_STALE = 8, /* Write attempted on stale version of object */ + SCD_INVALIDARGUMENT = 9, /* Invalid argument */ + SCD_NOTIFIERACTIVE = 10, /* Notifier is currently active */ + SCD_FAILED = 9999 /* Generic error */ +} SCDStatus; + +typedef const struct __SCDSession * SCDSessionRef; + +typedef const struct __SCDHandle * SCDHandleRef; + +typedef enum { + kSCDRegexKey = 0100000, /* pattern string is a regular expression */ +} SCDKeyOption; + +typedef enum { + kSCDOptionDebug = 0, /* Enable debugging */ + kSCDOptionVerbose = 1, /* Enable verbose logging */ + kSCDOptionUseSyslog = 2, /* Use syslog(3) for log messages */ + kSCDOptionUseCFRunLoop = 3, /* Calling application is CFRunLoop() based */ +} SCDOption; + +typedef boolean_t (*SCDCallbackRoutine_t) (SCDSessionRef session, + void *context); + +typedef void (*SCDBundleStartRoutine_t) (const char *bundlePath, + const char *bundleName); + +typedef void (*SCDBundlePrimeRoutine_t) (); + +typedef enum { + SCP_OK = 0, /* Success */ + SCP_NOSESSION = 1024, /* Preference session not active */ + SCP_BUSY = 1025, /* Preferences update currently in progress */ + SCP_NEEDLOCK = 1026, /* Lock required for this operation */ + SCP_EACCESS = 1027, /* Permission denied */ + SCP_ENOENT = 1028, /* Configuration file not found */ + SCP_BADCF = 1029, /* Configuration file corrupt */ + SCP_NOKEY = 1030, /* No such key */ + SCP_NOLINK = 1031, /* No such link */ + SCP_EXISTS = 1032, /* No such key */ + SCP_STALE = 1033, /* Write attempted on stale version of object */ + SCP_INVALIDARGUMENT = 1034, /* Invalid argument */ + SCP_FAILED = 9999 /* Generic error */ +} SCPStatus; + +typedef enum { + kSCPOpenCreatePrefs = 1, /* create preferences file if not found */ +} SCPOption; + +typedef enum { + kSCPKeyLock = 1, + kSCPKeyCommit = 2, + kSCPKeyApply = 3, +} SCPKeyType; + +typedef void * SCPSessionRef; + +typedef enum { + SCN_REACHABLE_UNKNOWN = -1, + SCN_REACHABLE_NO = 0, + SCN_REACHABLE_CONNECTION_REQUIRED = 1, + SCN_REACHABLE_YES = 2, +} SCNStatus; + +typedef enum { + kSCNFlagsTransientConnection = 1<<0, + kSCNFlagsConnectionAutomatic = 1<<1, + kSCNFlagsInterventionRequired = 1<<2, +} SCNConnectionFlags; + +__BEGIN_DECLS + +/* + * handle APIs + */ + +SCDHandleRef SCDHandleInit (); + +void SCDHandleRelease (SCDHandleRef handle); + +int SCDHandleGetInstance (SCDHandleRef handle); + +void _SCDHandleSetInstance (SCDHandleRef handle, + int instance); + +CFPropertyListRef SCDHandleGetData (SCDHandleRef handle); + +void SCDHandleSetData (SCDHandleRef handle, + CFPropertyListRef data); + +/* + * store access APIs + */ + +SCDStatus SCDOpen (SCDSessionRef *session, + CFStringRef name); + +SCDStatus SCDClose (SCDSessionRef *session); + +SCDStatus SCDLock (SCDSessionRef session); + +SCDStatus SCDUnlock (SCDSessionRef session); + +SCDStatus SCDList (SCDSessionRef session, + CFStringRef key, + int regexOptions, + CFArrayRef *subKeys); + +SCDStatus SCDAdd (SCDSessionRef session, + CFStringRef key, + SCDHandleRef handle); + +SCDStatus SCDAddSession (SCDSessionRef session, + CFStringRef key, + SCDHandleRef handle); + +SCDStatus SCDGet (SCDSessionRef session, + CFStringRef key, + SCDHandleRef *handle); + +SCDStatus SCDSet (SCDSessionRef session, + CFStringRef key, + SCDHandleRef handle); + +SCDStatus SCDRemove (SCDSessionRef session, + CFStringRef key); + +SCDStatus SCDTouch (SCDSessionRef session, + CFStringRef key); + +SCDStatus SCDNotifierList (SCDSessionRef session, + int regexOptions, + CFArrayRef *changedKeys); + +SCDStatus SCDNotifierAdd (SCDSessionRef session, + CFStringRef key, + int regexOptions); + +SCDStatus SCDNotifierRemove (SCDSessionRef session, + CFStringRef key, + int regexOptions); + +SCDStatus SCDNotifierGetChanges (SCDSessionRef session, + CFArrayRef *notifierKeys); + +SCDStatus SCDNotifierWait (SCDSessionRef session); + +SCDStatus SCDNotifierInformViaCallback (SCDSessionRef session, + SCDCallbackRoutine_t func, + void *arg); + +SCDStatus SCDNotifierInformViaMachPort (SCDSessionRef session, + mach_msg_id_t msgid, + mach_port_t *port); + +SCDStatus SCDNotifierInformViaFD (SCDSessionRef session, + int32_t identifier, + int *fd); + +SCDStatus SCDNotifierInformViaSignal (SCDSessionRef session, + pid_t pid, + int sig); + +SCDStatus SCDNotifierCancel (SCDSessionRef session); + +SCDStatus SCDSnapshot (SCDSessionRef session); + +int SCDOptionGet (SCDSessionRef session, + int option); + +void SCDOptionSet (SCDSessionRef session, + int option, + int value); + +void SCDSessionLog (SCDSessionRef session, + int level, + CFStringRef formatString, + ...); + +void SCDLog (int level, + CFStringRef formatString, + ...); + +const char * SCDError (SCDStatus status); + +/* + * store/preference keys + */ + +CFStringRef SCDKeyCreate (CFStringRef fmt, + ...); + +CFStringRef SCDKeyCreateNetworkGlobalEntity (CFStringRef domain, + CFStringRef entity); + +CFStringRef SCDKeyCreateNetworkInterface (CFStringRef domain); + +CFStringRef SCDKeyCreateNetworkInterfaceEntity (CFStringRef domain, + CFStringRef ifname, + CFStringRef entity); + +CFStringRef SCDKeyCreateNetworkServiceEntity (CFStringRef domain, + CFStringRef serviceID, + CFStringRef entity); + +/* + * preference APIs + */ + +SCPStatus SCPOpen (SCPSessionRef *session, + CFStringRef name, + CFStringRef prefsID, + int options); + +SCPStatus SCPUserOpen (SCPSessionRef *session, + CFStringRef name, + CFStringRef prefsID, + CFStringRef user, + int options); + +SCPStatus SCPClose (SCPSessionRef *session); + +SCPStatus SCPLock (SCPSessionRef session, + boolean_t wait); + +SCPStatus SCPCommit (SCPSessionRef session); + +SCPStatus SCPApply (SCPSessionRef session); + +SCPStatus SCPUnlock (SCPSessionRef session); + +SCPStatus SCPGetSignature (SCPSessionRef session, + CFDataRef *signature); + +SCPStatus SCPList (SCPSessionRef session, + CFArrayRef *keys); + +SCPStatus SCPGet (SCPSessionRef session, + CFStringRef key, + CFPropertyListRef *data); + +SCPStatus SCPAdd (SCPSessionRef session, + CFStringRef key, + CFPropertyListRef data); + +SCPStatus SCPSet (SCPSessionRef session, + CFStringRef key, + CFPropertyListRef data); + +SCPStatus SCPRemove (SCPSessionRef session, + CFStringRef key); + +SCPStatus SCPPathCreateUniqueChild (SCPSessionRef session, + CFStringRef prefix, + CFStringRef *newPath); + +SCPStatus SCPPathGetValue (SCPSessionRef session, + CFStringRef path, + CFDictionaryRef *value); + +SCPStatus SCPPathGetLink (SCPSessionRef session, + CFStringRef path, + CFStringRef *link); + +SCPStatus SCPPathSetValue (SCPSessionRef session, + CFStringRef path, + CFDictionaryRef value); + +SCPStatus SCPPathSetLink (SCPSessionRef session, + CFStringRef path, + CFStringRef link); + +SCPStatus SCPPathRemove (SCPSessionRef session, + CFStringRef path); + +CFStringRef SCPNotificationKeyCreate (CFStringRef prefsID, + int keyType); + +CFStringRef SCPUserNotificationKeyCreate (CFStringRef prefsID, + CFStringRef user, + int keyType); + +const char * SCPError (SCPStatus status); + +/* + * console user APIs + */ + +CFStringRef SCDKeyCreateConsoleUser (); + +SCDStatus SCDConsoleUserGet (char *user, + int userlen, + uid_t *uid, + gid_t *gid); + +SCDStatus SCDConsoleUserSet (const char *user, + uid_t uid, + gid_t gid); + +/* + * host name APIs + */ + +CFStringRef SCDKeyCreateHostName (); + +SCDStatus SCDHostNameGet (CFStringRef *name, + CFStringEncoding *nameEncoding); + +/* + * network reachability APIs + */ +SCNStatus SCNIsReachableByAddress (const struct sockaddr *address, + const int addrlen, + int *flags, + const char **errorMessage); + +SCNStatus SCNIsReachableByName (const char *nodename, + int *flags, + const char **errorMessage); + +__END_DECLS + +#endif /* _V1COMPATIBILITY_H */ diff --git a/configd.tproj/Makefile b/configd.tproj/Makefile index d9c7c6f..1579d6f 100644 --- a/configd.tproj/Makefile +++ b/configd.tproj/Makefile @@ -13,19 +13,20 @@ PROJECTVERSION = 2.8 PROJECT_TYPE = Tool HFILES = configd.h _SCD.h configd_server.h notify_server.h\ - plugin_support.h session.h notify.h + plugin_support.h session.h notify.h MFILES = configd.m CFILES = _SCD.c configd_server.c notify_server.c plugin_support.c\ - session.c notify.c _configopen.c _configclose.c _configlock.c\ - _configunlock.c _configlist.c _configadd.c _configadd_s.c\ - _configget.c _configset.c _configremove.c _configtouch.c\ - _notifyadd.c _notifyremove.c _notifychanges.c _notifyviaport.c\ - _notifyviafd.c _notifyviasignal.c _notifycancel.c _snapshot.c + session.c notify.c _configopen.c _configclose.c _configlock.c\ + _configunlock.c _configlist.c _configadd.c _configadd_s.c\ + _configget.c _configset.c _configremove.c _configtouch.c\ + _confignotify.c _notifyadd.c _notifyremove.c _notifychanges.c\ + _notifyviaport.c _notifyviafd.c _notifyviasignal.c\ + _notifycancel.c _snapshot.c OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\ - h.template config.defs + h.template config.defs MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles @@ -39,7 +40,8 @@ DEBUG_LIBS = $(LIBS) PROF_LIBS = $(LIBS) -FRAMEWORKS = -framework SystemConfiguration +NEXTSTEP_PB_CFLAGS = -DUSE_SYSTEMCONFIGURATION_PUBLIC_APIS +FRAMEWORKS = -framework CoreFoundation -framework SystemConfiguration NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc diff --git a/configd.tproj/PB.project b/configd.tproj/PB.project index 9174d1f..225a4c5 100644 --- a/configd.tproj/PB.project +++ b/configd.tproj/PB.project @@ -1,75 +1,77 @@ { - DYNAMIC_CODE_GEN = YES; + DYNAMIC_CODE_GEN = YES; FILESTABLE = { - FRAMEWORKS = (SystemConfiguration.framework); - FRAMEWORKSEARCH = (); - HEADERSEARCH = (); - H_FILES = ( - configd.h, - _SCD.h, - configd_server.h, - notify_server.h, - plugin_support.h, - session.h, - notify.h - ); - OTHER_LIBS = (objc); - OTHER_LINKED = ( - configd.m, - _SCD.c, - configd_server.c, - notify_server.c, - plugin_support.c, - session.c, - notify.c, - _configopen.c, - _configclose.c, - _configlock.c, - _configunlock.c, - _configlist.c, - _configadd.c, - _configadd_s.c, - _configget.c, - _configset.c, - _configremove.c, - _configtouch.c, - _notifyadd.c, - _notifyremove.c, - _notifychanges.c, - _notifyviaport.c, - _notifyviafd.c, - _notifyviasignal.c, - _notifycancel.c, - _snapshot.c - ); - OTHER_SOURCES = ( - Makefile.preamble, - Makefile, - Makefile.postamble, - m.template, - h.template, - config.defs - ); - PRECOMPILED_HEADERS = (); - PROJECT_HEADERS = (); - PUBLIC_HEADERS = (); - SUBPROJECTS = (); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; - NEXTSTEP_INSTALLDIR = /usr/sbin; - NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; - NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; - PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; - PDO_UNIX_INSTALLDIR = /bin; - PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; - PROJECTNAME = configd; - PROJECTTYPE = Tool; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_INSTALLDIR = /Library/Executables; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; + FRAMEWORKS = (CoreFoundation.framework, SystemConfiguration.framework); + FRAMEWORKSEARCH = (); + HEADERSEARCH = (); + H_FILES = ( + configd.h, + _SCD.h, + configd_server.h, + notify_server.h, + plugin_support.h, + session.h, + notify.h + ); + OTHER_LIBS = (objc); + OTHER_LINKED = ( + configd.m, + _SCD.c, + configd_server.c, + notify_server.c, + plugin_support.c, + session.c, + notify.c, + _configopen.c, + _configclose.c, + _configlock.c, + _configunlock.c, + _configlist.c, + _configadd.c, + _configadd_s.c, + _configget.c, + _configset.c, + _configremove.c, + _configtouch.c, + _confignotify.c, + _notifyadd.c, + _notifyremove.c, + _notifychanges.c, + _notifyviaport.c, + _notifyviafd.c, + _notifyviasignal.c, + _notifycancel.c, + _snapshot.c + ); + OTHER_SOURCES = ( + Makefile.preamble, + Makefile, + Makefile.postamble, + m.template, + h.template, + config.defs + ); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; + NEXTSTEP_COMPILEROPTIONS = "-DUSE_SYSTEMCONFIGURATION_PUBLIC_APIS"; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_INSTALLDIR = /bin; + PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = configd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_INSTALLDIR = /Library/Executables; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; } diff --git a/configd.tproj/_SCD.c b/configd.tproj/_SCD.c index c89dd8c..5d024af 100644 --- a/configd.tproj/_SCD.c +++ b/configd.tproj/_SCD.c @@ -20,35 +20,47 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * June 2, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" -CFMutableDictionaryRef sessionData = NULL; +CFMutableDictionaryRef sessionData = NULL; + +CFMutableDictionaryRef storeData = NULL; +CFMutableDictionaryRef storeData_s = NULL; -CFMutableDictionaryRef cacheData = NULL; -CFMutableDictionaryRef cacheData_s = NULL; +CFMutableSetRef changedKeys = NULL; +CFMutableSetRef changedKeys_s = NULL; -CFMutableSetRef changedKeys = NULL; -CFMutableSetRef changedKeys_s = NULL; +CFMutableSetRef deferredRemovals = NULL; +CFMutableSetRef deferredRemovals_s = NULL; -CFMutableSetRef deferredRemovals = NULL; -CFMutableSetRef deferredRemovals_s = NULL; +CFMutableSetRef removedSessionKeys = NULL; +CFMutableSetRef removedSessionKeys_s = NULL; -CFMutableSetRef removedSessionKeys = NULL; -CFMutableSetRef removedSessionKeys_s = NULL; +CFMutableSetRef needsNotification = NULL; -CFMutableSetRef needsNotification = NULL; +int storeLocked = 0; /* > 0 if dynamic store locked */ void -_swapLockedCacheData() +_swapLockedStoreData() { void *temp; - temp = cacheData; - cacheData = cacheData_s; - cacheData_s = temp; + temp = storeData; + storeData = storeData_s; + storeData_s = temp; temp = changedKeys; changedKeys = changedKeys_s; @@ -80,9 +92,9 @@ _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) CFNumberRef refNum; /* - * Get the dictionary associated with this key out of the cache + * Get the dictionary associated with this key out of the store */ - dict = CFDictionaryGetValue(cacheData, watchedKey); + dict = CFDictionaryGetValue(storeData, watchedKey); if (dict) { newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); } else { @@ -137,12 +149,12 @@ _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) CFRelease(newWatcherRefs); /* - * Update the cache for this key + * Update the store for this key */ - CFDictionarySetValue(cacheData, watchedKey, newDict); + CFDictionarySetValue(storeData, watchedKey, newDict); CFRelease(newDict); - SCDLog(LOG_DEBUG, CFSTR(" _addWatcher: %@, %@"), sessionNum, watchedKey); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _addWatcher: %@, %@"), sessionNum, watchedKey); return; } @@ -152,8 +164,8 @@ _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) * _addRegexWatcherByKey() * * This is a CFDictionaryApplierFunction which will iterate over each key - * defined in the "cacheData" dictionary. The arguments are the dictionary - * key, it's associated cache dictionary, and a context structure which + * defined in the "storeData" dictionary. The arguments are the dictionary + * key, it's associated store dictionary, and a context structure which * includes the following: * * 1. the session which has just added a regex notification request @@ -165,12 +177,12 @@ _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) void _addRegexWatcherByKey(const void *key, void *val, void *context) { - CFStringRef cacheStr = key; + CFStringRef storeStr = key; CFDictionaryRef info = val; - mach_port_t sessionID = ((addContextRef)context)->session->server; + mach_port_t sessionID = ((addContextRef)context)->store->server; regex_t *preg = ((addContextRef)context)->preg; - int cacheKeyLen; - char *cacheKey; + int storeKeyLen; + char *storeKey; CFNumberRef sessionNum; int reError; char reErrBuf[256]; @@ -181,22 +193,22 @@ _addRegexWatcherByKey(const void *key, void *val, void *context) return; } - /* convert cache key to C string */ - cacheKeyLen = CFStringGetLength(cacheStr) + 1; - cacheKey = CFAllocatorAllocate(NULL, cacheKeyLen, 0); - if (!CFStringGetCString(cacheStr, cacheKey, cacheKeyLen, kCFStringEncodingMacRoman)) { - SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString: could not convert cache key to C string")); - CFAllocatorDeallocate(NULL, cacheKey); + /* convert store key to C string */ + storeKeyLen = CFStringGetLength(storeStr) + 1; + storeKey = CFAllocatorAllocate(NULL, storeKeyLen, 0); + if (!CFStringGetCString(storeStr, storeKey, storeKeyLen, kCFStringEncodingMacRoman)) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert store key to C string")); + CFAllocatorDeallocate(NULL, storeKey); return; } - /* compare cache key to new notification keys regular expression pattern */ - reError = regexec(preg, cacheKey, 0, NULL, 0); + /* compare store key to new notification keys regular expression pattern */ + reError = regexec(preg, storeKey, 0, NULL, 0); switch (reError) { case 0 : /* we've got a match */ sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionID); - _addWatcher(sessionNum, cacheStr); + _addWatcher(sessionNum, storeStr); CFRelease(sessionNum); break; case REG_NOMATCH : @@ -204,10 +216,10 @@ _addRegexWatcherByKey(const void *key, void *val, void *context) break; default : reErrStrLen = regerror(reError, preg, reErrBuf, sizeof(reErrBuf)); - SCDLog(LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); break; } - CFAllocatorDeallocate(NULL, cacheKey); + CFAllocatorDeallocate(NULL, storeKey); } @@ -216,10 +228,10 @@ _addRegexWatcherByKey(const void *key, void *val, void *context) * * This is a CFDictionaryApplierFunction which will iterate over each session * defined in the "sessionData" dictionary. The arguments are the session - * key, it's associated session dictionary, , and the cache key being added. + * key, it's associated session dictionary, , and the store key being added. * * If an active session includes any regular expression keys which match the - * key being added to the "cacheData" dictionary then we mark this key as being + * key being added to the "storeData" dictionary then we mark this key as being * watched by the session. */ void @@ -250,7 +262,7 @@ _addRegexWatchersBySession(const void *key, void *val, void *context) newKeyLen = CFStringGetLength(addedKey) + 1; newKeyStr = CFAllocatorAllocate(NULL, newKeyLen, 0); if (!CFStringGetCString(addedKey, newKeyStr, newKeyLen, kCFStringEncodingMacRoman)) { - SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString: could not convert new key to C string")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert new key to C string")); CFAllocatorDeallocate(NULL, newKeyStr); return; } @@ -280,7 +292,7 @@ _addRegexWatchersBySession(const void *key, void *val, void *context) break; default : reErrStrLen = regerror(reError, preg, reErrBuf, sizeof(reErrBuf)); - SCDLog(LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); break; } @@ -305,12 +317,12 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) CFNumberRef refNum; /* - * Get the dictionary associated with this key out of the cache + * Get the dictionary associated with this key out of the store */ - dict = CFDictionaryGetValue(cacheData, watchedKey); + dict = CFDictionaryGetValue(storeData, watchedKey); if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDWatchers) == FALSE)) { /* key doesn't exist (isn't this really fatal?) */ - SCDLog(LOG_DEBUG, CFSTR("_removeWatcher: key not present in dictionary.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@, key not watched"), sessionNum, watchedKey); return; } newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); @@ -330,7 +342,7 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) CFRangeMake(0, CFArrayGetCount(newWatchers)), sessionNum); if (i == -1) { - SCDLog(LOG_DEBUG, CFSTR("_removeWatcher: no reference for session %@"), sessionNum); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@, session not watching"), sessionNum, watchedKey); CFRelease(newDict); CFRelease(newWatchers); CFRelease(newWatcherRefs); @@ -364,14 +376,14 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) if (CFDictionaryGetCount(newDict) > 0) { /* if this key is still active */ - CFDictionarySetValue(cacheData, watchedKey, newDict); + CFDictionarySetValue(storeData, watchedKey, newDict); } else { /* no information left, remove the empty dictionary */ - CFDictionaryRemoveValue(cacheData, watchedKey); + CFDictionaryRemoveValue(storeData, watchedKey); } CFRelease(newDict); - SCDLog(LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@"), sessionNum, watchedKey); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@"), sessionNum, watchedKey); return; } @@ -381,8 +393,8 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) * _removeRegexWatcherByKey() * * This is a CFDictionaryApplierFunction which will iterate over each key - * defined in the "cacheData" dictionary. The arguments are the dictionary - * key, it's associated cache dictionary, and a context structure which + * defined in the "storeData" dictionary. The arguments are the dictionary + * key, it's associated store dictionary, and a context structure which * includes the following: * * 1. the session which has just removed a regex notification request @@ -394,14 +406,14 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) void _removeRegexWatcherByKey(const void *key, void *val, void *context) { - CFStringRef cacheStr = key; + CFStringRef storeStr = key; CFDictionaryRef info = val; - mach_port_t sessionID = ((removeContextRef)context)->session->server; + mach_port_t sessionID = ((removeContextRef)context)->store->server; regex_t *preg = ((removeContextRef)context)->preg; CFNumberRef sessionNum; CFArrayRef watchers; - int cacheKeyLen; - char *cacheKey; + int storeKeyLen; + char *storeKey; int reError; char reErrBuf[256]; int reErrStrLen; @@ -423,31 +435,31 @@ _removeRegexWatcherByKey(const void *key, void *val, void *context) } /* convert key to C string */ - cacheKeyLen = CFStringGetLength(cacheStr) + 1; - cacheKey = CFAllocatorAllocate(NULL, cacheKeyLen, 0); - if (!CFStringGetCString(cacheStr, cacheKey, cacheKeyLen, kCFStringEncodingMacRoman)) { - SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString: could not convert key to C string")); - CFAllocatorDeallocate(NULL, cacheKey); + storeKeyLen = CFStringGetLength(storeStr) + 1; + storeKey = CFAllocatorAllocate(NULL, storeKeyLen, 0); + if (!CFStringGetCString(storeStr, storeKey, storeKeyLen, kCFStringEncodingMacRoman)) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert key to C string")); + CFAllocatorDeallocate(NULL, storeKey); CFRelease(sessionNum); return; } /* check if this key matches the regular expression */ - reError = regexec(preg, cacheKey, 0, NULL, 0); + reError = regexec(preg, storeKey, 0, NULL, 0); switch (reError) { case 0 : /* we've got a match */ - _removeWatcher(sessionNum, cacheStr); + _removeWatcher(sessionNum, storeStr); break; case REG_NOMATCH : /* no match */ break; default : reErrStrLen = regerror(reError, preg, reErrBuf, sizeof(reErrBuf)); - SCDLog(LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); break; } - CFAllocatorDeallocate(NULL, cacheKey); + CFAllocatorDeallocate(NULL, storeKey); CFRelease(sessionNum); } @@ -457,10 +469,10 @@ _removeRegexWatcherByKey(const void *key, void *val, void *context) * * This is a CFDictionaryApplierFunction which will iterate over each session * defined in the "sessionData" dictionary. The arguments are the session - * key, it's associated session dictionary, and the cache key being removed. + * key, it's associated session dictionary, and the store key being removed. * * If an active session includes any regular expression keys which match the - * key being removed from the "cacheData" dictionary then we clear this keys + * key being removed from the "storeData" dictionary then we clear this keys * reference of being watched. */ void @@ -491,7 +503,7 @@ _removeRegexWatchersBySession(const void *key, void *val, void *context) oldKeyLen = CFStringGetLength(removedKey) + 1; oldKeyStr = CFAllocatorAllocate(NULL, oldKeyLen, 0); if (!CFStringGetCString(removedKey, oldKeyStr, oldKeyLen, kCFStringEncodingMacRoman)) { - SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString: could not convert old key to C string")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert old key to C string")); CFAllocatorDeallocate(NULL, oldKeyStr); return; } @@ -521,7 +533,7 @@ _removeRegexWatchersBySession(const void *key, void *val, void *context) break; default : reErrStrLen = regerror(reError, preg, reErrBuf, sizeof(reErrBuf)); - SCDLog(LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); break; } diff --git a/configd.tproj/_SCD.h b/configd.tproj/_SCD.h index 32cf319..a2525a5 100644 --- a/configd.tproj/_SCD.h +++ b/configd.tproj/_SCD.h @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * June 2, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _S_SCD_H #define _S_SCD_H @@ -28,7 +38,7 @@ /* - * keys in the "cacheData" dictionary + * keys in the "storeData" dictionary */ /* @@ -76,14 +86,15 @@ #define kSCDSessionKeys CFSTR("sessionKeys") -extern CFMutableDictionaryRef cacheData; +extern int storeLocked; +extern CFMutableDictionaryRef storeData; extern CFMutableDictionaryRef sessionData; extern CFMutableSetRef changedKeys; extern CFMutableSetRef deferredRemovals; extern CFMutableSetRef removedSessionKeys; extern CFMutableSetRef needsNotification; -extern CFMutableDictionaryRef cacheData_s; +extern CFMutableDictionaryRef storeData_s; extern CFMutableSetRef changedKeys_s; extern CFMutableSetRef deferredRemovals_s; extern CFMutableSetRef removedSessionKeys_s; @@ -93,109 +104,136 @@ extern CFMutableSetRef removedSessionKeys_s; * _addRegexWatcherBySession(), and _removeRegexWatcherByKey() functions. */ typedef struct { - SCDSessionPrivateRef session; - regex_t *preg; + SCDynamicStorePrivateRef store; + regex_t *preg; } addContext, *addContextRef; typedef struct { - SCDSessionPrivateRef session; - regex_t *preg; + SCDynamicStorePrivateRef store; + regex_t *preg; } removeContext, *removeContextRef; __BEGIN_DECLS -SCDStatus _SCDOpen __P((SCDSessionRef *session, - CFStringRef name)); - -SCDStatus _SCDClose __P((SCDSessionRef *session)); - -SCDStatus _SCDLock __P((SCDSessionRef session)); - -SCDStatus _SCDUnlock __P((SCDSessionRef session)); - -SCDStatus _SCDList __P((SCDSessionRef session, - CFStringRef key, - int regexOptions, - CFArrayRef *subKeys)); - -SCDStatus _SCDAdd __P((SCDSessionRef session, - CFStringRef key, - SCDHandleRef handle)); - -SCDStatus _SCDAddSession __P((SCDSessionRef session, - CFStringRef key, - SCDHandleRef handle)); - -SCDStatus _SCDGet __P((SCDSessionRef session, - CFStringRef key, - SCDHandleRef *handle)); - -SCDStatus _SCDSet __P((SCDSessionRef session, - CFStringRef key, - SCDHandleRef handle)); - -SCDStatus _SCDRemove __P((SCDSessionRef session, - CFStringRef key)); - -SCDStatus _SCDTouch __P((SCDSessionRef session, - CFStringRef key)); - -SCDStatus _SCDSnapshot __P((SCDSessionRef session)); - -SCDStatus _SCDNotifierList __P((SCDSessionRef session, - int regexOptions, - CFArrayRef *notifierKeys)); - -SCDStatus _SCDNotifierAdd __P((SCDSessionRef session, - CFStringRef key, - int regexOptions)); - -SCDStatus _SCDNotifierRemove __P((SCDSessionRef session, - CFStringRef key, - int regexOptions)); - -SCDStatus _SCDNotifierGetChanges __P((SCDSessionRef session, - CFArrayRef *notifierKeys)); - -SCDStatus _SCDNotifierInformViaMachPort __P((SCDSessionRef session, - mach_msg_id_t msgid, - mach_port_t *port)); - -SCDStatus _SCDNotifierInformViaFD __P((SCDSessionRef session, - int32_t identifier, - int *fd)); - -SCDStatus _SCDNotifierInformViaSignal __P((SCDSessionRef session, - pid_t pid, - int sig)); - -SCDStatus _SCDNotifierCancel __P((SCDSessionRef session)); - -void _swapLockedCacheData __P(()); - -void _addWatcher __P((CFNumberRef sessionNum, - CFStringRef watchedKey)); - -void _addRegexWatcherByKey __P((const void *key, - void *val, - void *context)); - -void _addRegexWatchersBySession __P((const void *key, - void *val, - void *context)); - -void _removeWatcher __P((CFNumberRef sessionNum, - CFStringRef watchedKey)); - -void _removeRegexWatcherByKey __P((const void *key, - void *val, - void *context)); - -void _removeRegexWatchersBySession __P((const void *key, - void *val, - void *context)); +int +__SCDynamicStoreOpen (SCDynamicStoreRef *store, + CFStringRef name); +int +__SCDynamicStoreClose (SCDynamicStoreRef *store); + +int +__SCDynamicStoreLock (SCDynamicStoreRef store, + Boolean recursive); + +int +__SCDynamicStoreUnlock (SCDynamicStoreRef store, + Boolean recursive); + +int +__SCDynamicStoreCopyKeyList (SCDynamicStoreRef store, + CFStringRef prefix, + Boolean isRegex, + CFArrayRef *subKeys); + +int +__SCDynamicStoreAddValue (SCDynamicStoreRef store, + CFStringRef key, + CFPropertyListRef value); + +int +__SCDynamicStoreAddTemporaryValue (SCDynamicStoreRef store, + CFStringRef key, + CFPropertyListRef value); + +int +__SCDynamicStoreCopyValue (SCDynamicStoreRef store, + CFStringRef key, + CFPropertyListRef *value); + +int +__SCDynamicStoreSetValue (SCDynamicStoreRef store, + CFStringRef key, + CFPropertyListRef value); + +int +__SCDynamicStoreRemoveValue (SCDynamicStoreRef store, + CFStringRef key); + +int +__SCDynamicStoreTouchValue (SCDynamicStoreRef store, + CFStringRef key); + +int +__SCDynamicStoreNotifyValue (SCDynamicStoreRef store, + CFStringRef key); + +int +__SCDynamicStoreSnapshot (SCDynamicStoreRef store); + +int +__SCDynamicStoreAddWatchedKey (SCDynamicStoreRef store, + CFStringRef key, + Boolean isRegex); + +int +__SCDynamicStoreRemoveWatchedKey (SCDynamicStoreRef store, + CFStringRef key, + Boolean isRegex); + +int +__SCDynamicStoreCopyNotifiedKeys (SCDynamicStoreRef store, + CFArrayRef *notifierKeys); + +int +__SCDynamicStoreNotifyMachPort (SCDynamicStoreRef store, + mach_msg_id_t msgid, + mach_port_t *port); + +int +__SCDynamicStoreNotifyFileDescriptor (SCDynamicStoreRef store, + int32_t identifier, + int *fd); + +int +__SCDynamicStoreNotifySignal (SCDynamicStoreRef store, + pid_t pid, + int sig); + +int +__SCDynamicStoreNotifyCancel (SCDynamicStoreRef store); + +void +_swapLockedStoreData (); + +void +_addWatcher (CFNumberRef sessionNum, + CFStringRef watchedKey); + +void +_addRegexWatcherByKey (const void *key, + void *val, + void *context); + +void +_addRegexWatchersBySession (const void *key, + void *val, + void *context); + +void +_removeWatcher (CFNumberRef sessionNum, + CFStringRef watchedKey); + +void +_removeRegexWatcherByKey (const void *key, + void *val, + void *context); + +void +_removeRegexWatchersBySession (const void *key, + void *val, + void *context); __END_DECLS diff --git a/configd.tproj/_configadd.c b/configd.tproj/_configadd.c index 76a9dfb..d06abd1 100644 --- a/configd.tproj/_configadd.c +++ b/configd.tproj/_configadd.c @@ -20,71 +20,74 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDAdd(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) +int +__SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - SCDStatus scd_status = SCD_OK; - boolean_t wasLocked; - SCDHandleRef tempHandle; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + int sc_status = kSCStatusOK; + CFPropertyListRef tempValue; - SCDLog(LOG_DEBUG, CFSTR("_SCDAdd:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" data = %@"), SCDHandleGetData(handle)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreAddValue:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } /* - * 1. Determine if the cache lock is currently held - * and acquire the lock if necessary. + * 1. Ensure that we hold the lock. */ - wasLocked = SCDOptionGet(NULL, kSCDOptionIsLocked); - if (!wasLocked) { - scd_status = _SCDLock(session); - if (scd_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" _SCDLock(): %s"), SCDError(scd_status)); - return scd_status; - } + sc_status = __SCDynamicStoreLock(store, TRUE); + if (sc_status != kSCStatusOK) { + return sc_status; } /* * 2. Ensure that this is a new key. */ - scd_status = _SCDGet(session, key, &tempHandle); - switch (scd_status) { - case SCD_NOKEY : - /* cache key does not exist, proceed */ + sc_status = __SCDynamicStoreCopyValue(store, key, &tempValue); + switch (sc_status) { + case kSCStatusNoKey : + /* store key does not exist, proceed */ break; - case SCD_OK : - /* cache key exists, sorry */ - SCDHandleRelease(tempHandle); - scd_status = SCD_EXISTS; + case kSCStatusOK : + /* store key exists, sorry */ + CFRelease(tempValue); + sc_status = kSCStatusKeyExists; goto done; default : - SCDLog(LOG_DEBUG, CFSTR(" _SCDGet(): %s"), SCDError(scd_status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _SCDGet(): %s"), SCErrorString(sc_status)); goto done; } /* * 3. Save the new key. */ - scd_status = _SCDSet(session, key, handle); + sc_status = __SCDynamicStoreSetValue(store, key, value); /* - * 4. Release the lock if we acquired it as part of this request. + * 4. Release our lock. */ done: - if (!wasLocked) - _SCDUnlock(session); + __SCDynamicStoreUnlock(store, TRUE); - return scd_status; + return sc_status; } @@ -95,7 +98,7 @@ _configadd(mach_port_t server, xmlData_t dataRef, /* raw XML bytes */ mach_msg_type_number_t dataLen, int *newInstance, - int *scd_status + int *sc_status ) { kern_return_t status; @@ -104,17 +107,18 @@ _configadd(mach_port_t server, CFStringRef key; /* key (un-serialized) */ CFDataRef xmlData; /* data (XML serialized) */ CFPropertyListRef data; /* data (un-serialized) */ - SCDHandleRef handle; CFStringRef xmlError; - SCDLog(LOG_DEBUG, CFSTR("Add key to configuration database.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Add key to configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + + *sc_status = kSCStatusOK; /* un-serialize the key */ 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)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } key = CFPropertyListCreateFromXMLData(NULL, @@ -122,17 +126,23 @@ _configadd(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlKey); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError); - *scd_status = SCD_FAILED; - return KERN_SUCCESS; + if (!key) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() key: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFString(key)) { + *sc_status = kSCStatusInvalidArgument; } /* un-serialize the data */ xmlData = CFDataCreate(NULL, dataRef, dataLen); status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } data = CFPropertyListCreateFromXMLData(NULL, @@ -140,20 +150,27 @@ _configadd(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlData); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() data: %s"), xmlError); - CFRelease(key); - *scd_status = SCD_FAILED; - return KERN_SUCCESS; + if (!data) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() data: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFPropertyList(data)) { + *sc_status = kSCStatusInvalidArgument; } - handle = SCDHandleInit(); - SCDHandleSetData(handle, data); - *scd_status = _SCDAdd(mySession->session, key, handle); - if (*scd_status == SCD_OK) { - *newInstance = SCDHandleGetInstance(handle); + if (*sc_status != kSCStatusOK) { + if (key) CFRelease(key); + if (data) CFRelease(data); + return KERN_SUCCESS; } - SCDHandleRelease(handle); + + *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data); + *newInstance = 0; + CFRelease(key); CFRelease(data); diff --git a/configd.tproj/_configadd_s.c b/configd.tproj/_configadd_s.c index 8e54070..c09c478 100644 --- a/configd.tproj/_configadd_s.c +++ b/configd.tproj/_configadd_s.c @@ -20,41 +20,51 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * October 17, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDAddSession(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) +int +__SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - SCDStatus scd_status = SCD_OK; - CFStringRef sessionKey; - CFDictionaryRef dict; - CFMutableDictionaryRef newDict; - CFArrayRef keys; - CFMutableArrayRef newKeys; - - SCDLog(LOG_DEBUG, CFSTR("_SCDAddSession:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" data = %@"), SCDHandleGetData(handle)); - - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + int sc_status = kSCStatusOK; + CFStringRef sessionKey; + CFDictionaryRef dict; + CFMutableDictionaryRef newDict; + CFArrayRef keys; + CFMutableArrayRef newKeys; + + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreAddTemporaryValue:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); + + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } /* * 1. Add the key */ - scd_status = _SCDAdd(session, key, handle); - if (scd_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" _SCDAdd(): %s"), SCDError(scd_status)); - return scd_status; + sc_status = __SCDynamicStoreAddValue(store, key, value); + if (sc_status != kSCStatusOK) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreAddValue(): %s"), SCErrorString(sc_status)); + return sc_status; } /* * 2. Create the session key */ - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server); + sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); /* * 3. Add this key to my list of per-session keys @@ -89,14 +99,14 @@ _SCDAddSession(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) /* * 4. Mark the key as a "session" key and track the creator. */ - dict = CFDictionaryGetValue(cacheData, key); + dict = CFDictionaryGetValue(storeData, key); newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); CFDictionarySetValue(newDict, kSCDSession, sessionKey); - CFDictionarySetValue(cacheData, key, newDict); + CFDictionarySetValue(storeData, key, newDict); CFRelease(newDict); CFRelease(sessionKey); - return scd_status; + return sc_status; } @@ -107,7 +117,7 @@ _configadd_s(mach_port_t server, xmlData_t dataRef, /* raw XML bytes */ mach_msg_type_number_t dataLen, int *newInstance, - int *scd_status + int *sc_status ) { kern_return_t status; @@ -116,17 +126,18 @@ _configadd_s(mach_port_t server, CFStringRef key; /* key (un-serialized) */ CFDataRef xmlData; /* data (XML serialized) */ CFPropertyListRef data; /* data (un-serialized) */ - SCDHandleRef handle; CFStringRef xmlError; - SCDLog(LOG_DEBUG, CFSTR("Add (session) key to configuration database.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Add (session) key to configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + + *sc_status = kSCStatusOK; /* un-serialize the key */ 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)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } key = CFPropertyListCreateFromXMLData(NULL, @@ -134,17 +145,23 @@ _configadd_s(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlKey); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError); - *scd_status = SCD_FAILED; - return KERN_SUCCESS; + if (!key) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() key: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFString(key)) { + *sc_status = kSCStatusInvalidArgument; } /* un-serialize the data */ xmlData = CFDataCreate(NULL, dataRef, dataLen); status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } data = CFPropertyListCreateFromXMLData(NULL, @@ -152,20 +169,28 @@ _configadd_s(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlData); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() data: %s"), xmlError); - CFRelease(key); - *scd_status = SCD_FAILED; + if (!data) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() data: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFPropertyList(data)) { + *sc_status = kSCStatusInvalidArgument; + } + + if (*sc_status != kSCStatusOK) { + if (key) CFRelease(key); + if (data) CFRelease(data); return KERN_SUCCESS; } - handle = SCDHandleInit(); - SCDHandleSetData(handle, data); - *scd_status = _SCDAddSession(mySession->session, key, handle); - if (*scd_status == SCD_OK) { - *newInstance = SCDHandleGetInstance(handle); + *sc_status = __SCDynamicStoreAddTemporaryValue(mySession->store, key, data); + if (*sc_status == kSCStatusOK) { + *newInstance = 1; } - SCDHandleRelease(handle); CFRelease(key); CFRelease(data); diff --git a/configd.tproj/_configclose.c b/configd.tproj/_configclose.c index afba5bb..d623f85 100644 --- a/configd.tproj/_configclose.c +++ b/configd.tproj/_configclose.c @@ -20,30 +20,40 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include "configd.h" #include "session.h" -static boolean_t +static Boolean isMySessionKey(CFStringRef sessionKey, CFStringRef key) { CFDictionaryRef dict; - CFStringRef cacheSessionKey; + CFStringRef storeSessionKey; - dict = CFDictionaryGetValue(cacheData, key); + dict = CFDictionaryGetValue(storeData, key); if (!dict) { /* if key no longer exists */ return FALSE; } - cacheSessionKey = CFDictionaryGetValue(dict, kSCDSession); - if (!cacheSessionKey) { + storeSessionKey = CFDictionaryGetValue(dict, kSCDSession); + if (!storeSessionKey) { /* if this is not a session key */ return FALSE; } - if (!CFEqual(sessionKey, cacheSessionKey)) { + if (!CFEqual(sessionKey, storeSessionKey)) { /* if this is not "my" session key */ return FALSE; } @@ -52,113 +62,113 @@ isMySessionKey(CFStringRef sessionKey, CFStringRef key) } -SCDStatus -_SCDClose(SCDSessionRef *session) +int +__SCDynamicStoreClose(SCDynamicStoreRef *store) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)*session; - CFIndex keyCnt; - CFStringRef sessionKey; - CFDictionaryRef dict; - CFArrayRef keys; - serverSessionRef mySession; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)*store; + CFIndex keyCnt; + CFStringRef sessionKey; + CFDictionaryRef dict; + CFArrayRef keys; + serverSessionRef mySession; - SCDLog(LOG_DEBUG, CFSTR("_SCDClose:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreClose:")); - if ((*session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; + if ((*store == NULL) || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } /* Remove notification keys */ - if ((keyCnt = CFSetGetCount(sessionPrivate->keys)) > 0) { + if ((keyCnt = CFSetGetCount(storePrivate->keys)) > 0) { void **watchedKeys; CFArrayRef keysToRemove; CFIndex i; watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); - CFSetGetValues(sessionPrivate->keys, watchedKeys); + CFSetGetValues(storePrivate->keys, watchedKeys); keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks); CFAllocatorDeallocate(NULL, watchedKeys); for (i=0; ireKeys)) > 0) { + if ((keyCnt = CFSetGetCount(storePrivate->reKeys)) > 0) { void **watchedKeys; CFArrayRef keysToRemove; CFIndex i; watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); - CFSetGetValues(sessionPrivate->reKeys, watchedKeys); + CFSetGetValues(storePrivate->reKeys, watchedKeys); keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks); CFAllocatorDeallocate(NULL, watchedKeys); for (i=0; iserver); + sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); dict = CFDictionaryGetValue(sessionData, sessionKey); keys = CFDictionaryGetValue(dict, kSCDSessionKeys); if (keys && ((keyCnt = CFArrayGetCount(keys)) > 0)) { - boolean_t wasLocked; - CFIndex i; + Boolean wasLocked; + CFIndex i; /* * if necessary, claim a lock to ensure that we inform * any processes that a session key was removed. */ - wasLocked = SCDOptionGet(NULL, kSCDOptionIsLocked); + wasLocked = (storeLocked > 0); if (!wasLocked) { - (void) _SCDLock(*session); + (void) __SCDynamicStoreLock(*store, FALSE); } - /* remove keys from "locked" cache" */ + /* remove keys from "locked" store" */ for (i=0; ilocked) { + (void) __SCDynamicStoreUnlock(*store, FALSE); } /* - * Invalidate the server port (for this client) which will result - * in the removal of any associated run loop sources. + * Remove the run loop source on the server port (for this + * client). Then, invalidate and release the port. */ - mySession = getSession(sessionPrivate->server); + mySession = getSession(storePrivate->server); if (mySession->serverRunLoopSource) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mySession->serverRunLoopSource, @@ -168,29 +178,28 @@ _SCDClose(SCDSessionRef *session) CFMachPortInvalidate(mySession->serverPort); CFRelease(mySession->serverPort); - CFRelease(sessionPrivate->keys); - CFRelease(sessionPrivate->reKeys); - CFAllocatorDeallocate(NULL, sessionPrivate); - *session = NULL; + storePrivate->server = MACH_PORT_NULL; + CFRelease(*store); + *store = NULL; - return SCD_OK; + return kSCStatusOK; } kern_return_t -_configclose(mach_port_t server, int *scd_status) +_configclose(mach_port_t server, int *sc_status) { serverSessionRef mySession = getSession(server); - SCDLog(LOG_DEBUG, CFSTR("Close session.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Close session.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); /* * Close the session. */ - *scd_status = _SCDClose(&mySession->session); - if (*scd_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" _SCDClose(): %s"), SCDError(*scd_status)); + *sc_status = __SCDynamicStoreClose(&mySession->store); + if (*sc_status != kSCStatusOK) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreClose(): %s"), SCErrorString(*sc_status)); return KERN_SUCCESS; } diff --git a/configd.tproj/_configget.c b/configd.tproj/_configget.c index 7b1e64d..48bab88 100644 --- a/configd.tproj/_configget.c +++ b/configd.tproj/_configget.c @@ -20,48 +20,46 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDGet(SCDSessionRef session, CFStringRef key, SCDHandleRef *handle) +int +__SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef *value) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - CFDictionaryRef dict; - CFNumberRef num; - int dictInstance; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + CFDictionaryRef dict; - SCDLog(LOG_DEBUG, CFSTR("_SCDGet:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyValue:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } - dict = CFDictionaryGetValue(cacheData, key); + dict = CFDictionaryGetValue(storeData, key); if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDData) == FALSE)) { /* key doesn't exist (or data never defined) */ - return SCD_NOKEY; + return kSCStatusNoKey; } - /* Create a new handle associated with the cached data */ - *handle = SCDHandleInit(); - /* Return the data associated with the key */ - SCDHandleSetData(*handle, CFDictionaryGetValue(dict, kSCDData)); - - /* Return the instance number associated with the key */ - num = CFDictionaryGetValue(dict, kSCDInstance); - (void) CFNumberGetValue(num, kCFNumberIntType, &dictInstance); - _SCDHandleSetInstance(*handle, dictInstance); + *value = CFRetain(CFDictionaryGetValue(dict, kSCDData)); - SCDLog(LOG_DEBUG, CFSTR(" data = %@"), SCDHandleGetData(*handle)); - SCDLog(LOG_DEBUG, CFSTR(" instance = %d"), SCDHandleGetInstance(*handle)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" value = %@"), *value); - return SCD_OK; + return kSCStatusOK; } - kern_return_t _configget(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -69,7 +67,7 @@ _configget(mach_port_t server, xmlDataOut_t *dataRef, /* raw XML bytes */ mach_msg_type_number_t *dataLen, int *newInstance, - int *scd_status + int *sc_status ) { kern_return_t status; @@ -77,17 +75,17 @@ _configget(mach_port_t server, CFDataRef xmlKey; /* key (XML serialized) */ CFStringRef key; /* key (un-serialized) */ CFDataRef xmlData; /* data (XML serialized) */ - SCDHandleRef handle; + CFPropertyListRef value; CFStringRef xmlError; - SCDLog(LOG_DEBUG, CFSTR("Get key from configuration database.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Get key from configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); /* un-serialize the key */ 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)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } key = CFPropertyListCreateFromXMLData(NULL, @@ -95,15 +93,23 @@ _configget(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlKey); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError); - *scd_status = SCD_FAILED; + if (!key) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() key: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + return KERN_SUCCESS; + } else if (!isA_CFString(key)) { + *sc_status = kSCStatusInvalidArgument; return KERN_SUCCESS; } - *scd_status = _SCDGet(mySession->session, key, &handle); + *sc_status = __SCDynamicStoreCopyValue(mySession->store, key, &value); CFRelease(key); - if (*scd_status != SCD_OK) { + if (*sc_status != kSCStatusOK) { *dataRef = NULL; *dataLen = 0; return KERN_SUCCESS; @@ -113,12 +119,13 @@ _configget(mach_port_t server, * serialize the data, copy it into an allocated buffer which will be * released when it is returned as part of a Mach message. */ - xmlData = CFPropertyListCreateXMLData(NULL, SCDHandleGetData(handle)); + xmlData = CFPropertyListCreateXMLData(NULL, value); + CFRelease(value); *dataLen = CFDataGetLength(xmlData); status = vm_allocate(mach_task_self(), (void *)dataRef, *dataLen, TRUE); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status)); - *scd_status = SCD_FAILED; + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status)); + *sc_status = kSCStatusFailed; CFRelease(xmlData); *dataRef = NULL; *dataLen = 0; @@ -131,9 +138,194 @@ _configget(mach_port_t server, /* * return the instance number associated with the returned data. */ - *newInstance = SCDHandleGetInstance(handle); + *newInstance = 1; + + return KERN_SUCCESS; +} + +/* + * "context" argument for addSpecificKey() and addSpecificPattern() + */ +typedef struct { + SCDynamicStoreRef store; + CFMutableDictionaryRef dict; +} addSpecific, *addSpecificRef; + +static void +addSpecificKey(const void *value, void *context) +{ + CFStringRef key = (CFStringRef)value; + addSpecificRef myContextRef = (addSpecificRef)context; + int sc_status; + CFPropertyListRef data; - SCDHandleRelease(handle); + if (!isA_CFString(key)) { + return; + } + + sc_status = __SCDynamicStoreCopyValue(myContextRef->store, key, &data); + if (sc_status == kSCStatusOK) { + CFDictionaryAddValue(myContextRef->dict, key, data); + CFRelease(data); + } + + return; +} + +static void +addSpecificPattern(const void *value, void *context) +{ + CFStringRef pattern = (CFStringRef)value; + addSpecificRef myContextRef = (addSpecificRef)context; + int sc_status; + CFArrayRef keys; + + if (!isA_CFString(pattern)) { + return; + } + + sc_status = __SCDynamicStoreCopyKeyList(myContextRef->store, pattern, TRUE, &keys); + if (sc_status == kSCStatusOK) { + CFArrayApplyFunction(keys, + CFRangeMake(0, CFArrayGetCount(keys)), + addSpecificKey, + context); + CFRelease(keys); + } + + return; +} + +kern_return_t +_configget_m(mach_port_t server, + xmlData_t keysRef, + mach_msg_type_number_t keysLen, + xmlData_t patternsRef, + mach_msg_type_number_t patternsLen, + xmlDataOut_t *dataRef, + mach_msg_type_number_t *dataLen, + int *sc_status) +{ + kern_return_t status; + serverSessionRef mySession = getSession(server); + CFArrayRef keys = NULL; /* keys (un-serialized) */ + CFArrayRef patterns = NULL; /* patterns (un-serialized) */ + CFDataRef xmlData; /* data (XML serialized) */ + addSpecific myContext; + + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Get key from configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + + *sc_status = kSCStatusOK; + + if (keysRef && (keysLen > 0)) { + CFDataRef xmlKeys; /* keys (XML serialized) */ + CFStringRef xmlError; + + /* un-serialize the keys */ + xmlKeys = CFDataCreate(NULL, keysRef, keysLen); + status = vm_deallocate(mach_task_self(), (vm_address_t)keysRef, keysLen); + if (status != KERN_SUCCESS) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + /* non-fatal???, proceed */ + } + keys = CFPropertyListCreateFromXMLData(NULL, + xmlKeys, + kCFPropertyListImmutable, + &xmlError); + CFRelease(xmlKeys); + if (!keys) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() keys: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFArray(keys)) { + *sc_status = kSCStatusInvalidArgument; + } + } + + if (patternsRef && (patternsLen > 0)) { + CFDataRef xmlPatterns; /* patterns (XML serialized) */ + CFStringRef xmlError; + + /* un-serialize the patterns */ + xmlPatterns = CFDataCreate(NULL, patternsRef, patternsLen); + status = vm_deallocate(mach_task_self(), (vm_address_t)patternsRef, patternsLen); + if (status != KERN_SUCCESS) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + /* non-fatal???, proceed */ + } + patterns = CFPropertyListCreateFromXMLData(NULL, + xmlPatterns, + kCFPropertyListImmutable, + &xmlError); + CFRelease(xmlPatterns); + if (!patterns) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() patterns: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFArray(patterns)) { + *sc_status = kSCStatusInvalidArgument; + } + } + + if (*sc_status != kSCStatusOK) { + if (keys) CFRelease(keys); + if (patterns) CFRelease(patterns); + *dataRef = NULL; + *dataLen = 0; + return KERN_SUCCESS; + } + + myContext.store = mySession->store; + myContext.dict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (keys) { + CFArrayApplyFunction(keys, + CFRangeMake(0, CFArrayGetCount(keys)), + addSpecificKey, + &myContext); + CFRelease(keys); + } + + if (patterns) { + CFArrayApplyFunction(patterns, + CFRangeMake(0, CFArrayGetCount(patterns)), + addSpecificPattern, + &myContext); + CFRelease(patterns); + } + + /* + * serialize the dictionary of matching keys/patterns, copy it into an + * allocated buffer which will be released when it is returned as part + * of a Mach message. + */ + xmlData = CFPropertyListCreateXMLData(NULL, myContext.dict); + CFRelease(myContext.dict); + *dataLen = CFDataGetLength(xmlData); + status = vm_allocate(mach_task_self(), (void *)dataRef, *dataLen, TRUE); + if (status != KERN_SUCCESS) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status)); + *sc_status = kSCStatusFailed; + CFRelease(xmlData); + *dataRef = NULL; + *dataLen = 0; + return KERN_SUCCESS; + } + + bcopy((char *)CFDataGetBytePtr(xmlData), *dataRef, *dataLen); + CFRelease(xmlData); return KERN_SUCCESS; } diff --git a/configd.tproj/_configlist.c b/configd.tproj/_configlist.c index 85286c3..6613f8a 100644 --- a/configd.tproj/_configlist.c +++ b/configd.tproj/_configlist.c @@ -20,102 +20,128 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDList(SCDSessionRef session, CFStringRef key, int regexOptions, CFArrayRef *subKeys) +int +__SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, CFArrayRef *subKeys) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - CFIndex cacheCnt; - void **cacheKeys; - void **cacheValues; - CFMutableArrayRef keyArray; - int i; - CFStringRef cacheStr; - CFDictionaryRef cacheValue; - int regexStrLen; - char *regexStr = NULL; - regex_t preg; - int reError; - char reErrBuf[256]; - int reErrStrLen; - - SCDLog(LOG_DEBUG, CFSTR("_SCDList:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" regexOptions = %0o"), regexOptions); - - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + CFIndex storeCnt; + void **storeKeys; + void **storeValues; + CFMutableArrayRef keyArray; + int i; + CFStringRef storeStr; + CFDictionaryRef storeValue; + int regexBufLen; + char *regexBuf = NULL; + regex_t preg; + int reError; + char reErrBuf[256]; + int reErrStrLen; + + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList:")); + 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; /* you must have an open session to play */ } - cacheCnt = CFDictionaryGetCount(cacheData); - keyArray = CFArrayCreateMutable(NULL, cacheCnt, &kCFTypeArrayCallBacks); + storeCnt = CFDictionaryGetCount(storeData); + keyArray = CFArrayCreateMutable(NULL, storeCnt, &kCFTypeArrayCallBacks); + + if (isRegex) { + UniChar ch_s = 0; + UniChar ch_e = 0; + Boolean ok; + CFIndex regexLen; + CFMutableStringRef regexStr; + + regexStr = CFStringCreateMutableCopy(NULL, 0, key); + regexLen = CFStringGetLength(regexStr); + if (regexLen > 0) { + ch_s = CFStringGetCharacterAtIndex(regexStr, 0); + ch_e = CFStringGetCharacterAtIndex(regexStr, regexLen - 1); + } + if ((regexLen == 0) || ((ch_s != (UniChar)'^') && (ch_e != (UniChar)'$'))) { + /* if regex pattern is not already bounded */ + CFStringInsert(regexStr, 0, CFSTR("^")); + CFStringAppend(regexStr, CFSTR("$")); + } - if (regexOptions & kSCDRegexKey) { /* * compile the provided regular expression using the - * provided regexOptions (passing only those flags - * which would make sense). + * provided isRegex. */ - regexStrLen = CFStringGetLength(key) + 1; - regexStr = CFAllocatorAllocate(NULL, regexStrLen, 0); - if (!CFStringGetCString(key, - regexStr, - regexStrLen, - kCFStringEncodingMacRoman)) { - SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString() key: could not convert to regex string")); - CFAllocatorDeallocate(NULL, regexStr); - return SCD_FAILED; + regexBufLen = CFStringGetLength(regexStr)+1; + regexBuf = CFAllocatorAllocate(NULL, regexBufLen, 0); + ok = CFStringGetCString(regexStr, regexBuf, regexBufLen, kCFStringEncodingMacRoman); + CFRelease(regexStr); + if (!ok) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString() key: could not convert to regex string")); + CFAllocatorDeallocate(NULL, regexBuf); + return kSCStatusFailed; } - reError = regcomp(&preg, regexStr, REG_EXTENDED); + reError = regcomp(&preg, regexBuf, REG_EXTENDED); if (reError != 0) { reErrStrLen = regerror(reError, &preg, reErrBuf, sizeof(reErrBuf)); - cacheStr = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingMacRoman); - CFArrayAppendValue(keyArray, cacheStr); - CFRelease(cacheStr); + storeStr = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingMacRoman); + CFArrayAppendValue(keyArray, storeStr); + CFRelease(storeStr); *subKeys = CFArrayCreateCopy(NULL, keyArray); CFRelease(keyArray); - CFAllocatorDeallocate(NULL, regexStr); - return SCD_FAILED; + CFAllocatorDeallocate(NULL, regexBuf); + return kSCStatusFailed; } } - cacheKeys = CFAllocatorAllocate(NULL, cacheCnt * sizeof(CFStringRef), 0); - cacheValues = CFAllocatorAllocate(NULL, cacheCnt * sizeof(CFStringRef), 0); - CFDictionaryGetKeysAndValues(cacheData, cacheKeys, cacheValues); - for (i=0; isession, key, regexOptions, &subKeys); + *sc_status = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex, &subKeys); CFRelease(key); - if (*scd_status != SCD_OK) { - *listRef = NULL; - *listLen = 0; + if (*sc_status != kSCStatusOK) { return KERN_SUCCESS; } @@ -213,8 +246,8 @@ _configlist(mach_port_t server, *listLen = CFDataGetLength(xmlList); status = vm_allocate(mach_task_self(), (void *)listRef, *listLen, TRUE); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status)); - *scd_status = SCD_FAILED; + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status)); + *sc_status = kSCStatusFailed; CFRelease(xmlList); *listRef = NULL; *listLen = 0; diff --git a/configd.tproj/_configlock.c b/configd.tproj/_configlock.c index ec6b9b1..8544c78 100644 --- a/configd.tproj/_configlock.c +++ b/configd.tproj/_configlock.c @@ -20,54 +20,61 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "configd_server.h" #include "session.h" -SCDStatus -_SCDLock(SCDSessionRef session) +int +__SCDynamicStoreLock(SCDynamicStoreRef store, Boolean recursive) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - serverSessionRef mySession; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + serverSessionRef mySession; - SCDLog(LOG_DEBUG, CFSTR("_SCDLock:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreLock:")); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } - if (SCDOptionGet(NULL, kSCDOptionIsLocked)) { - return SCD_LOCKED; /* sorry, someone (you) already have the lock */ + if (storeLocked > 0) { + if (storePrivate->locked && recursive) { + /* if this session holds the lock and this is a recursive (internal) request */ + storeLocked++; + return kSCStatusOK; + } + return kSCStatusLocked; /* sorry, someone (you) already have the lock */ } /* check credentials */ - mySession = getSession(sessionPrivate->server); + mySession = getSession(storePrivate->server); if (mySession->callerEUID != 0) { -#ifdef DEBUG - if (!SCDOptionGet(NULL, kSCDOptionDebug)) { -#endif /* DEBUG */ - return SCD_EACCESS; -#ifdef DEBUG - } else { - SCDLog(LOG_DEBUG, CFSTR(" non-root access granted while debugging")); - } -#endif /* DEBUG */ + return kSCStatusAccessError; } - SCDOptionSet(NULL, kSCDOptionIsLocked, TRUE); /* global lock flag */ - SCDOptionSet(session, kSCDOptionIsLocked, TRUE); /* per-session lock flag */ + storeLocked = 1; /* global lock flag */ + storePrivate->locked = TRUE; /* per-session lock flag */ /* - * defer all (actually, most) changes until the call to _SCDUnlock() + * defer all (actually, most) changes until the call to __SCDynamicStoreUnlock() */ - if (cacheData_s) { - CFRelease(cacheData_s); + if (storeData_s) { + CFRelease(storeData_s); CFRelease(changedKeys_s); CFRelease(deferredRemovals_s); CFRelease(removedSessionKeys_s); } - cacheData_s = CFDictionaryCreateMutableCopy(NULL, 0, cacheData); + storeData_s = CFDictionaryCreateMutableCopy(NULL, 0, storeData); changedKeys_s = CFSetCreateMutableCopy(NULL, 0, changedKeys); deferredRemovals_s = CFSetCreateMutableCopy(NULL, 0, deferredRemovals); removedSessionKeys_s = CFSetCreateMutableCopy(NULL, 0, removedSessionKeys); @@ -75,21 +82,21 @@ _SCDLock(SCDSessionRef session) /* Add a "locked" mode run loop source for this port */ CFRunLoopAddSource(CFRunLoopGetCurrent(), mySession->serverRunLoopSource, CFSTR("locked")); - return SCD_OK; + return kSCStatusOK; } kern_return_t -_configlock(mach_port_t server, int *scd_status) +_configlock(mach_port_t server, int *sc_status) { serverSessionRef mySession = getSession(server); - SCDLog(LOG_DEBUG, CFSTR("Lock configuration database.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Lock configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); - *scd_status = _SCDLock(mySession->session); - if (*scd_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" SCDLock(): %s"), SCDError(*scd_status)); + *sc_status = __SCDynamicStoreLock(mySession->store, FALSE); + if (*sc_status != kSCStatusOK) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" SCDynamicStoreLock(): %s"), SCErrorString(*sc_status)); return KERN_SUCCESS; } diff --git a/configd.tproj/_confignotify.c b/configd.tproj/_confignotify.c new file mode 100644 index 0000000..8c6e262 --- /dev/null +++ b/configd.tproj/_confignotify.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Modification History + * + * May 19, 2001 Allan Nathanson + * - initial revision + */ + +#include "configd.h" +#include "session.h" + +int +__SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key) +{ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + int sc_status = kSCStatusOK; + CFDictionaryRef dict; + Boolean newValue = FALSE; + CFPropertyListRef value; + + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyValue:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ + } + + /* + * 1. Ensure that we hold the lock. + */ + sc_status = __SCDynamicStoreLock(store, TRUE); + if (sc_status != kSCStatusOK) { + return sc_status; + } + + /* + * 2. Tickle the value in the dynamic store + */ + dict = CFDictionaryGetValue(storeData, key); + if (!dict || !CFDictionaryGetValueIfPresent(dict, kSCDData, (void **)&value)) { + /* key doesn't exist (or data never defined) */ + value = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); + newValue = TRUE; + } + + /* replace or store initial/temporary existing value */ + __SCDynamicStoreSetValue(store, key, value); + + if (newValue) { + /* remove the value we just created */ + __SCDynamicStoreRemoveValue(store, key); + CFRelease(value); + } + + /* + * 3. Release our lock. + */ + __SCDynamicStoreUnlock(store, TRUE); + + return sc_status; +} + + +kern_return_t +_confignotify(mach_port_t server, + xmlData_t keyRef, /* raw XML bytes */ + mach_msg_type_number_t keyLen, + int *sc_status +) +{ + kern_return_t status; + serverSessionRef mySession = getSession(server); + CFDataRef xmlKey; /* key (XML serialized) */ + CFStringRef key; /* key (un-serialized) */ + CFStringRef xmlError; + + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Notify key in configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + + /* un-serialize the key */ + xmlKey = CFDataCreate(NULL, keyRef, keyLen); + status = vm_deallocate(mach_task_self(), (vm_address_t)keyRef, keyLen); + if (status != KERN_SUCCESS) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + /* non-fatal???, proceed */ + } + key = CFPropertyListCreateFromXMLData(NULL, + xmlKey, + kCFPropertyListImmutable, + &xmlError); + CFRelease(xmlKey); + if (!key) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() key: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + return KERN_SUCCESS; + } else if (!isA_CFString(key)) { + *sc_status = kSCStatusInvalidArgument; + return KERN_SUCCESS; + } + + *sc_status = __SCDynamicStoreNotifyValue(mySession->store, key); + CFRelease(key); + + return KERN_SUCCESS; +} diff --git a/configd.tproj/_configopen.c b/configd.tproj/_configopen.c index 62b1238..f462ee9 100644 --- a/configd.tproj/_configopen.c +++ b/configd.tproj/_configopen.c @@ -20,29 +20,36 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "configd_server.h" #include "session.h" -SCDStatus -_SCDOpen(SCDSessionRef *session, CFStringRef name) +int +__SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name) { - SCDSessionPrivateRef sessionPrivate; - - SCDLog(LOG_DEBUG, CFSTR("_SCDOpen:")); - SCDLog(LOG_DEBUG, CFSTR(" name = %@"), name); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreOpen:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" name = %@"), name); /* * allocate and initialize a new session */ - sessionPrivate = (SCDSessionPrivateRef)_SCDSessionCreatePrivate(); - *session = (SCDSessionRef)sessionPrivate; + *store = __SCDynamicStoreCreatePrivate(NULL, name, NULL, NULL); /* - * If necessary, initialize the cache and session data dictionaries + * If necessary, initialize the store and session data dictionaries */ - if (cacheData == NULL) { - cacheData = CFDictionaryCreateMutable(NULL, + if (storeData == NULL) { + storeData = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -61,7 +68,7 @@ _SCDOpen(SCDSessionRef *session, CFStringRef name) &kCFTypeSetCallBacks); } - return SCD_OK; + return kSCStatusOK; } @@ -70,28 +77,28 @@ _configopen(mach_port_t server, xmlData_t nameRef, /* raw XML bytes */ mach_msg_type_number_t nameLen, mach_port_t *newServer, - int *scd_status) + int *sc_status) { kern_return_t status; serverSessionRef mySession, newSession; CFDataRef xmlName; /* name (XML serialized) */ CFStringRef name; /* name (un-serialized) */ CFStringRef xmlError; - mach_port_t oldNotify; + 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); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Open new session.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); /* un-serialize the name */ 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)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } name = CFPropertyListCreateFromXMLData(NULL, @@ -99,17 +106,26 @@ _configopen(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlName); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() name: %s"), xmlError); - *scd_status = SCD_FAILED; + if (!name) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() name: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + return KERN_SUCCESS; + } else if (!isA_CFString(name)) { + CFRelease(name); + *sc_status = kSCStatusInvalidArgument; return KERN_SUCCESS; } mySession = getSession(server); - if (mySession->session) { + if (mySession->store) { CFRelease(name); - SCDLog(LOG_DEBUG, CFSTR(" Sorry, this session is already open.")); - *scd_status = SCD_FAILED; /* you can't re-open an "open" session */ + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" Sorry, this session is already open.")); + *sc_status = kSCStatusFailed; /* you can't re-open an "open" session */ return KERN_SUCCESS; } @@ -136,12 +152,12 @@ _configopen(mach_port_t server, newSession->callerEUID = mySession->callerEUID; newSession->callerEGID = mySession->callerEGID; - *scd_status = _SCDOpen(&newSession->session, name); + *sc_status = __SCDynamicStoreOpen(&newSession->store, name); /* * Make the server port accessible to the framework routines. */ - ((SCDSessionPrivateRef)newSession->session)->server = *newServer; + ((SCDynamicStorePrivateRef)newSession->store)->server = *newServer; /* Request a notification when/if the client dies */ status = mach_port_request_notification(mach_task_self(), @@ -152,19 +168,17 @@ _configopen(mach_port_t server, MACH_MSG_TYPE_MAKE_SEND_ONCE, &oldNotify); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); CFRelease(name); cleanupSession(*newServer); *newServer = MACH_PORT_NULL; - *scd_status = SCD_FAILED; + *sc_status = kSCStatusFailed; return KERN_SUCCESS; - } + } -#ifdef DEBUG if (oldNotify != MACH_PORT_NULL) { - SCDLog(LOG_DEBUG, CFSTR("_configopen(): why is oldNotify != MACH_PORT_NULL?")); + SCLog(_configd_verbose, LOG_ERR, CFSTR("_configopen(): why is oldNotify != MACH_PORT_NULL?")); } -#endif /* DEBUG */ /* * Save the name of the calling application / plug-in with the session data. diff --git a/configd.tproj/_configremove.c b/configd.tproj/_configremove.c index 77c5fa9..a496571 100644 --- a/configd.tproj/_configremove.c +++ b/configd.tproj/_configremove.c @@ -20,46 +20,50 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDRemove(SCDSessionRef session, CFStringRef key) +int +__SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - SCDStatus scd_status = SCD_OK; - boolean_t wasLocked; - CFDictionaryRef dict; - CFMutableDictionaryRef newDict; - CFStringRef sessionKey; - - SCDLog(LOG_DEBUG, CFSTR("_SCDRemove:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + int sc_status = kSCStatusOK; + CFDictionaryRef dict; + CFMutableDictionaryRef newDict; + CFStringRef sessionKey; + + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreRemoveValue:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } /* - * 1. Determine if the cache lock is currently held and acquire - * the lock if necessary. + * 1. Ensure that we hold the lock. */ - wasLocked = SCDOptionGet(NULL, kSCDOptionIsLocked); - if (!wasLocked) { - scd_status = _SCDLock(session); - if (scd_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" _SCDLock(): %s"), SCDError(scd_status)); - return scd_status; - } + sc_status = __SCDynamicStoreLock(store, TRUE); + if (sc_status != kSCStatusOK) { + return sc_status; } /* * 2. Ensure that this key exists. */ - dict = CFDictionaryGetValue(cacheData, key); + dict = CFDictionaryGetValue(storeData, key); if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDData) == FALSE)) { /* key doesn't exist (or data never defined) */ - scd_status = SCD_NOKEY; + sc_status = kSCStatusNoKey; goto done; } newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); @@ -96,27 +100,26 @@ _SCDRemove(SCDSessionRef session, CFStringRef key) /* * 6. Remove data, remove instance, and update/remove - * the dictionary cache entry. + * the dictionary store entry. */ CFDictionaryRemoveValue(newDict, kSCDData); CFDictionaryRemoveValue(newDict, kSCDInstance); if (CFDictionaryGetCount(newDict) > 0) { /* this key is still being "watched" */ - CFDictionarySetValue(cacheData, key, newDict); + CFDictionarySetValue(storeData, key, newDict); } else { /* no information left, remove the empty dictionary */ - CFDictionaryRemoveValue(cacheData, key); + CFDictionaryRemoveValue(storeData, key); } CFRelease(newDict); /* - * 7. Release the lock if we acquired it as part of this request. + * 7. Release our lock. */ done: - if (!wasLocked) - _SCDUnlock(session); + __SCDynamicStoreUnlock(store, TRUE); - return scd_status; + return sc_status; } @@ -124,7 +127,7 @@ kern_return_t _configremove(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ mach_msg_type_number_t keyLen, - int *scd_status + int *sc_status ) { kern_return_t status; @@ -133,14 +136,14 @@ _configremove(mach_port_t server, CFStringRef key; /* key (un-serialized) */ CFStringRef xmlError; - SCDLog(LOG_DEBUG, CFSTR("Remove key from configuration database.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Remove key from configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); /* un-serialize the key */ 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)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } key = CFPropertyListCreateFromXMLData(NULL, @@ -148,13 +151,21 @@ _configremove(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlKey); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError); - *scd_status = SCD_FAILED; + if (!key) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() key: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + return KERN_SUCCESS; + } else if (!isA_CFString(key)) { + *sc_status = kSCStatusInvalidArgument; return KERN_SUCCESS; } - *scd_status = _SCDRemove(mySession->session, key); + *sc_status = __SCDynamicStoreRemoveValue(mySession->store, key); CFRelease(key); return KERN_SUCCESS; diff --git a/configd.tproj/_configset.c b/configd.tproj/_configset.c index efa671c..0b43260 100644 --- a/configd.tproj/_configset.c +++ b/configd.tproj/_configset.c @@ -20,49 +20,51 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDSet(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) +int +__SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - SCDStatus scd_status = SCD_OK; - boolean_t wasLocked; - CFDictionaryRef dict; - CFMutableDictionaryRef newDict; - CFNumberRef num; - int dictInstance; - CFStringRef sessionKey; - CFStringRef cacheSessionKey; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + int sc_status = kSCStatusOK; + CFDictionaryRef dict; + CFMutableDictionaryRef newDict; + Boolean newEntry = FALSE; + CFStringRef sessionKey; + CFStringRef storeSessionKey; - SCDLog(LOG_DEBUG, CFSTR("_SCDSet:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" data = %@"), SCDHandleGetData(handle)); - SCDLog(LOG_DEBUG, CFSTR(" instance = %d"), SCDHandleGetInstance(handle)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreSetValue:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } /* - * 1. Determine if the cache lock is currently held - * and acquire the lock if necessary. + * 1. Ensure that we hold the lock. */ - wasLocked = SCDOptionGet(NULL, kSCDOptionIsLocked); - if (!wasLocked) { - scd_status = _SCDLock(session); - if (scd_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" _SCDLock(): %s"), SCDError(scd_status)); - return scd_status; - } + sc_status = __SCDynamicStoreLock(store, TRUE); + if (sc_status != kSCStatusOK) { + return sc_status; } /* * 2. Grab the current (or establish a new) dictionary for this key. */ - dict = CFDictionaryGetValue(cacheData, key); + dict = CFDictionaryGetValue(storeData, key); if (dict) { newDict = CFDictionaryCreateMutableCopy(NULL, 0, @@ -75,67 +77,40 @@ _SCDSet(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) } /* - * 3. Make sure that we're not updating the cache with potentially - * stale information. + * 3. Update the dictionary entry to be saved to the store. */ - - if ((num = CFDictionaryGetValue(newDict, kSCDInstance)) == NULL) { - /* if first instance */ - dictInstance = 0; - _SCDHandleSetInstance(handle, dictInstance); - } else { - (void) CFNumberGetValue(num, kCFNumberIntType, &dictInstance); - } - if (SCDHandleGetInstance(handle) != dictInstance) { - /* data may be based on old information */ - CFRelease(newDict); - scd_status = SCD_STALE; - goto done; - } + newEntry = !CFDictionaryContainsKey(newDict, kSCDData); + CFDictionarySetValue(newDict, kSCDData, value); /* - * 4. Update the dictionary entry (data & instance) to be saved to - * the cache. - */ - - CFDictionarySetValue(newDict, kSCDData, SCDHandleGetData(handle)); - - dictInstance++; - num = CFNumberCreate(NULL, kCFNumberIntType, &dictInstance); - CFDictionarySetValue(newDict, kSCDInstance, num); - CFRelease(num); - _SCDHandleSetInstance(handle, dictInstance); - SCDLog(LOG_DEBUG, CFSTR(" new instance = %d"), SCDHandleGetInstance(handle)); - - /* - * 5. Since we are updating this key we need to check and, if + * 4. Since we are updating this key we need to check and, if * necessary, remove the indication that this key is on * another session's remove-on-close list. */ - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server); - if (CFDictionaryGetValueIfPresent(newDict, kSCDSession, (void *)&cacheSessionKey) && - !CFEqual(sessionKey, cacheSessionKey)) { + sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); + if (CFDictionaryGetValueIfPresent(newDict, kSCDSession, (void *)&storeSessionKey) && + !CFEqual(sessionKey, storeSessionKey)) { CFStringRef removedKey; /* We are no longer a session key! */ CFDictionaryRemoveValue(newDict, kSCDSession); /* add this session key to the (session) removal list */ - removedKey = CFStringCreateWithFormat(NULL, 0, CFSTR("%@:%@"), cacheSessionKey, key); + removedKey = CFStringCreateWithFormat(NULL, 0, CFSTR("%@:%@"), storeSessionKey, key); CFSetAddValue(removedSessionKeys, removedKey); CFRelease(removedKey); } CFRelease(sessionKey); /* - * 6. Update the dictionary entry in the cache. + * 5. Update the dictionary entry in the store. */ - CFDictionarySetValue(cacheData, key, newDict); + CFDictionarySetValue(storeData, key, newDict); CFRelease(newDict); /* - * 7. For "new" entries to the cache, check the deferred cleanup + * 6. For "new" entries to the store, check the deferred cleanup * list. If the key is flagged for removal, remove it from the * list since any defined regex's for this key are still defined * and valid. If the key is not flagged then iterate over the @@ -144,7 +119,7 @@ _SCDSet(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) * being watched. */ - if (dictInstance == 1) { + if (newEntry) { if (CFSetContainsValue(deferredRemovals, key)) { CFSetRemoveValue(deferredRemovals, key); } else { @@ -155,22 +130,19 @@ _SCDSet(SCDSessionRef session, CFStringRef key, SCDHandleRef handle) } /* - * 8. Mark this key as "changed". Any "watchers" will be notified + * 7. Mark this key as "changed". Any "watchers" will be notified * as soon as the lock is released. */ CFSetAddValue(changedKeys, key); /* - * 9. Release the lock if we acquired it as part of this request. + * 8. Release our lock. */ - done: - if (!wasLocked) - _SCDUnlock(session); + __SCDynamicStoreUnlock(store, TRUE); - return scd_status; + return sc_status; } - kern_return_t _configset(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -179,7 +151,7 @@ _configset(mach_port_t server, mach_msg_type_number_t dataLen, int oldInstance, int *newInstance, - int *scd_status + int *sc_status ) { kern_return_t status; @@ -188,17 +160,18 @@ _configset(mach_port_t server, CFStringRef key; /* key (un-serialized) */ CFDataRef xmlData; /* data (XML serialized) */ CFPropertyListRef data; /* data (un-serialized) */ - SCDHandleRef handle; CFStringRef xmlError; - SCDLog(LOG_DEBUG, CFSTR("Set key to configuration database.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Set key to configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + + *sc_status = kSCStatusOK; /* un-serialize the key */ 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)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } key = CFPropertyListCreateFromXMLData(NULL, @@ -206,17 +179,23 @@ _configset(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlKey); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError); - *scd_status = SCD_FAILED; - return KERN_SUCCESS; + if (!key) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() key: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFString(key)) { + *sc_status = kSCStatusInvalidArgument; } /* un-serialize the data */ xmlData = CFDataCreate(NULL, dataRef, dataLen); status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } data = CFPropertyListCreateFromXMLData(NULL, @@ -224,23 +203,239 @@ _configset(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlData); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() data: %s"), xmlError); - CFRelease(key); - *scd_status = SCD_FAILED; - return KERN_SUCCESS; + if (!data) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() data: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFPropertyList(data)) { + *sc_status = kSCStatusInvalidArgument; } - handle = SCDHandleInit(); - SCDHandleSetData(handle, data); - _SCDHandleSetInstance(handle, oldInstance); - *scd_status = _SCDSet(mySession->session, key, handle); - if (*scd_status == SCD_OK) { - *newInstance = SCDHandleGetInstance(handle); + if (*sc_status != kSCStatusOK) { + if (key) CFRelease(key); + if (data) CFRelease(data); + return KERN_SUCCESS; } - SCDHandleRelease(handle); + + *sc_status = __SCDynamicStoreSetValue(mySession->store, key, data); + *newInstance = 0; + CFRelease(key); CFRelease(data); return KERN_SUCCESS; } + +static void +setSpecificKey(const void *key, const void *value, void *context) +{ + CFStringRef k = (CFStringRef)key; + CFPropertyListRef v = (CFPropertyListRef)value; + SCDynamicStoreRef store = (SCDynamicStoreRef)context; + + if (!isA_CFString(k)) { + return; + } + + if (!isA_CFPropertyList(v)) { + return; + } + + (void) __SCDynamicStoreSetValue(store, k, v); + + return; +} + +static void +removeSpecificKey(const void *value, void *context) +{ + CFStringRef k = (CFStringRef)value; + SCDynamicStoreRef store = (SCDynamicStoreRef)context; + + if (!isA_CFString(k)) { + return; + } + + (void) __SCDynamicStoreRemoveValue(store, k); + + return; +} + +static void +notifySpecificKey(const void *value, void *context) +{ + CFStringRef k = (CFStringRef)value; + SCDynamicStoreRef store = (SCDynamicStoreRef)context; + + if (!isA_CFString(k)) { + return; + } + + (void) __SCDynamicStoreNotifyValue(store, k); + + return; +} + +kern_return_t +_configset_m(mach_port_t server, + xmlData_t dictRef, + mach_msg_type_number_t dictLen, + xmlData_t removeRef, + mach_msg_type_number_t removeLen, + xmlData_t notifyRef, + mach_msg_type_number_t notifyLen, + int *sc_status) +{ + kern_return_t status; + serverSessionRef mySession = getSession(server); + CFDictionaryRef dict = NULL; /* key/value dictionary (un-serialized) */ + CFArrayRef remove = NULL; /* keys to remove (un-serialized) */ + CFArrayRef notify = NULL; /* keys to notify (un-serialized) */ + + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Set key to configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + + *sc_status = kSCStatusOK; + + if (dictRef && (dictLen > 0)) { + CFDataRef xmlDict; /* key/value dictionary (XML serialized) */ + CFStringRef xmlError; + + /* un-serialize the key/value pairs to set */ + xmlDict = CFDataCreate(NULL, dictRef, dictLen); + status = vm_deallocate(mach_task_self(), (vm_address_t)dictRef, dictLen); + if (status != KERN_SUCCESS) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + /* non-fatal???, proceed */ + } + dict = CFPropertyListCreateFromXMLData(NULL, + xmlDict, + kCFPropertyListImmutable, + &xmlError); + CFRelease(xmlDict); + if (!dict) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() dict: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFDictionary(dict)) { + *sc_status = kSCStatusInvalidArgument; + } + } + + if (removeRef && (removeLen > 0)) { + CFDataRef xmlRemove; /* keys to remove (XML serialized) */ + CFStringRef xmlError; + + /* un-serialize the keys to remove */ + xmlRemove = CFDataCreate(NULL, removeRef, removeLen); + status = vm_deallocate(mach_task_self(), (vm_address_t)removeRef, removeLen); + if (status != KERN_SUCCESS) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + /* non-fatal???, proceed */ + } + remove = CFPropertyListCreateFromXMLData(NULL, + xmlRemove, + kCFPropertyListImmutable, + &xmlError); + CFRelease(xmlRemove); + if (!remove) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() remove: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFArray(remove)) { + *sc_status = kSCStatusInvalidArgument; + } + } + + if (notifyRef && (notifyLen > 0)) { + CFDataRef xmlNotify; /* keys to notify (XML serialized) */ + CFStringRef xmlError; + + /* un-serialize the keys to notify */ + xmlNotify = CFDataCreate(NULL, notifyRef, notifyLen); + status = vm_deallocate(mach_task_self(), (vm_address_t)notifyRef, notifyLen); + if (status != KERN_SUCCESS) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + /* non-fatal???, proceed */ + } + notify = CFPropertyListCreateFromXMLData(NULL, + xmlNotify, + kCFPropertyListImmutable, + &xmlError); + CFRelease(xmlNotify); + if (!notify) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() notify: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + } else if (!isA_CFArray(notify)) { + *sc_status = kSCStatusInvalidArgument; + } + } + + if (*sc_status != kSCStatusOK) { + goto done; + } + + /* + * Ensure that we hold the lock + */ + *sc_status = __SCDynamicStoreLock(mySession->store, TRUE); + if (*sc_status != kSCStatusOK) { + goto done; + } + + /* + * Set the new/updated keys + */ + if (dict) { + CFDictionaryApplyFunction(dict, + setSpecificKey, + (void *)mySession->store); + } + + /* + * Remove the specified keys + */ + if (remove) { + CFArrayApplyFunction(remove, + CFRangeMake(0, CFArrayGetCount(remove)), + removeSpecificKey, + (void *)mySession->store); + } + + /* + * Notify the specified keys + */ + if (notify) { + CFArrayApplyFunction(notify, + CFRangeMake(0, CFArrayGetCount(notify)), + notifySpecificKey, + (void *)mySession->store); + } + + __SCDynamicStoreUnlock(mySession->store, TRUE); /* Release our lock */ + + done : + + if (dict) CFRelease(dict); + if (remove) CFRelease(remove); + if (notify) CFRelease(notify); + + return KERN_SUCCESS; +} diff --git a/configd.tproj/_configtouch.c b/configd.tproj/_configtouch.c index 318e6db..f241ad8 100644 --- a/configd.tproj/_configtouch.c +++ b/configd.tproj/_configtouch.c @@ -20,89 +20,92 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * June 20, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDTouch(SCDSessionRef session, CFStringRef key) +int +__SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - SCDStatus scd_status; - boolean_t wasLocked; - SCDHandleRef handle; - CFPropertyListRef value; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + int sc_status; + Boolean newValue = FALSE; + CFPropertyListRef value; - SCDLog(LOG_DEBUG, CFSTR("_SCDTouch:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreTouchValue:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } /* - * 1. Determine if the cache lock is currently held by this session - * and acquire the lock if necessary. + * 1. Ensure that we hold the lock. */ - wasLocked = SCDOptionGet(NULL, kSCDOptionIsLocked); - if (!wasLocked) { - scd_status = _SCDLock(session); - if (scd_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" _SCDLock(): %s"), SCDError(scd_status)); - return scd_status; - } + sc_status = __SCDynamicStoreLock(store, TRUE); + if (sc_status != kSCStatusOK) { + return sc_status; } /* - * 2. Grab the current (or establish a new) cache entry for this key. + * 2. Grab the current (or establish a new) store entry for this key. */ - scd_status = _SCDGet(session, key, &handle); - switch (scd_status) { - case SCD_NOKEY : - /* cache entry does not exist, create */ - handle = SCDHandleInit(); - value = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); - SCDLog(LOG_DEBUG, CFSTR(" new time stamp = %@"), value); - SCDHandleSetData(handle, value); - CFRelease(value); + sc_status = __SCDynamicStoreCopyValue(store, key, &value); + switch (sc_status) { + case kSCStatusNoKey : + /* store entry does not exist, create */ + value = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); + newValue = TRUE; + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" new time stamp = %@"), value); break; - case SCD_OK : - /* cache entry exists, update */ - value = SCDHandleGetData(handle); + case kSCStatusOK : + /* store entry exists */ if (CFGetTypeID(value) == CFDateGetTypeID()) { - /* if value is a CFDate */ - value = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); - SCDLog(LOG_DEBUG, CFSTR(" new time stamp = %@"), value); - SCDHandleSetData(handle, value); + /* the value is a CFDate, update the time stamp */ CFRelease(value); + value = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); + newValue = TRUE; + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" new time stamp = %@"), value); } /* else, we'll just save the data (again) to bump the instance */ break; default : - SCDLog(LOG_DEBUG, CFSTR(" _SCDGet(): %s"), SCDError(scd_status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status)); goto done; } - scd_status = _SCDSet(session, key, handle); - SCDHandleRelease(handle); + sc_status = __SCDynamicStoreSetValue(store, key, value); + + if (newValue) { + CFRelease(value); + } done : /* - * 8. Release the lock if we acquired it as part of this request. + * 8. Release our lock. */ - if (!wasLocked) - _SCDUnlock(session); + __SCDynamicStoreUnlock(store, TRUE); - return SCD_OK; + return kSCStatusOK; } kern_return_t -_configtouch(mach_port_t server, +_configtouch(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ mach_msg_type_number_t keyLen, - int *scd_status + int *sc_status ) { kern_return_t status; @@ -111,14 +114,14 @@ _configtouch(mach_port_t server, CFStringRef key; /* key (un-serialized) */ CFStringRef xmlError; - SCDLog(LOG_DEBUG, CFSTR("Touch key in configuration database.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Touch key in configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); /* un-serialize the key */ 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)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } key = CFPropertyListCreateFromXMLData(NULL, @@ -126,13 +129,21 @@ _configtouch(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlKey); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError); - *scd_status = SCD_FAILED; + if (!key) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() key: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + return KERN_SUCCESS; + } else if (!isA_CFString(key)) { + *sc_status = kSCStatusInvalidArgument; return KERN_SUCCESS; } - *scd_status = _SCDTouch(mySession->session, key); + *sc_status = __SCDynamicStoreTouchValue(mySession->store, key); CFRelease(key); return KERN_SUCCESS; diff --git a/configd.tproj/_configunlock.c b/configd.tproj/_configunlock.c index 421eee6..8cf247a 100644 --- a/configd.tproj/_configunlock.c +++ b/configd.tproj/_configunlock.c @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "configd_server.h" @@ -47,7 +57,7 @@ _notifyWatchers() CFArrayRef changes; CFMutableArrayRef newChanges; - dict = CFDictionaryGetValue(cacheData, (CFStringRef)keys[keyCnt]); + dict = CFDictionaryGetValue(storeData, (CFStringRef)keys[keyCnt]); if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDWatchers) == FALSE)) { /* key doesn't exist or nobody cares if it changed */ continue; @@ -110,7 +120,7 @@ _notifyWatchers() /* * The list of changed keys have been updated for any sessions - * monitoring changes to the "cache". The next step, handled by + * monitoring changes to the "store". The next step, handled by * the "configd" server, is to push out any needed notifications. */ CFSetRemoveAllValues(changedKeys); @@ -137,7 +147,7 @@ _processDeferredRemovals() CFAllocatorDeallocate(NULL, keys); /* - * All regex keys associated with removed cache dictionary keys have + * All regex keys associated with removed store dictionary keys have * been removed. Start the list fresh again. */ CFSetRemoveAllValues(deferredRemovals); @@ -215,35 +225,41 @@ _cleanupRemovedSessionKeys(const void *value, void *context) } -SCDStatus -_SCDUnlock(SCDSessionRef session) +int +__SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - serverSessionRef mySession; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + serverSessionRef mySession; + + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreUnlock:")); - SCDLog(LOG_DEBUG, CFSTR("_SCDUnlock:")); + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ + } - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; + if ((storeLocked == 0) || !storePrivate->locked) { + return kSCStatusNeedLock; /* sorry, you don't have the lock */ } - if (!SCDOptionGet(NULL, kSCDOptionIsLocked) || !SCDOptionGet(session, kSCDOptionIsLocked)) { - return SCD_NEEDLOCK; /* sorry, you don't have the lock */ + if ((storeLocked > 1) && recursive) { + /* if the lock is being held for a recursive (internal) request */ + storeLocked--; + return kSCStatusOK; } /* - * all of the changes can be committed to the (real) cache. + * all of the changes can be committed to the (real) store. */ - CFDictionaryRemoveAllValues(cacheData_s); + CFDictionaryRemoveAllValues(storeData_s); CFSetRemoveAllValues (changedKeys_s); CFSetRemoveAllValues (deferredRemovals_s); CFSetRemoveAllValues (removedSessionKeys_s); #ifdef DEBUG - SCDLog(LOG_DEBUG, CFSTR("keys I changed = %@"), changedKeys); - SCDLog(LOG_DEBUG, CFSTR("keys flagged for removal = %@"), deferredRemovals); - SCDLog(LOG_DEBUG, CFSTR("keys I'm watching = %@"), sessionPrivate->keys); - SCDLog(LOG_DEBUG, CFSTR("regex keys I'm watching = %@"), sessionPrivate->reKeys); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("keys I changed = %@"), changedKeys); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("keys flagged for removal = %@"), deferredRemovals); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("keys I'm watching = %@"), storePrivate->keys); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regex keys I'm watching = %@"), storePrivate->reKeys); #endif /* DEBUG */ /* @@ -264,31 +280,31 @@ _SCDUnlock(SCDSessionRef session) CFSetRemoveAllValues(removedSessionKeys); #ifdef DEBUG - SCDLog(LOG_DEBUG, CFSTR("sessions to notify = %@"), needsNotification); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("sessions to notify = %@"), needsNotification); #endif /* DEBUG */ /* Remove the "locked" run loop source for this port */ - mySession = getSession(sessionPrivate->server); + mySession = getSession(storePrivate->server); CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mySession->serverRunLoopSource, CFSTR("locked")); - SCDOptionSet(NULL, kSCDOptionIsLocked, FALSE); /* global lock flag */ - SCDOptionSet(session, kSCDOptionIsLocked, FALSE); /* per-session lock flag */ + storeLocked = 0; /* global lock flag */ + storePrivate->locked = FALSE; /* per-session lock flag */ - return SCD_OK; + return kSCStatusOK; } kern_return_t -_configunlock(mach_port_t server, int *scd_status) +_configunlock(mach_port_t server, int *sc_status) { serverSessionRef mySession = getSession(server); - SCDLog(LOG_DEBUG, CFSTR("Unlock configuration database.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Unlock configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); - *scd_status = _SCDUnlock(mySession->session); - if (*scd_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" _SCDUnlock(): %s"), SCDError(*scd_status)); + *sc_status = __SCDynamicStoreUnlock(mySession->store, FALSE); + if (*sc_status != kSCStatusOK) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreUnlock(): %s"), SCErrorString(*sc_status)); return KERN_SUCCESS; } diff --git a/configd.tproj/_notifyadd.c b/configd.tproj/_notifyadd.c index 5ca354a..56210cd 100644 --- a/configd.tproj/_notifyadd.c +++ b/configd.tproj/_notifyadd.c @@ -20,36 +20,63 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDNotifierAdd(SCDSessionRef session, CFStringRef key, int regexOptions) + +static __inline__ void +my_CFDictionaryApplyFunction(CFDictionaryRef theDict, + CFDictionaryApplierFunction applier, + void *context) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; + 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; - SCDLog(LOG_DEBUG, CFSTR("_SCDNotifierAdd:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" regexOptions = %0o"), regexOptions); + 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 ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } /* * add new key after checking if key has already been defined */ - if (regexOptions & kSCDRegexKey) { - if (CFSetContainsValue(sessionPrivate->reKeys, key)) - return SCD_EXISTS; /* sorry, key already exists in notifier list */ - CFSetAddValue(sessionPrivate->reKeys, key); /* add key to this sessions notifier list */ + if (isRegex) { + if (CFSetContainsValue(storePrivate->reKeys, key)) + return kSCStatusKeyExists; /* sorry, key already exists in notifier list */ + CFSetAddValue(storePrivate->reKeys, key); /* add key to this sessions notifier list */ } else { - if (CFSetContainsValue(sessionPrivate->keys, key)) - return SCD_EXISTS; /* sorry, key already exists in notifier list */ - CFSetAddValue(sessionPrivate->keys, key); /* add key to this sessions notifier list */ + if (CFSetContainsValue(storePrivate->keys, key)) + return kSCStatusKeyExists; /* sorry, key already exists in notifier list */ + CFSetAddValue(storePrivate->keys, key); /* add key to this sessions notifier list */ } - if (regexOptions & kSCDRegexKey) { + if (isRegex) { CFStringRef sessionKey; int regexStrLen; char *regexStr; @@ -67,7 +94,7 @@ _SCDNotifierAdd(SCDSessionRef session, CFStringRef key, int regexOptions) /* * We are adding a regex key. As such, we need to flag - * any keys currently in the cache. + * any keys currently in the store. */ /* 1. Extract a C String version of the key pattern string. */ @@ -78,9 +105,9 @@ _SCDNotifierAdd(SCDSessionRef session, CFStringRef key, int regexOptions) regexStr, regexStrLen, kCFStringEncodingMacRoman)) { - SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString: could not convert regex key to C string")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert regex key to C string")); CFAllocatorDeallocate(NULL, regexStr); - return SCD_FAILED; + return kSCStatusFailed; } /* 2. Compile the regular expression from the pattern string. */ @@ -96,27 +123,27 @@ _SCDNotifierAdd(SCDSessionRef session, CFStringRef key, int regexOptions) (regex_t *)CFDataGetBytePtr(regexData), reErrBuf, sizeof(reErrBuf)); - SCDLog(LOG_DEBUG, CFSTR("regcomp() key: %s"), reErrBuf); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regcomp() key: %s"), reErrBuf); CFRelease(regexData); - return SCD_FAILED; + return kSCStatusFailed; } /* * 3. Iterate over the current keys and add this session as a "watcher" - * for any key already defined in the cache. + * for any key already defined in the store. */ - context.session = sessionPrivate; - context.preg = (regex_t *)CFDataGetBytePtr(regexData); - CFDictionaryApplyFunction(cacheData, - (CFDictionaryApplierFunction)_addRegexWatcherByKey, - &context); + context.store = storePrivate; + context.preg = (regex_t *)CFDataGetBytePtr(regexData); + my_CFDictionaryApplyFunction(storeData, + (CFDictionaryApplierFunction)_addRegexWatcherByKey, + &context); /* * 4. We also need to save this key and the associated regex data * for any subsequent additions. */ - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server); + sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); info = CFDictionaryGetValue(sessionData, sessionKey); if (info) { @@ -159,14 +186,14 @@ _SCDNotifierAdd(SCDSessionRef session, CFStringRef key, int regexOptions) /* * We are watching a specific key. As such, update the - * cache to mark our interest in any changes. + * store to mark our interest in any changes. */ - sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionPrivate->server); + sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server); _addWatcher(sessionNum, key); CFRelease(sessionNum); } - return SCD_OK; + return kSCStatusOK; } @@ -174,8 +201,8 @@ kern_return_t _notifyadd(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ mach_msg_type_number_t keyLen, - int regexOptions, - int *scd_status + int isRegex, + int *sc_status ) { kern_return_t status; @@ -184,14 +211,14 @@ _notifyadd(mach_port_t server, CFStringRef key; /* key (un-serialized) */ CFStringRef xmlError; - SCDLog(LOG_DEBUG, CFSTR("Add notification key for this session.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Add notification key for this session.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); /* un-serialize the key */ 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)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } key = CFPropertyListCreateFromXMLData(NULL, @@ -199,13 +226,21 @@ _notifyadd(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlKey); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError); - *scd_status = SCD_FAILED; + if (!key) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() key: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + return KERN_SUCCESS; + } else if (!isA_CFString(key)) { + *sc_status = kSCStatusInvalidArgument; return KERN_SUCCESS; } - *scd_status = _SCDNotifierAdd(mySession->session, key, regexOptions); + *sc_status = __SCDynamicStoreAddWatchedKey(mySession->store, key, isRegex); CFRelease(key); return KERN_SUCCESS; diff --git a/configd.tproj/_notifycancel.c b/configd.tproj/_notifycancel.c index 5a77701..bcf06d7 100644 --- a/configd.tproj/_notifycancel.c +++ b/configd.tproj/_notifycancel.c @@ -20,54 +20,64 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 31, 2000 Allan Nathanson + * - initial revision + */ + #include #include "configd.h" #include "session.h" -SCDStatus -_SCDNotifierCancel(SCDSessionRef session) +int +__SCDynamicStoreNotifyCancel(SCDynamicStoreRef store) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; - SCDLog(LOG_DEBUG, CFSTR("_SCDNotifierCancel:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyCancel:")); - if (session == NULL) { - return SCD_NOSESSION; /* you must have an open session to play */ + if (!store) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } /* * cleanup any mach port based notifications. */ - if (sessionPrivate->notifyPort != MACH_PORT_NULL) { - (void) mach_port_destroy(mach_task_self(), sessionPrivate->notifyPort); - sessionPrivate->notifyPort = MACH_PORT_NULL; + if (storePrivate->notifyPort != MACH_PORT_NULL) { + (void) mach_port_destroy(mach_task_self(), storePrivate->notifyPort); + storePrivate->notifyPort = MACH_PORT_NULL; } /* * cleanup any file based notifications. */ - if (sessionPrivate->notifyFile >= 0) { - SCDLog(LOG_DEBUG, CFSTR(" closing (notification) fd %d"), sessionPrivate->notifyFile); - (void) close(sessionPrivate->notifyFile); - sessionPrivate->notifyFile = -1; + if (storePrivate->notifyFile >= 0) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" closing (notification) fd %d"), storePrivate->notifyFile); + (void) close(storePrivate->notifyFile); + storePrivate->notifyFile = -1; } /* * cleanup any signal notifications. */ - if (sessionPrivate->notifySignal > 0) { - (void) mach_port_destroy(mach_task_self(), sessionPrivate->notifySignalTask); - sessionPrivate->notifySignal = 0; - sessionPrivate->notifySignalTask = TASK_NULL; + if (storePrivate->notifySignal > 0) { + (void) mach_port_destroy(mach_task_self(), storePrivate->notifySignalTask); + storePrivate->notifySignal = 0; + storePrivate->notifySignalTask = TASK_NULL; } /* remove this session from the to-be-notified list */ if (needsNotification) { CFNumberRef num; - num = CFNumberCreate(NULL, kCFNumberIntType, &sessionPrivate->server); + num = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server); CFSetRemoveValue(needsNotification, num); CFRelease(num); @@ -78,24 +88,24 @@ _SCDNotifierCancel(SCDSessionRef session) } /* set notifier inactive */ - sessionPrivate->notifyStatus = NotifierNotRegistered; + storePrivate->notifyStatus = NotifierNotRegistered; - return SCD_OK; + return kSCStatusOK; } kern_return_t _notifycancel(mach_port_t server, - int *scd_status) + int *sc_status) { serverSessionRef mySession = getSession(server); - SCDLog(LOG_DEBUG, CFSTR("Cancel requested notifications.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Cancel requested notifications.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); - *scd_status = _SCDNotifierCancel(mySession->session); - if (*scd_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" SCDNotifierCancel(): %s"), SCDError(*scd_status)); + *sc_status = __SCDynamicStoreNotifyCancel(mySession->store); + if (*sc_status != kSCStatusOK) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreNotifyCancel(): %s"), SCErrorString(*sc_status)); } return KERN_SUCCESS; diff --git a/configd.tproj/_notifychanges.c b/configd.tproj/_notifychanges.c index 19ad363..0cb0ed8 100644 --- a/configd.tproj/_notifychanges.c +++ b/configd.tproj/_notifychanges.c @@ -20,30 +20,40 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDNotifierGetChanges(SCDSessionRef session, CFArrayRef *notifierKeys) +int +__SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store, CFArrayRef *notifierKeys) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - CFStringRef sessionKey; - CFDictionaryRef info; - CFMutableDictionaryRef newInfo; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + CFStringRef sessionKey; + CFDictionaryRef info; + CFMutableDictionaryRef newInfo; - SCDLog(LOG_DEBUG, CFSTR("_SCDNotifierGetChanges:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyNotifiedKeys:")); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server); + sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); info = CFDictionaryGetValue(sessionData, sessionKey); if ((info == NULL) || (CFDictionaryContainsKey(info, kSCDChangedKeys) == FALSE)) { CFRelease(sessionKey); *notifierKeys = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);; - return SCD_OK; + return kSCStatusOK; } newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info); @@ -59,7 +69,7 @@ _SCDNotifierGetChanges(SCDSessionRef session, CFArrayRef *notifierKeys) CFRelease(newInfo); CFRelease(sessionKey); - return SCD_OK; + return kSCStatusOK; } @@ -67,7 +77,7 @@ kern_return_t _notifychanges(mach_port_t server, xmlDataOut_t *listRef, /* raw XML bytes */ mach_msg_type_number_t *listLen, - int *scd_status + int *sc_status ) { kern_return_t status; @@ -75,11 +85,11 @@ _notifychanges(mach_port_t server, CFArrayRef notifierKeys; /* array of CFStringRef's */ CFDataRef xmlList; /* list (XML serialized) */ - SCDLog(LOG_DEBUG, CFSTR("List notification keys which have changed.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("List notification keys which have changed.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); - *scd_status = _SCDNotifierGetChanges(mySession->session, ¬ifierKeys); - if (*scd_status != SCD_OK) { + *sc_status = __SCDynamicStoreCopyNotifiedKeys(mySession->store, ¬ifierKeys); + if (*sc_status != kSCStatusOK) { *listRef = NULL; *listLen = 0; return KERN_SUCCESS; @@ -94,11 +104,11 @@ _notifychanges(mach_port_t server, *listLen = CFDataGetLength(xmlList); status = vm_allocate(mach_task_self(), (void *)listRef, *listLen, TRUE); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status)); CFRelease(xmlList); *listRef = NULL; *listLen = 0; - *scd_status = SCD_FAILED; + *sc_status = kSCStatusFailed; return KERN_SUCCESS; } diff --git a/configd.tproj/_notifyremove.c b/configd.tproj/_notifyremove.c index e16f2a2..fb74607 100644 --- a/configd.tproj/_notifyremove.c +++ b/configd.tproj/_notifyremove.c @@ -20,37 +20,64 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDNotifierRemove(SCDSessionRef session, CFStringRef key, int regexOptions) + +static __inline__ void +my_CFDictionaryApplyFunction(CFDictionaryRef theDict, + CFDictionaryApplierFunction applier, + void *context) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; + CFAllocatorRef myAllocator; + CFDictionaryRef myDict; + + myAllocator = CFGetAllocator(theDict); + myDict = CFDictionaryCreateCopy(myAllocator, theDict); + CFDictionaryApplyFunction(myDict, applier, context); + CFRelease(myDict); + return; +} + + +int +__SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex) +{ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; - SCDLog(LOG_DEBUG, CFSTR("_SCDNotifierRemove:")); - SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); - SCDLog(LOG_DEBUG, CFSTR(" regexOptions = %0o"), regexOptions); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreRemoveWatchedKey:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE"); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you can't do anything with a closed session */ + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } /* * remove key from this sessions notifier list after checking that * it was previously defined. */ - if (regexOptions & kSCDRegexKey) { - if (!CFSetContainsValue(sessionPrivate->reKeys, key)) - return SCD_NOKEY; /* sorry, key does not exist in notifier list */ - CFSetRemoveValue(sessionPrivate->reKeys, key); /* remove key from this sessions notifier list */ + if (isRegex) { + if (!CFSetContainsValue(storePrivate->reKeys, key)) + return kSCStatusNoKey; /* sorry, key does not exist in notifier list */ + CFSetRemoveValue(storePrivate->reKeys, key); /* remove key from this sessions notifier list */ } else { - if (!CFSetContainsValue(sessionPrivate->keys, key)) - return SCD_NOKEY; /* sorry, key does not exist in notifier list */ - CFSetRemoveValue(sessionPrivate->keys, key); /* remove key from this sessions notifier list */ + if (!CFSetContainsValue(storePrivate->keys, key)) + return kSCStatusNoKey; /* sorry, key does not exist in notifier list */ + CFSetRemoveValue(storePrivate->keys, key); /* remove key from this sessions notifier list */ } - if (regexOptions & kSCDRegexKey) { + if (isRegex) { CFStringRef sessionKey; CFDictionaryRef info; CFMutableDictionaryRef newInfo; @@ -62,7 +89,7 @@ _SCDNotifierRemove(SCDSessionRef session, CFStringRef key, int regexOptions) CFDataRef regexData; removeContext context; - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server); + sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); info = CFDictionaryGetValue(sessionData, sessionKey); newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info); @@ -78,11 +105,11 @@ _SCDNotifierRemove(SCDSessionRef session, CFStringRef key, int regexOptions) key); regexData = CFArrayGetValueAtIndex(newRData, i); - context.session = sessionPrivate; - context.preg = (regex_t *)CFDataGetBytePtr(regexData); - CFDictionaryApplyFunction(cacheData, - (CFDictionaryApplierFunction)_removeRegexWatcherByKey, - &context); + context.store = storePrivate; + context.preg = (regex_t *)CFDataGetBytePtr(regexData); + my_CFDictionaryApplyFunction(storeData, + (CFDictionaryApplierFunction)_removeRegexWatcherByKey, + &context); /* remove the regex key */ CFArrayRemoveValueAtIndex(newRKeys, i); @@ -113,15 +140,15 @@ _SCDNotifierRemove(SCDSessionRef session, CFStringRef key, int regexOptions) /* * We are watching a specific key. As such, update the - * cache to mark our interest in any changes. + * store to mark our interest in any changes. */ - sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionPrivate->server); + sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server); _removeWatcher(sessionNum, key); CFRelease(sessionNum); } - return SCD_OK; + return kSCStatusOK; } @@ -129,8 +156,8 @@ kern_return_t _notifyremove(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ mach_msg_type_number_t keyLen, - int regexOptions, - int *scd_status + int isRegex, + int *sc_status ) { kern_return_t status; @@ -139,14 +166,14 @@ _notifyremove(mach_port_t server, CFStringRef key; /* key (un-serialized) */ CFStringRef xmlError; - SCDLog(LOG_DEBUG, CFSTR("Remove notification key for this session.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Remove notification key for this session.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); /* un-serialize the key */ 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)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } key = CFPropertyListCreateFromXMLData(NULL, @@ -154,13 +181,21 @@ _notifyremove(mach_port_t server, kCFPropertyListImmutable, &xmlError); CFRelease(xmlKey); - if (xmlError) { - SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError); - *scd_status = SCD_FAILED; + if (!key) { + if (xmlError) { + SCLog(_configd_verbose, LOG_DEBUG, + CFSTR("CFPropertyListCreateFromXMLData() key: %@"), + xmlError); + CFRelease(xmlError); + } + *sc_status = kSCStatusFailed; + return KERN_SUCCESS; + } else if (!isA_CFString(key)) { + *sc_status = kSCStatusInvalidArgument; return KERN_SUCCESS; } - *scd_status = _SCDNotifierRemove(mySession->session, key, regexOptions); + *sc_status = __SCDynamicStoreRemoveWatchedKey(mySession->store, key, isRegex); CFRelease(key); return KERN_SUCCESS; diff --git a/configd.tproj/_notifyviafd.c b/configd.tproj/_notifyviafd.c index 7eedbfc..dd7f3ab 100644 --- a/configd.tproj/_notifyviafd.c +++ b/configd.tproj/_notifyviafd.c @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * April 5, 2000 Allan Nathanson + * - initial revision + */ + #include #include #include @@ -30,36 +40,36 @@ #include "session.h" -SCDStatus -_SCDNotifierInformViaFD(SCDSessionRef session, - int32_t identifier, - int *fd) +int +__SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, + int32_t identifier, + int *fd) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - int sock; - CFStringRef sessionKey; - CFDictionaryRef info; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + int sock; + CFStringRef sessionKey; + CFDictionaryRef info; - SCDLog(LOG_DEBUG, CFSTR("_SCDNotifierInformViaFD:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyFileDescriptor:")); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } - if (sessionPrivate->notifyStatus != NotifierNotRegistered) { + if (storePrivate->notifyStatus != NotifierNotRegistered) { /* sorry, you can only have one notification registered at once */ - return SCD_NOTIFIERACTIVE; + return kSCStatusNotifierActive; } if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - SCDLog(LOG_NOTICE, CFSTR("socket: %s"), strerror(errno)); - return SCD_FAILED; + SCLog(_configd_verbose, LOG_NOTICE, CFSTR("socket: %s"), strerror(errno)); + return kSCStatusFailed; } *fd = sock; /* push out a notification if any changes are pending */ - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server); + sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); info = CFDictionaryGetValue(sessionData, sessionKey); CFRelease(sessionKey); if (info && CFDictionaryContainsKey(info, kSCDChangedKeys)) { @@ -70,12 +80,12 @@ _SCDNotifierInformViaFD(SCDSessionRef session, 0, &kCFTypeSetCallBacks); - sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionPrivate->server); + sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server); CFSetAddValue(needsNotification, sessionNum); CFRelease(sessionNum); } - return SCD_OK; + return kSCStatusOK; } @@ -84,33 +94,33 @@ _notifyviafd(mach_port_t server, xmlData_t pathRef, mach_msg_type_number_t pathLen, int identifier, - int *scd_status + int *sc_status ) { kern_return_t status; serverSessionRef mySession = getSession(server); - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)mySession->session; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)mySession->store; struct sockaddr_un un; int sock; - int bufSiz = sizeof(sessionPrivate->notifyFileIdentifier); + int bufSiz = sizeof(storePrivate->notifyFileIdentifier); int nbioYes = 1; - SCDLog(LOG_DEBUG, CFSTR("Send message via UNIX domain socket when a notification key changes.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); - SCDLog(LOG_DEBUG, CFSTR(" path = %s"), pathRef); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Send message via UNIX domain socket when a notification key changes.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" path = %s"), pathRef); /* * if socket currently open, close it! */ /* validate the UNIX domain socket path */ if (pathLen > (sizeof(un.sun_path) - 1)) { - SCDLog(LOG_NOTICE, CFSTR("domain socket path length too long!")); + SCLog(_configd_verbose, LOG_NOTICE, CFSTR("domain socket path length too long!")); status = vm_deallocate(mach_task_self(), (vm_address_t)pathRef, pathLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } - *scd_status = SCD_FAILED; + *sc_status = kSCStatusFailed; return KERN_SUCCESS; } @@ -120,49 +130,49 @@ _notifyviafd(mach_port_t server, un.sun_path[pathLen] = '\0'; status = vm_deallocate(mach_task_self(), (vm_address_t)pathRef, pathLen); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); /* non-fatal???, proceed */ } /* do common sanity checks, get socket */ - *scd_status = _SCDNotifierInformViaFD(mySession->session, identifier, &sock); + *sc_status = __SCDynamicStoreNotifyFileDescriptor(mySession->store, identifier, &sock); - /* check status of _SCDNotifierInformViaFD() */ - if (*scd_status != SCD_OK) { + /* check status of __SCDynamicStoreNotifyFileDescriptor() */ + if (*sc_status != kSCStatusOK) { return KERN_SUCCESS; } /* establish the connection, get ready for a read() */ if (connect(sock, (struct sockaddr *)&un, sizeof(un)) == -1) { - SCDLog(LOG_DEBUG, CFSTR("connect: %s"), strerror(errno)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("connect: %s"), strerror(errno)); (void) close(sock); - sessionPrivate->notifyStatus = NotifierNotRegistered; - sessionPrivate->notifyFile = -1; - *scd_status = SCD_FAILED; + storePrivate->notifyStatus = NotifierNotRegistered; + storePrivate->notifyFile = -1; + *sc_status = kSCStatusFailed; return KERN_SUCCESS; } - SCDLog(LOG_NOTICE, CFSTR(" fd = %d"), sock); + SCLog(_configd_verbose, LOG_NOTICE, CFSTR(" fd = %d"), sock); (void) unlink(un.sun_path); if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufSiz, sizeof(bufSiz)) < 0) { - SCDLog(LOG_DEBUG, CFSTR("setsockopt: %s"), strerror(errno)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("setsockopt: %s"), strerror(errno)); (void) close(sock); - *scd_status = SCD_FAILED; + *sc_status = kSCStatusFailed; return KERN_SUCCESS; } if (ioctl(sock, FIONBIO, &nbioYes) == -1) { - SCDLog(LOG_DEBUG, CFSTR("ioctl(,FIONBIO,): %s"), strerror(errno)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("ioctl(,FIONBIO,): %s"), strerror(errno)); (void) close(sock); - *scd_status = SCD_FAILED; + *sc_status = kSCStatusFailed; return KERN_SUCCESS; } /* set notifier active */ - sessionPrivate->notifyStatus = Using_NotifierInformViaFD; - sessionPrivate->notifyFile = sock; - sessionPrivate->notifyFileIdentifier = identifier; + storePrivate->notifyStatus = Using_NotifierInformViaFD; + storePrivate->notifyFile = sock; + storePrivate->notifyFileIdentifier = identifier; return KERN_SUCCESS; } diff --git a/configd.tproj/_notifyviaport.c b/configd.tproj/_notifyviaport.c index ac270ec..0c20ffe 100644 --- a/configd.tproj/_notifyviaport.c +++ b/configd.tproj/_notifyviaport.c @@ -20,34 +20,46 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" -SCDStatus -_SCDNotifierInformViaMachPort(SCDSessionRef session, mach_msg_id_t identifier, mach_port_t *port) +int +__SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, + mach_msg_id_t identifier, + mach_port_t *port) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - CFStringRef sessionKey; - CFDictionaryRef info; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + CFStringRef sessionKey; + CFDictionaryRef info; - SCDLog(LOG_DEBUG, CFSTR("_SCDNotifierInformViaMachPort:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyMachPort:")); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } - if (sessionPrivate->notifyStatus != NotifierNotRegistered) { + if (storePrivate->notifyStatus != NotifierNotRegistered) { /* sorry, you can only have one notification registered at once */ - return SCD_NOTIFIERACTIVE; + return kSCStatusNotifierActive; } if (*port == MACH_PORT_NULL) { /* sorry, you must specify a valid mach port */ - return SCD_INVALIDARGUMENT; + return kSCStatusInvalidArgument; } /* push out a notification if any changes are pending */ - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server); + sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); info = CFDictionaryGetValue(sessionData, sessionKey); CFRelease(sessionKey); if (info && CFDictionaryContainsKey(info, kSCDChangedKeys)) { @@ -58,12 +70,12 @@ _SCDNotifierInformViaMachPort(SCDSessionRef session, mach_msg_id_t identifier, m 0, &kCFTypeSetCallBacks); - sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionPrivate->server); + sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server); CFSetAddValue(needsNotification, sessionNum); CFRelease(sessionNum); } - return SCD_OK; + return kSCStatusOK; } @@ -71,29 +83,29 @@ kern_return_t _notifyviaport(mach_port_t server, mach_port_t port, mach_msg_id_t identifier, - int *scd_status + int *sc_status ) { - serverSessionRef mySession = getSession(server); - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)mySession->session; + serverSessionRef mySession = getSession(server); + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)mySession->store; - SCDLog(LOG_DEBUG, CFSTR("Send mach message when a notification key changes.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); - SCDLog(LOG_DEBUG, CFSTR(" port = %d"), port); - SCDLog(LOG_DEBUG, CFSTR(" message id = %d"), identifier); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Send mach message when a notification key changes.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" port = %d"), port); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" message id = %d"), identifier); - if (sessionPrivate->notifyPort != MACH_PORT_NULL) { - SCDLog(LOG_DEBUG, CFSTR(" destroying old callback mach port %d"), sessionPrivate->notifyPort); - (void) mach_port_destroy(mach_task_self(), sessionPrivate->notifyPort); + if (storePrivate->notifyPort != MACH_PORT_NULL) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" destroying old callback mach port %d"), storePrivate->notifyPort); + (void) mach_port_destroy(mach_task_self(), storePrivate->notifyPort); } - *scd_status = _SCDNotifierInformViaMachPort(mySession->session, identifier, &port); + *sc_status = __SCDynamicStoreNotifyMachPort(mySession->store, identifier, &port); - if (*scd_status == SCD_OK) { + if (*sc_status == kSCStatusOK) { /* save notification port, requested identifier, and set notifier active */ - sessionPrivate->notifyStatus = Using_NotifierInformViaMachPort; - sessionPrivate->notifyPort = port; - sessionPrivate->notifyPortIdentifier = identifier; + storePrivate->notifyStatus = Using_NotifierInformViaMachPort; + storePrivate->notifyPort = port; + storePrivate->notifyPortIdentifier = identifier; } return KERN_SUCCESS; diff --git a/configd.tproj/_notifyviasignal.c b/configd.tproj/_notifyviasignal.c index fc10d1b..bbe43ee 100644 --- a/configd.tproj/_notifyviasignal.c +++ b/configd.tproj/_notifyviasignal.c @@ -20,35 +20,50 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "configd_server.h" #include "session.h" -SCDStatus -_SCDNotifierInformViaSignal(SCDSessionRef session, pid_t pid, int sig) +int +__SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig) { - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; - CFStringRef sessionKey; - CFDictionaryRef info; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + CFStringRef sessionKey; + CFDictionaryRef info; - SCDLog(LOG_DEBUG, CFSTR("_SCDNotifierInformViaSignal:")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifySignal:")); - if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { - return SCD_NOSESSION; /* you must have an open session to play */ + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ } - if (sessionPrivate->notifyStatus != NotifierNotRegistered) { + if (storePrivate->notifyStatus != NotifierNotRegistered) { /* sorry, you can only have one notification registered at once */ - return SCD_NOTIFIERACTIVE; + return kSCStatusNotifierActive; + } + + if (pid == getpid()) { + /* sorry, you can't request that configd be signalled */ + return kSCStatusFailed; } if ((sig <= 0) || (sig > NSIG)) { /* sorry, you must specify a valid signal */ - return SCD_INVALIDARGUMENT; + return kSCStatusInvalidArgument; } /* push out a notification if any changes are pending */ - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server); + sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); info = CFDictionaryGetValue(sessionData, sessionKey); CFRelease(sessionKey); if (info && CFDictionaryContainsKey(info, kSCDChangedKeys)) { @@ -59,12 +74,12 @@ _SCDNotifierInformViaSignal(SCDSessionRef session, pid_t pid, int sig) 0, &kCFTypeSetCallBacks); - sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionPrivate->server); + sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server); CFSetAddValue(needsNotification, sessionNum); CFRelease(sessionNum); } - return SCD_OK; + return kSCStatusOK; } @@ -72,24 +87,30 @@ kern_return_t _notifyviasignal(mach_port_t server, task_t task, int sig, - int *scd_status) + int *sc_status) { - serverSessionRef mySession = getSession(server); - SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)mySession->session; -#if defined(DEBUG) || defined(NOTYET) - kern_return_t status; -#endif + serverSessionRef mySession = getSession(server); + pid_t pid; + kern_return_t status; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)mySession->store; #ifdef NOTYET - mach_port_t oldNotify; + mach_port_t oldNotify; #endif /* NOTYET */ - SCDLog(LOG_DEBUG, CFSTR("Send signal when a notification key changes.")); - SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); - SCDLog(LOG_DEBUG, CFSTR(" task = %d"), task); - SCDLog(LOG_DEBUG, CFSTR(" signal = %d"), sig); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Send signal when a notification key changes.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" task = %d"), task); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" signal = %d"), sig); - *scd_status = _SCDNotifierInformViaSignal(mySession->session, 0, sig); /* pid is N/A for server */ - if (*scd_status != SCD_OK) { + status = pid_for_task(task, &pid); + if (status != KERN_SUCCESS) { + /* could not determine pid for task */ + *sc_status = kSCStatusFailed; + return KERN_SUCCESS; + } + + *sc_status = __SCDynamicStoreNotifySignal(mySession->store, pid, sig); + if (*sc_status != kSCStatusOK) { if (task != TASK_NULL) { (void) mach_port_destroy(mach_task_self(), task); } @@ -115,7 +136,7 @@ _notifyviasignal(mach_port_t server, *rp++ = 'D'; *rp = '\0'; - SCDLog(LOG_DEBUG, CFSTR("Task %d, port rights = %s"), task, rights); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Task %d, port rights = %s"), task, rights); } } #endif /* DEBUG */ @@ -130,29 +151,27 @@ _notifyviasignal(mach_port_t server, MACH_MSG_TYPE_MAKE_SEND_ONCE, &oldNotify); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); - *scd_status = SCD_FAILED; + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); + *sc_status = kSCStatusFailed; return KERN_SUCCESS; } -#ifdef DEBUG if (oldNotify != MACH_PORT_NULL) { - SCDLog(LOG_DEBUG, CFSTR("_notifyviasignal(): why is oldNotify != MACH_PORT_NULL?")); + SCLog(_configd_verbose, LOG_ERR, CFSTR("_notifyviasignal(): why is oldNotify != MACH_PORT_NULL?")); } -#endif /* DEBUG */ - SCDLog(LOG_DEBUG, CFSTR("Adding task notification port %d to the server's port set"), task); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Adding task notification port %d to the server's port set"), task); status = mach_port_move_member(mach_task_self(), task, server_ports); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("mach_port_move_member(): %s"), mach_error_string(status)); - *scd_status = SCD_FAILED; + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_move_member(): %s"), mach_error_string(status)); + *sc_status = kSCStatusFailed; return KERN_SUCCESS; } #endif /* NOTYET */ - sessionPrivate->notifyStatus = Using_NotifierInformViaSignal; - sessionPrivate->notifySignal = sig; - sessionPrivate->notifySignalTask = task; + storePrivate->notifyStatus = Using_NotifierInformViaSignal; + storePrivate->notifySignal = sig; + storePrivate->notifySignalTask = task; return KERN_SUCCESS; } diff --git a/configd.tproj/_snapshot.c b/configd.tproj/_snapshot.c index b21d96a..68e8509 100644 --- a/configd.tproj/_snapshot.c +++ b/configd.tproj/_snapshot.c @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * April 14, 2000 Allan Nathanson + * - initial revision + */ + #include #include #include @@ -29,27 +39,36 @@ #include "session.h" -#define SNAPSHOT_PATH_CACHE _PATH_VARTMP "configd-cache.xml" +#define SNAPSHOT_PATH_STORE _PATH_VARTMP "configd-store.xml" #define SNAPSHOT_PATH_SESSION _PATH_VARTMP "configd-session.xml" -SCDStatus -_SCDSnapshot(SCDSessionRef session) +int +__SCDynamicStoreSnapshot(SCDynamicStoreRef store) { - int fd; - CFDataRef xmlData; + int fd; + serverSessionRef mySession; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + CFDataRef xmlData; + + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreSnapshot:")); - SCDLog(LOG_DEBUG, CFSTR("_SCDSnapshot:")); + /* check credentials */ + + mySession = getSession(storePrivate->server); + if (mySession->callerEUID != 0) { + return kSCStatusAccessError; + } - /* Save a snapshot of the "cache" data */ + /* Save a snapshot of the "store" data */ - (void) unlink(SNAPSHOT_PATH_CACHE); - fd = open(SNAPSHOT_PATH_CACHE, O_WRONLY|O_CREAT|O_TRUNC, 0644); + (void) unlink(SNAPSHOT_PATH_STORE); + fd = open(SNAPSHOT_PATH_STORE, O_WRONLY|O_CREAT|O_TRUNC, 0644); if (fd < 0) { - return SCD_FAILED; + return kSCStatusFailed; } - xmlData = CFPropertyListCreateXMLData(NULL, cacheData); + xmlData = CFPropertyListCreateXMLData(NULL, storeData); (void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData)); (void) close(fd); CFRelease(xmlData); @@ -59,7 +78,7 @@ _SCDSnapshot(SCDSessionRef session) (void) unlink(SNAPSHOT_PATH_SESSION); fd = open(SNAPSHOT_PATH_SESSION, O_WRONLY|O_CREAT|O_TRUNC, 0644); if (fd < 0) { - return SCD_FAILED; + return kSCStatusFailed; } /* Save a snapshot of the "session" data */ @@ -69,20 +88,20 @@ _SCDSnapshot(SCDSessionRef session) (void) close(fd); CFRelease(xmlData); - return SCD_OK; + return kSCStatusOK; } kern_return_t -_snapshot(mach_port_t server, int *scd_status) +_snapshot(mach_port_t server, int *sc_status) { serverSessionRef mySession = getSession(server); - SCDLog(LOG_DEBUG, CFSTR("Snapshot configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Snapshot configuration database.")); - *scd_status = _SCDSnapshot(mySession->session); - if (*scd_status != SCD_OK) { - SCDLog(LOG_DEBUG, CFSTR(" SCDUnlock(): %s"), SCDError(*scd_status)); + *sc_status = __SCDynamicStoreSnapshot(mySession->store); + if (*sc_status != kSCStatusOK) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreSnapshot(): %s"), SCErrorString(*sc_status)); } return KERN_SUCCESS; diff --git a/configd.tproj/configd.h b/configd.tproj/configd.h index 05ffe70..f04426d 100644 --- a/configd.tproj/configd.h +++ b/configd.tproj/configd.h @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _S_CONFIGD_H #define _S_CONFIGD_H @@ -29,11 +39,20 @@ #include #include -#include +/* configd doesn't need the preference keys */ +#define _SCSCHEMADEFINITIONS_H + +#include +#include +#include "SCDynamicStoreInternal.h" +#include #include "config_types.h" -#include "SCDPrivate.h" #include "_SCD.h" +extern Boolean _configd_fork; /* TRUE if process should be run in the background */ +extern Boolean _configd_verbose; /* TRUE if verbose logging enabled */ +extern CFMutableSetRef _plugins_exclude; /* bundle identifiers to exclude from loading */ +extern CFMutableSetRef _plugins_verbose; /* bundle identifiers to enable verbose logging */ __BEGIN_DECLS __END_DECLS diff --git a/configd.tproj/configd.m b/configd.tproj/configd.m index dad2d5a..55caa0b 100644 --- a/configd.tproj/configd.m +++ b/configd.tproj/configd.m @@ -20,10 +20,14 @@ * @APPLE_LICENSE_HEADER_END@ */ -/* - * Modification History - * 24 March 2000 Allan Nathanson (ajn@apple.com) - * - created +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * 24 March 2000 Allan Nathanson (ajn@apple.com) + * - created */ #include @@ -40,8 +44,12 @@ #include "configd_server.h" #include "plugin_support.h" +Boolean _configd_fork = TRUE; /* TRUE if process should be run in the background */ +Boolean _configd_verbose = FALSE; /* TRUE if verbose logging enabled */ +CFMutableSetRef _plugins_exclude = NULL; /* bundle identifiers to exclude from loading */ +CFMutableSetRef _plugins_verbose = NULL; /* bundle identifiers to enable verbose logging */ -const char *signames[] = { +static const char *signames[] = { "" , "HUP" , "INT" , "QUIT", "ILL" , "TRAP", "ABRT", "EMT" , "FPE" , "KILL", "BUS" , "SEGV", "SYS" , "PIPE", "ALRM", "TERM", "URG" , "STOP", "TSTP" , "CONT", "CHLD" , "TTIN", "TTOU", "IO" , @@ -49,30 +57,32 @@ const char *signames[] = { }; -void +static void usage(const char *prog) { - SCDLog(LOG_INFO, CFSTR("%s: [-d] [-v] [-b] [-t plugin-bundle-path]"), prog); - SCDLog(LOG_INFO, CFSTR("options:")); - SCDLog(LOG_INFO, CFSTR("\t-d\tenable debugging")); - SCDLog(LOG_INFO, CFSTR("\t-v\tenable verbose logging")); - SCDLog(LOG_INFO, CFSTR("\t-b\tdisable loading of ALL plug-ins")); - SCDLog(LOG_INFO, CFSTR("\t-t\tload/test the specified plug-in")); - SCDLog(LOG_INFO, CFSTR("\t\t (Note: only the plug-in will be started)"), prog); + SCPrint(TRUE, stderr, CFSTR("%s: [-d] [-v] [-V bundleID] [-b] [-B bundleID] [-t plugin-path]\n"), prog); + SCPrint(TRUE, stderr, CFSTR("options:\n")); + SCPrint(TRUE, stderr, CFSTR("\t-d\tdisable daemon/run in foreground\n")); + SCPrint(TRUE, stderr, CFSTR("\t-v\tenable verbose logging\n")); + SCPrint(TRUE, stderr, CFSTR("\t-V\tenable verbose logging for the specified plug-in\n")); + SCPrint(TRUE, stderr, CFSTR("\t-b\tdisable loading of ALL plug-ins\n")); + SCPrint(TRUE, stderr, CFSTR("\t-B\tdisable loading of the specified plug-in\n")); + SCPrint(TRUE, stderr, CFSTR("\t-t\tload/test the specified plug-in\n")); + SCPrint(TRUE, stderr, CFSTR("\t\t (Note: only the plug-in will be started)\n"), prog); exit (EX_USAGE); } -void +static void catcher(int signum) { /* * log the signal * - * Note: we can't use SCDLog() since the signal may be received while the + * Note: we can't use SCLog() since the signal may be received while the * logging thread lock is held. */ - if (SCDOptionGet(NULL, kSCDOptionUseSyslog)) { + if (_configd_verbose) { syslog (LOG_INFO, "caught SIG%s" , signames[signum]); } else { fprintf(stderr, "caught SIG%s\n", signames[signum]); @@ -127,44 +137,62 @@ fork_child() if (setsid() == -1) return -1; - (void)chdir("/"); + (void) chdir("/"); if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { - (void)dup2(fd, STDIN_FILENO); - (void)dup2(fd, STDOUT_FILENO); - (void)dup2(fd, STDERR_FILENO); + (void) dup2(fd, STDIN_FILENO); + (void) dup2(fd, STDOUT_FILENO); + (void) dup2(fd, STDERR_FILENO); if (fd > 2) - (void)close(fd); + (void) close(fd); } return 0; } int -main (int argc, const char *argv[]) +main(int argc, const char *argv[]) { - extern int optind; + Boolean loadBundles = TRUE; + struct sigaction nact; int opt; + extern int optind; const char *prog = argv[0]; - boolean_t loadBundles = TRUE; + CFStringRef str; const char *testBundle = NULL; - struct sigaction nact; + + _plugins_exclude = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); + _plugins_verbose = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); /* process any arguments */ - while ((opt = getopt(argc, argv, "bdt:v")) != -1) { + while ((opt = getopt(argc, argv, "bB:dt:vV:")) != -1) { switch(opt) { case 'b': loadBundles = FALSE; break; + case 'B': + str = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingMacRoman); + CFSetSetValue(_plugins_exclude, str); + CFRelease(str); + break; case 'd': - SCDOptionSet(NULL, kSCDOptionDebug, TRUE); + _configd_fork = FALSE; break; case 't': testBundle = optarg; break; case 'v': - SCDOptionSet(NULL, kSCDOptionVerbose, TRUE); + _configd_verbose = TRUE; + break; + case 'V': + if (strcmp(optarg, "com.apple.SystemConfiguration") == 0) { + _sc_verbose = TRUE; + } else { + str = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingMacRoman); + CFSetSetValue(_plugins_verbose, str); + CFRelease(str); + } break; case '?': default : @@ -182,43 +210,47 @@ main (int argc, const char *argv[]) exit (EX_UNAVAILABLE); } - /* get ready */ - - SCDOptionSet(NULL, kSCDOptionIsServer, TRUE); /* Use the config API's "server" code */ - SCDOptionSet(NULL, kSCDOptionUseCFRunLoop, TRUE); /* Use the CFRunLoop */ - /* check credentials */ if (getuid() != 0) { -#ifdef DEBUG - if (!SCDOptionGet(NULL, kSCDOptionDebug)) { -#endif /* DEBUG */ - fprintf(stderr, "%s: permission denied.\n", prog); - exit (EX_NOPERM); -#ifdef DEBUG - } -#endif /* DEBUG */ + fprintf(stderr, "%s: permission denied.\n", prog); + exit (EX_NOPERM); } - if ((testBundle == NULL) && !SCDOptionGet(NULL, kSCDOptionDebug)) { + if (_configd_fork) { if (fork_child() == -1) { fprintf(stderr, "configd: fork() failed, %s\n", strerror(errno)); exit (1); } /* now the child process, parent waits in fork_child */ + } + + /* open syslog() facility */ + if (_configd_fork) { + int logopt = LOG_NDELAY|LOG_PID; - /* log via syslog() facility */ - openlog("configd", (LOG_NDELAY | LOG_PID), LOG_DAEMON); - SCDOptionSet(NULL, kSCDOptionUseSyslog, TRUE); + if (_configd_verbose) + logopt |= LOG_CONS; + openlog("configd", logopt, LOG_DAEMON); + } else { + _sc_log = FALSE; /* redirect SCLog() to stdout/stderr */ } - /* add signal handler to catch a SIGPIPE */ + /* add signal handler to catch a SIGHUP */ nact.sa_handler = catcher; sigemptyset(&nact.sa_mask); nact.sa_flags = SA_RESTART; + if (sigaction(SIGHUP, &nact, NULL) == -1) { + SCLog(_configd_verbose, LOG_ERR, + CFSTR("sigaction(SIGHUP, ...) failed: %s"), + strerror(errno)); + } + + /* add signal handler to catch a SIGPIPE */ + if (sigaction(SIGPIPE, &nact, NULL) == -1) { - SCDLog(LOG_ERR, + SCLog(_configd_verbose, LOG_ERR, CFSTR("sigaction(SIGPIPE, ...) failed: %s"), strerror(errno)); } @@ -228,14 +260,14 @@ main (int argc, const char *argv[]) objc_setMultithreaded(YES); if (testBundle == NULL) { - /* initialize primary (cache management) thread */ + /* initialize primary (store management) thread */ server_init(); /* load/initialize/start bundles into the secondary thread */ if (loadBundles) { plugin_init(); } else { - if (!SCDOptionGet(NULL, kSCDOptionDebug)) { + if (_configd_fork) { /* synchronize with parent process */ kill(getppid(), SIGTERM); } @@ -245,7 +277,7 @@ main (int argc, const char *argv[]) /* go */ if (testBundle == NULL) { - /* start primary (cache management) thread */ + /* start primary (store management) thread */ server_loop(); } else { /* load/initialize/start specified plug-in */ diff --git a/configd.tproj/configd_server.c b/configd.tproj/configd_server.c index 69a1911..d589c69 100644 --- a/configd.tproj/configd_server.c +++ b/configd.tproj/configd_server.c @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include #include @@ -34,14 +44,13 @@ extern struct rpc_subsystem _config_subsystem; extern boolean_t config_server(mach_msg_header_t *, mach_msg_header_t *); /* server state information */ -CFMachPortRef configd_port; /* configd server port (for new session requests) */ +CFMachPortRef configd_port; /* configd server port (for new session requests) */ boolean_t config_demux(mach_msg_header_t *request, mach_msg_header_t *reply) { - boolean_t processed = FALSE; - + Boolean processed = FALSE; mach_msg_format_0_trailer_t *trailer; /* Feed the request into the ("MiG" generated) server */ @@ -61,14 +70,14 @@ config_demux(mach_msg_header_t *request, mach_msg_header_t *reply) (trailer->msgh_trailer_size >= MACH_MSG_TRAILER_FORMAT_0_SIZE)) { thisSession->callerEUID = trailer->msgh_sender.val[0]; thisSession->callerEGID = trailer->msgh_sender.val[1]; - SCDLog(LOG_DEBUG, CFSTR("caller has eUID = %d, eGID = %d"), + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("caller has eUID = %d, eGID = %d"), thisSession->callerEUID, thisSession->callerEGID); } else { - static boolean_t warned = FALSE; + static Boolean warned = FALSE; if (!warned) { - SCDLog(LOG_WARNING, CFSTR("caller's credentials not available.")); + SCLog(_configd_verbose, LOG_WARNING, CFSTR("caller's credentials not available.")); warned = TRUE; } thisSession->callerEUID = 0; @@ -88,8 +97,15 @@ config_demux(mach_msg_header_t *request, mach_msg_header_t *reply) } if (!processed) { - SCDLog(LOG_WARNING, CFSTR("unknown message received")); - exit (EX_OSERR); + SCLog(TRUE, LOG_ERR, CFSTR("unknown message ID (%d) received"), request->msgh_id); + + reply->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request->msgh_bits), 0); + reply->msgh_remote_port = request->msgh_remote_port; + reply->msgh_size = sizeof(mig_reply_error_t); /* Minimal size */ + reply->msgh_local_port = MACH_PORT_NULL; + reply->msgh_id = request->msgh_id; + ((mig_reply_error_t *)reply)->NDR = NDR_record; + ((mig_reply_error_t *)reply)->RetCode = MIG_BAD_ID; } return processed; @@ -176,6 +192,7 @@ configdCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) } CFAllocatorDeallocate(NULL, bufReply); + return; } @@ -225,7 +242,7 @@ server_init() /* Getting bootstrap server port */ status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port); if (status != KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status)); exit (EX_UNAVAILABLE); } @@ -234,7 +251,7 @@ server_init() switch (status) { case BOOTSTRAP_SUCCESS : if (active) { - SCDLog(LOG_DEBUG, CFSTR("\"%s\" is currently active, exiting."), SCD_SERVER); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("\"%s\" is currently active, exiting."), SCD_SERVER); exit (EX_UNAVAILABLE); } break; @@ -264,20 +281,20 @@ server_init() /* Create a session for the primary / new connection port */ (void) addSession(configd_port); - SCDLog(LOG_DEBUG, CFSTR("Registering service \"%s\""), SCD_SERVER); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Registering service \"%s\""), SCD_SERVER); status = bootstrap_register(bootstrap_port, SCD_SERVER, CFMachPortGetPort(configd_port)); switch (status) { case BOOTSTRAP_SUCCESS : /* service not currently registered, "a good thing" (tm) */ break; case BOOTSTRAP_NOT_PRIVILEGED : - SCDLog(LOG_ERR, CFSTR("bootstrap_register(): bootstrap not privileged")); + SCLog(_configd_verbose, LOG_ERR, CFSTR("bootstrap_register(): bootstrap not privileged")); exit (EX_OSERR); case BOOTSTRAP_SERVICE_ACTIVE : - SCDLog(LOG_ERR, CFSTR("bootstrap_register(): bootstrap service active")); + SCLog(_configd_verbose, LOG_ERR, CFSTR("bootstrap_register(): bootstrap service active")); exit (EX_OSERR); default : - SCDLog(LOG_ERR, CFSTR("bootstrap_register(): %s"), mach_error_string(status)); + SCLog(_configd_verbose, LOG_ERR, CFSTR("bootstrap_register(): %s"), mach_error_string(status)); exit (EX_OSERR); } @@ -292,18 +309,16 @@ server_loop() int rlStatus; while (TRUE) { - boolean_t isLocked = SCDOptionGet(NULL, kSCDOptionIsLocked); - /* * if linked with a DEBUG version of the framework, display some * debugging information */ - _showMachPortStatus(); + __showMachPortStatus(); /* * process one run loop event */ - rlMode = isLocked ? CFSTR("locked") : kCFRunLoopDefaultMode; + rlMode = (storeLocked > 0) ? CFSTR("locked") : kCFRunLoopDefaultMode; rlStatus = CFRunLoopRunInMode(rlMode, 1.0e10, TRUE); /* diff --git a/configd.tproj/configd_server.h b/configd.tproj/configd_server.h index bc5708c..cb1c29c 100644 --- a/configd.tproj/configd_server.h +++ b/configd.tproj/configd_server.h @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _S_CONFIGD_SERVER_H #define _S_CONFIGD_SERVER_H @@ -33,116 +43,144 @@ extern CFMachPortRef configd_port; /* configd server port (for new session req __BEGIN_DECLS -void configdCallback __P((CFMachPortRef port, - void *msg, - CFIndex size, - void *info)); - -boolean_t server_active __P(()); -void server_init __P(()); - -void server_loop __P(()); - -kern_return_t _snapshot __P((mach_port_t server, int *scd_status)); - -kern_return_t _configopen __P((mach_port_t server, - xmlData_t name, - mach_msg_type_number_t nameCnt, - mach_port_t *newServer, - int *scd_status)); - -kern_return_t _configclose __P((mach_port_t server, int *scd_status)); - -kern_return_t _configlock __P((mach_port_t server, int *scd_status)); - -kern_return_t _configunlock __P((mach_port_t server, int *scd_status)); - -kern_return_t _configlist __P((mach_port_t server, - xmlData_t key, - mach_msg_type_number_t keyCnt, - int regexOptions, - xmlDataOut_t *list, - mach_msg_type_number_t *listCnt, - int *scd_status)); - -kern_return_t _configadd __P((mach_port_t server, - xmlData_t key, - mach_msg_type_number_t keyCnt, - xmlData_t data, - mach_msg_type_number_t dataCnt, - int *newInstance, - int *scd_status)); - -kern_return_t _configadd_s __P((mach_port_t server, - xmlData_t key, - mach_msg_type_number_t keyCnt, - xmlData_t data, - mach_msg_type_number_t dataCnt, - int *newInstance, - int *scd_status)); - -kern_return_t _configget __P((mach_port_t server, - xmlData_t key, - mach_msg_type_number_t keyCnt, - xmlDataOut_t *data, - mach_msg_type_number_t *dataCnt, - int *newInstance, - int *scd_status)); - -kern_return_t _configset __P((mach_port_t server, - xmlData_t key, - mach_msg_type_number_t keyCnt, - xmlData_t data, - mach_msg_type_number_t dataCnt, - int *newInstance, - int *scd_status)); - -kern_return_t _configremove __P((mach_port_t server, - xmlData_t key, - mach_msg_type_number_t keyCnt, - int *scd_status)); - -kern_return_t _configtouch __P((mach_port_t server, - xmlData_t key, - mach_msg_type_number_t keyCnt, - int *scd_status)); - -kern_return_t _notifyadd __P((mach_port_t server, - xmlData_t key, - mach_msg_type_number_t keyCnt, - int regexOptions, - int *status)); - -kern_return_t _notifyremove __P((mach_port_t server, - xmlData_t key, - mach_msg_type_number_t keyCnt, - int regexOptions, - int *status)); - -kern_return_t _notifychanges __P((mach_port_t server, - xmlDataOut_t *list, - mach_msg_type_number_t *listCnt, - int *status)); - -kern_return_t _notifyviaport __P((mach_port_t server, - mach_port_t port, - mach_msg_id_t msgid, - int *status)); - -kern_return_t _notifyviafd __P((mach_port_t server, - xmlData_t path, - mach_msg_type_number_t pathCnt, - int identifier, - int *status)); +void configdCallback (CFMachPortRef port, + void *msg, + CFIndex size, + void *info); + +boolean_t server_active (); + +void server_init (); + +void server_loop (); + +kern_return_t _snapshot (mach_port_t server, + int *sc_status); + +kern_return_t _configopen (mach_port_t server, + xmlData_t nameRef, + mach_msg_type_number_t nameLen, + mach_port_t *newServer, + int *sc_status); + +kern_return_t _configclose (mach_port_t server, + int *sc_status); + +kern_return_t _configlock (mach_port_t server, + int *sc_status); + +kern_return_t _configunlock (mach_port_t server, + int *sc_status); + +kern_return_t _configlist (mach_port_t server, + xmlData_t keyRef, + mach_msg_type_number_t keyLen, + int isRegex, + xmlDataOut_t *listRef, + mach_msg_type_number_t *listLen, + int *sc_status); + +kern_return_t _configadd (mach_port_t server, + xmlData_t keyRef, + mach_msg_type_number_t keyLen, + xmlData_t dataRef, + mach_msg_type_number_t dataLen, + int *newInstance, + int *sc_status); + +kern_return_t _configadd_s (mach_port_t server, + xmlData_t keyRef, + mach_msg_type_number_t keyLen, + xmlData_t dataRef, + mach_msg_type_number_t dataLen, + int *newInstance, + int *sc_status); + +kern_return_t _configget (mach_port_t server, + xmlData_t keyRef, + mach_msg_type_number_t keyLen, + xmlDataOut_t *dataRef, + mach_msg_type_number_t *dataLen, + int *newInstance, + int *sc_status); + +kern_return_t _configset (mach_port_t server, + xmlData_t keyRef, + mach_msg_type_number_t keyLen, + xmlData_t dataRef, + mach_msg_type_number_t dataLen, + int *newInstance, + int *sc_status); + +kern_return_t _configremove (mach_port_t server, + xmlData_t keyRef, + mach_msg_type_number_t keyLen, + int *sc_status); + +kern_return_t _configtouch (mach_port_t server, + xmlData_t keyRef, + mach_msg_type_number_t keyLen, + int *sc_status); + +kern_return_t _confignotify (mach_port_t server, + xmlData_t keyRef, + mach_msg_type_number_t keyLen, + int *sc_status); + +kern_return_t _configget_m (mach_port_t server, + xmlData_t keysRef, + mach_msg_type_number_t keysLen, + xmlData_t patternsRef, + mach_msg_type_number_t patternsLen, + xmlDataOut_t *dataRef, + mach_msg_type_number_t *dataLen, + int *sc_status); + +kern_return_t _configset_m (mach_port_t server, + xmlData_t dataRef, + mach_msg_type_number_t dataLen, + xmlData_t removeRef, + mach_msg_type_number_t removeLen, + xmlData_t notifyRef, + mach_msg_type_number_t notifyLen, + int *sc_status); + +kern_return_t _notifyadd (mach_port_t server, + xmlData_t keyRef, + mach_msg_type_number_t keyLen, + int isRegex, + int *status); + +kern_return_t _notifyremove (mach_port_t server, + xmlData_t keyRef, + mach_msg_type_number_t keyLen, + int isRegex, + int *status); + +kern_return_t _notifychanges (mach_port_t server, + xmlDataOut_t *listRef, + mach_msg_type_number_t *listLen, + int *status); + +kern_return_t _notifyviaport (mach_port_t server, + mach_port_t port, + mach_msg_id_t msgid, + int *status); + +kern_return_t _notifyviafd (mach_port_t server, + xmlData_t pathRef, + mach_msg_type_number_t pathLen, + int identifier, + int *status); kern_return_t _notifyviasignal - __P((mach_port_t server, - task_t task, - int signal, - int *status)); + (mach_port_t server, + task_t task, + int signal, + int *status); -kern_return_t _notifycancel __P((mach_port_t server, - int *scd_status)); +kern_return_t _notifycancel (mach_port_t server, + int *sc_status); __END_DECLS diff --git a/configd.tproj/notify.c b/configd.tproj/notify.c index b87dd9e..3248c92 100644 --- a/configd.tproj/notify.c +++ b/configd.tproj/notify.c @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 31, 2000 Allan Nathanson + * - initial revision + */ + #include @@ -31,11 +41,11 @@ void pushNotifications() { - void **sessionsToNotify; - CFIndex notifyCnt; - int server; - serverSessionRef theSession; - SCDSessionPrivateRef sessionPrivate; + void **sessionsToNotify; + CFIndex notifyCnt; + int server; + serverSessionRef theSession; + SCDynamicStorePrivateRef storePrivate; if (needsNotification == NULL) return; /* if no sessions need to be kicked */ @@ -48,36 +58,27 @@ pushNotifications() kCFNumberIntType, &server); theSession = getSession(server); - sessionPrivate = (SCDSessionPrivateRef)theSession->session; - - /* - * handle callbacks for "configd" plug-ins - */ - if (sessionPrivate->callbackFunction != NULL) { - SCDLog(LOG_DEBUG, CFSTR("executing notifiction callback function (server=%d)."), - sessionPrivate->server); - (void) (*sessionPrivate->callbackFunction)(theSession->session, - sessionPrivate->callbackArgument); - } + storePrivate = (SCDynamicStorePrivateRef)theSession->store; /* * deliver notifications to client sessions */ - if (sessionPrivate->notifyPort != MACH_PORT_NULL) { + if ((storePrivate->notifyStatus == Using_NotifierInformViaMachPort) && + (storePrivate->notifyPort != MACH_PORT_NULL)) { mach_msg_empty_send_t msg; mach_msg_option_t options; kern_return_t status; /* * Post notification as mach message */ - SCDLog(LOG_DEBUG, CFSTR("sending mach message notification.")); - SCDLog(LOG_DEBUG, CFSTR(" port = %d"), sessionPrivate->notifyPort); - SCDLog(LOG_DEBUG, CFSTR(" msgid = %d"), sessionPrivate->notifyPortIdentifier); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("sending mach message notification.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" port = %d"), storePrivate->notifyPort); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" msgid = %d"), storePrivate->notifyPortIdentifier); msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); msg.header.msgh_size = sizeof(msg); - msg.header.msgh_remote_port = sessionPrivate->notifyPort; + msg.header.msgh_remote_port = storePrivate->notifyPort; msg.header.msgh_local_port = MACH_PORT_NULL; - msg.header.msgh_id = sessionPrivate->notifyPortIdentifier; + msg.header.msgh_id = storePrivate->notifyPortIdentifier; options = MACH_SEND_TIMEOUT; status = mach_msg(&msg.header, /* msg */ MACH_SEND_MSG|options, /* options */ @@ -88,64 +89,66 @@ pushNotifications() MACH_PORT_NULL); /* notify */ } - if (sessionPrivate->notifyFile >= 0) { + if ((storePrivate->notifyStatus == Using_NotifierInformViaFD) && + (storePrivate->notifyFile >= 0)) { ssize_t written; - SCDLog(LOG_DEBUG, CFSTR("sending (UNIX domain) socket notification")); - SCDLog(LOG_DEBUG, CFSTR(" fd = %d"), sessionPrivate->notifyFile); - SCDLog(LOG_DEBUG, CFSTR(" msgid = %d"), sessionPrivate->notifyFileIdentifier); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("sending (UNIX domain) socket notification")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" fd = %d"), storePrivate->notifyFile); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" msgid = %d"), storePrivate->notifyFileIdentifier); - written = write(sessionPrivate->notifyFile, - &sessionPrivate->notifyFileIdentifier, - sizeof(sessionPrivate->notifyFileIdentifier)); + written = write(storePrivate->notifyFile, + &storePrivate->notifyFileIdentifier, + sizeof(storePrivate->notifyFileIdentifier)); if (written == -1) { if (errno == EWOULDBLOCK) { - SCDLog(LOG_DEBUG, + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("sorry, only one outstanding notification per session.")); } else { - SCDLog(LOG_DEBUG, + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send notification, write() failed: %s"), strerror(errno)); - sessionPrivate->notifyFile = -1; + storePrivate->notifyFile = -1; } - } else if (written != sizeof(sessionPrivate->notifyFileIdentifier)) { - SCDLog(LOG_DEBUG, + } else if (written != sizeof(storePrivate->notifyFileIdentifier)) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send notification, incomplete write()")); - sessionPrivate->notifyFile = -1; + storePrivate->notifyFile = -1; } } - if (sessionPrivate->notifySignal > 0) { + if ((storePrivate->notifyStatus == Using_NotifierInformViaSignal) && + (storePrivate->notifySignal > 0)) { kern_return_t status; pid_t pid; /* * Post notification as signal */ - status = pid_for_task(sessionPrivate->notifySignalTask, &pid); + status = pid_for_task(storePrivate->notifySignalTask, &pid); if (status == KERN_SUCCESS) { - SCDLog(LOG_DEBUG, CFSTR("sending signal notification")); - SCDLog(LOG_DEBUG, CFSTR(" pid = %d"), pid); - SCDLog(LOG_DEBUG, CFSTR(" signal = %d"), sessionPrivate->notifySignal); - if (kill(pid, sessionPrivate->notifySignal) != 0) { - SCDLog(LOG_DEBUG, CFSTR("could not send signal: %s"), strerror(errno)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("sending signal notification")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" pid = %d"), pid); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" signal = %d"), storePrivate->notifySignal); + if (kill(pid, storePrivate->notifySignal) != 0) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), strerror(errno)); status = KERN_FAILURE; } } else { mach_port_type_t pt; - if ((mach_port_type(mach_task_self(), sessionPrivate->notifySignalTask, &pt) == KERN_SUCCESS) && + if ((mach_port_type(mach_task_self(), storePrivate->notifySignalTask, &pt) == KERN_SUCCESS) && (pt & MACH_PORT_TYPE_DEAD_NAME)) { - SCDLog(LOG_DEBUG, CFSTR("could not send signal, process died")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal, process died")); } else { - SCDLog(LOG_DEBUG, CFSTR("could not send signal: %s"), mach_error_string(status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), mach_error_string(status)); } } if (status != KERN_SUCCESS) { /* don't bother with any more attempts */ - (void) mach_port_destroy(mach_task_self(), sessionPrivate->notifySignalTask); - sessionPrivate->notifySignal = 0; - sessionPrivate->notifySignalTask = TASK_NULL; + (void) mach_port_destroy(mach_task_self(), storePrivate->notifySignalTask); + storePrivate->notifySignal = 0; + storePrivate->notifySignalTask = TASK_NULL; } } } diff --git a/configd.tproj/notify.h b/configd.tproj/notify.h index cd1f018..790e781 100644 --- a/configd.tproj/notify.h +++ b/configd.tproj/notify.h @@ -20,6 +20,13 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * March 31, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _S_NOTIFY_H #define _S_NOTIFY_H @@ -27,7 +34,7 @@ __BEGIN_DECLS -void pushNotifications __P(()); +void pushNotifications (); __END_DECLS diff --git a/configd.tproj/notify_server.c b/configd.tproj/notify_server.c index c043d43..734b90d 100644 --- a/configd.tproj/notify_server.c +++ b/configd.tproj/notify_server.c @@ -20,8 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "session.h" +#include "notify.h" boolean_t notify_server(mach_msg_header_t *request, mach_msg_header_t *reply) @@ -35,7 +43,7 @@ notify_server(mach_msg_header_t *request, mach_msg_header_t *reply) switch (notify->not_header.msgh_id) { case MACH_NOTIFY_NO_SENDERS : - SCDLog(LOG_DEBUG, CFSTR("No more senders for port %d, closing."), + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("No more senders for port %d, closing."), notify->not_header.msgh_local_port); cleanupSession(notify->not_header.msgh_local_port); @@ -44,7 +52,7 @@ notify_server(mach_msg_header_t *request, mach_msg_header_t *reply) notify->not_header.msgh_remote_port = MACH_PORT_NULL; return TRUE; case MACH_NOTIFY_DEAD_NAME : - SCDLog(LOG_DEBUG, CFSTR("Dead name for port %d, closing."), + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Dead name for port %d, closing."), notify->not_header.msgh_local_port); cleanupSession(notify->not_header.msgh_local_port); @@ -56,7 +64,7 @@ notify_server(mach_msg_header_t *request, mach_msg_header_t *reply) break; } - SCDLog(LOG_DEBUG, CFSTR("HELP!, Received notification: port=%d, msgh_id=%d"), + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("HELP!, Received notification: port=%d, msgh_id=%d"), notify->not_header.msgh_local_port, notify->not_header.msgh_id); diff --git a/configd.tproj/notify_server.h b/configd.tproj/notify_server.h index 170d718..150b58e 100644 --- a/configd.tproj/notify_server.h +++ b/configd.tproj/notify_server.h @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _S_NOTIFY_SERVER_H #define _S_NOTIFY_SERVER_H @@ -28,7 +38,7 @@ __BEGIN_DECLS -boolean_t notify_server __P((mach_msg_header_t *request, mach_msg_header_t *reply)); +boolean_t notify_server (mach_msg_header_t *request, mach_msg_header_t *reply); __END_DECLS diff --git a/configd.tproj/plugin_support.c b/configd.tproj/plugin_support.c index fd6e3c8..b511a89 100644 --- a/configd.tproj/plugin_support.c +++ b/configd.tproj/plugin_support.c @@ -20,6 +20,19 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 11, 2001 Allan Nathanson + * - start using CFBundle code + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * May 26, 2000 Allan Nathanson + * - initial revision + */ + #include #include #include @@ -29,27 +42,17 @@ #include #include "configd.h" +#include /* - * Information maintained for each to-be-kicked registration. + * path components, extensions, entry points, ... */ -typedef struct { - /* - * bundle paths - */ - char bundle[MAXNAMLEN + 1]; /* bundle name */ - char path [MAXPATHLEN]; /* bundle path */ - - /* - * entry points for initialization code. - */ - SCDBundleStartRoutine_t start; /* address of start() routine */ - SCDBundlePrimeRoutine_t prime; /* address of prime() routine */ +#define BUNDLE_DIRECTORY "/SystemConfiguration" /* [/System/Library]/... */ +#define BUNDLE_DIR_EXTENSION ".bundle" -} plugin, *pluginRef; -CFMutableArrayRef plugins; +static CFMutableArrayRef allBundles = NULL; /* exception handling functions */ @@ -166,262 +169,296 @@ catch_exception_raise_state_identity(mach_port_t exception_port, } -static boolean_t -bundleLoad(pluginRef info) +static CFStringRef +shortBundleIdentifier(CFStringRef bundleID) { - int len; - NSObjectFileImage image; - NSObjectFileImageReturnCode status; - NSModule module; - NSSymbol symbol; - unsigned long options; - char *bundleExe; /* full path of bundle executable */ - struct stat sb; + CFIndex len = CFStringGetLength(bundleID); + CFRange range; + CFStringRef shortID = NULL; + + if (CFStringFindWithOptions(bundleID, + CFSTR("."), + CFRangeMake(0, len), + kCFCompareBackwards, + &range)) { + range.location = range.location + range.length; + range.length = len - range.location; + shortID = CFStringCreateWithSubstring(NULL, bundleID, range); + } - /* - * allocate enough space for the bundle directory path, a "/" separator, - * the bundle name, and the (optional) "_debug" extension. - */ + return shortID; +} - len = strlen(info->path); /* path */ - len += sizeof(BUNDLE_NEW_SUBDIR) - 1; /* "/" or "/Contents/MacOS/" */ - len += strlen(info->bundle); /* bundle name */ - len += sizeof(BUNDLE_DEBUG_EXTENSION); /* "_debug" (and NUL) */ - bundleExe = CFAllocatorAllocate(NULL, len, 0); - - /* check for the (old layout) bundle executable path */ - strcpy(bundleExe, info->path); - strcat(bundleExe, BUNDLE_OLD_SUBDIR); - strcat(bundleExe, info->bundle); - if (stat(bundleExe, &sb) == 0) { - goto load; - } - /* check for the "_debug" version */ - strcat(bundleExe, BUNDLE_DEBUG_EXTENSION); - if (stat(bundleExe, &sb) == 0) { - goto load; +static void +loadBundle(const void *value, void *context) { + CFBundleRef bundle = (CFBundleRef)value; + CFStringRef bundleID = CFBundleGetIdentifier(bundle); + Boolean bundleExclude = FALSE; + Boolean bundleVerbose = FALSE; + CFDictionaryRef dict; + void *func; + SCDynamicStoreBundleLoadFunction load; + Boolean loaded; + CFIndex *nLoaded = (CFIndex *)context; + + SCLog(TRUE, LOG_DEBUG, CFSTR("loading %@"), bundleID); + + bundleExclude = CFSetContainsValue(_plugins_exclude, bundleID); + if (!bundleExclude) { + CFStringRef shortID = shortBundleIdentifier(bundleID); + + if (shortID) { + bundleExclude = CFSetContainsValue(_plugins_exclude, shortID); + CFRelease(shortID); + } } - /* check for the (new layout) bundle executable path */ - strcpy(bundleExe, info->path); - strcat(bundleExe, BUNDLE_NEW_SUBDIR); - strcat(bundleExe, info->bundle); - if (stat(bundleExe, &sb) == 0) { - goto load; + if (bundleExclude) { + SCLog(TRUE, + LOG_DEBUG, + CFSTR("%@ load skipped"), + bundleID); + return; } - /* check for the "_debug" version */ - strcat(bundleExe, BUNDLE_DEBUG_EXTENSION); - if (stat(bundleExe, &sb) == 0) { - goto load; + loaded = CFBundleLoadExecutable(bundle); + if (!loaded) { + SCLog(TRUE, + LOG_NOTICE, + CFSTR("%@ load failed"), + bundleID); + return; } - SCDLog(LOG_ERR, - CFSTR("bundleLoad() failed, no executable for %s in %s"), - info->bundle, - info->path); - CFAllocatorDeallocate(NULL, bundleExe); - return FALSE; + if (!CFBundleIsExecutableLoaded(bundle)) { + SCLog(TRUE, + LOG_NOTICE, + CFSTR("%@ executable not loaded"), + bundleID); + return; + } - load : + /* bump the count of loaded bundles */ + *nLoaded = *nLoaded + 1; - /* load the bundle */ - SCDLog(LOG_DEBUG, CFSTR("loading %s"), bundleExe); - status = NSCreateObjectFileImageFromFile(bundleExe, &image); - if (status != NSObjectFileImageSuccess) { - char *err; + /* identify any exception handling functions */ - switch (status) { - case NSObjectFileImageFailure : - err = "NSObjectFileImageFailure"; - break; - case NSObjectFileImageInappropriateFile : - err = "NSObjectFileImageInappropriateFile"; - break; - case NSObjectFileImageArch : - err = "NSObjectFileImageArch"; - break; - case NSObjectFileImageFormat : - err = "NSObjectFileImageFormat"; - break; - case NSObjectFileImageAccess : - err = "NSObjectFileImageAccess"; - break; - default : - err = "Unknown"; - break; - } - SCDLog(LOG_ERR, CFSTR("NSCreateObjectFileImageFromFile() failed")); - SCDLog(LOG_ERR, CFSTR(" executable path = %s"), bundleExe); - SCDLog(LOG_ERR, CFSTR(" error status = %s"), err); - CFAllocatorDeallocate(NULL, bundleExe); - return FALSE; + func = CFBundleGetFunctionPointerForName(bundle, CFSTR("catch_exception_raise")); + if (func) { + catch_exception_raise_func = func; } - options = NSLINKMODULE_OPTION_BINDNOW; - options |= NSLINKMODULE_OPTION_PRIVATE; - options |= NSLINKMODULE_OPTION_RETURN_ON_ERROR; - module = NSLinkModule(image, bundleExe, options); - - if (module == NULL) { - NSLinkEditErrors c; - int errorNumber; - const char *fileName; - const char *errorString; - - SCDLog(LOG_ERR, CFSTR("NSLinkModule() failed")); - SCDLog(LOG_ERR, CFSTR(" executable path = %s"), bundleExe); - - /* collect and report the details */ - NSLinkEditError(&c, &errorNumber, &fileName, &errorString); - SCDLog(LOG_ERR, CFSTR(" NSLinkEditErrors = %d"), (int)c); - SCDLog(LOG_ERR, CFSTR(" errorNumber = %d"), errorNumber); - if((fileName != NULL) && (*fileName != '\0')) - SCDLog(LOG_ERR, CFSTR(" fileName = %s"), fileName); - if((errorString != NULL) && (*errorString != '\0')) - SCDLog(LOG_ERR, CFSTR(" errorString = %s"), errorString); - - CFAllocatorDeallocate(NULL, bundleExe); - return FALSE; + func = CFBundleGetFunctionPointerForName(bundle, CFSTR("catch_exception_raise_state")); + if (func) { + catch_exception_raise_state_func = func; } - CFAllocatorDeallocate(NULL, bundleExe); - - /* identify the initialization functions */ - - symbol = NSLookupSymbolInModule(module, BUNDLE_ENTRY_POINT); - if (symbol) { - info->start = NSAddressOfSymbol(symbol); + func = CFBundleGetFunctionPointerForName(bundle, CFSTR("catch_exception_raise_identity")); + if (func) { + catch_exception_raise_identity_func = func; } - symbol = NSLookupSymbolInModule(module, BUNDLE_ENTRY_POINT2); - if (symbol) { - info->prime = NSAddressOfSymbol(symbol); - } + /* if defined, call the bundles load() function */ - if ((info->start == NULL) && (info->prime == NULL)) { - SCDLog(LOG_DEBUG, CFSTR(" no entry points")); - return FALSE; + load = CFBundleGetFunctionPointerForName(bundle, CFSTR("load")); + if (!load) { + return; } - /* identify any exception handling functions */ + bundleVerbose = CFSetContainsValue(_plugins_verbose, bundleID); + if (!bundleVerbose) { + CFStringRef shortID = shortBundleIdentifier(bundleID); - symbol = NSLookupSymbolInModule(module, "_catch_exception_raise"); - if (symbol) { - catch_exception_raise_func = NSAddressOfSymbol(symbol); + if (shortID) { + bundleVerbose = CFSetContainsValue(_plugins_verbose, shortID); + CFRelease(shortID); + } } - symbol = NSLookupSymbolInModule(module, "_catch_exception_raise_state"); - if (symbol) { - catch_exception_raise_state_func = NSAddressOfSymbol(symbol); - } + if (!bundleVerbose) { + dict = CFBundleGetInfoDictionary(bundle); + if (isA_CFDictionary(dict)) { + CFBooleanRef bool; - symbol = NSLookupSymbolInModule(module, "_catch_exception_raise_identity"); - if (symbol) { - catch_exception_raise_identity_func = NSAddressOfSymbol(symbol); + bool = CFDictionaryGetValue(dict, kSCBundleVerbose); + if (isA_CFBoolean(bool) && CFBooleanGetValue(bool)) { + bundleVerbose = TRUE; + } + } } - return TRUE; + (*load)(bundle, bundleVerbose); + return; } static void -bundleStart(const void *value, void *context) -{ - CFDataRef data = (CFDataRef)value; - pluginRef info; - - info = (pluginRef)CFDataGetBytePtr(data); - if (info->start) { - (*info->start)(info->bundle, info->path); +startBundle(const void *value, void *context) { + CFBundleRef bundle = (CFBundleRef)value; + CFURLRef bundleURL; + char bundleName[MAXNAMLEN + 1]; + char bundlePath[MAXPATHLEN]; + char *cp; + CFDictionaryRef dict; + int len; + Boolean ok; + SCDynamicStoreBundleStartFunction start; + + if (!CFBundleIsExecutableLoaded(bundle)) { + return; } -} + start = CFBundleGetFunctionPointerForName(bundle, CFSTR("start")); + if (!start) { + return; + } -static void -bundlePrime(const void *value, void *context) -{ - CFDataRef data = (CFDataRef)value; - pluginRef info; + dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundle)); + if (!dict) { + return; + } - info = (pluginRef)CFDataGetBytePtr(data); - if (info->prime) { - (*info->prime)(info->bundle, info->path); + bundleURL = CFBundleCopyBundleURL(bundle); + if (!bundleURL) { + return; } -} + ok = CFURLGetFileSystemRepresentation(bundleURL, + TRUE, + (UInt8 *)&bundlePath, + sizeof(bundlePath)); + CFRelease(bundleURL); + if (!ok) { + return; + } -static void -loadOne(const char *bundleDir, const char *bundleName) -{ - CFMutableDataRef info; - pluginRef pluginInfo; - int len; + cp = strrchr(bundlePath, '/'); + if (cp) { + cp++; + } else { + cp = bundlePath; + } /* check if this directory entry is a valid bundle name */ - len = strlen(bundleName); + len = strlen(cp); if (len <= sizeof(BUNDLE_DIR_EXTENSION)) { /* if entry name isn't long enough */ return; } len -= sizeof(BUNDLE_DIR_EXTENSION) - 1; - if (strcmp(&bundleName[len], BUNDLE_DIR_EXTENSION) != 0) { + if (strcmp(&cp[len], BUNDLE_DIR_EXTENSION) != 0) { /* if entry name doesn end with ".bundle" */ return; } - info = CFDataCreateMutable(NULL, sizeof(plugin)); - pluginInfo = (pluginRef)CFDataGetBytePtr(info); - pluginInfo->start = NULL; - pluginInfo->prime = NULL; - /* get (just) the bundle's name */ - pluginInfo->bundle[0] = '\0'; - (void) strncat(pluginInfo->bundle, bundleName, len); - - /* get the bundle directory path */ - (void) sprintf(pluginInfo->path, "%s/%s", bundleDir, bundleName); - - /* load the bundle */ - if (bundleLoad(pluginInfo)) { - SCDLog(LOG_INFO, CFSTR("%s loaded"), bundleName); - CFArrayAppendValue(plugins, info); - } else { - SCDLog(LOG_ERR, CFSTR("load of \"%s\" failed"), bundleName); - } - CFRelease(info); + bundleName[0] = '\0'; + (void) strncat(bundleName, cp, len); + (*start)(bundleName, bundlePath); return; } static void -loadAll(const char *bundleDir) -{ - DIR *dirp; - struct dirent *dp; +primeBundle(const void *value, void *context) { + CFBundleRef bundle = (CFBundleRef)value; + SCDynamicStoreBundlePrimeFunction prime; - dirp = opendir(bundleDir); - if (dirp == NULL) { - /* if no plugin directory */ + if (!CFBundleIsExecutableLoaded(bundle)) { return; } - while ((dp = readdir(dirp)) != NULL) { - loadOne(bundleDir, dp->d_name); + prime = CFBundleGetFunctionPointerForName(bundle, CFSTR("prime")); + if (!prime) { + return; } - closedir(dirp); + (*prime)(); return; } -void +static void timerCallback(CFRunLoopTimerRef timer, void *info) { - SCDLog(LOG_INFO, CFSTR("the CFRunLoop is waiting for something to happen....")); + SCLog(_configd_verbose, + LOG_INFO, + CFSTR("the CFRunLoop is waiting for something to happen....")); + return; +} + + +static void +sortBundles(CFMutableArrayRef orig) +{ + CFMutableArrayRef new; + + new = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + while (CFArrayGetCount(orig) > 0) { + int i; + Boolean inserted = FALSE; + + for (i = 0; i < CFArrayGetCount(orig); i++) { + CFBundleRef bundle1 = CFArrayGetValueAtIndex(orig, i); + CFStringRef bundleID1 = CFBundleGetIdentifier(bundle1); + int count; + CFDictionaryRef dict; + int j; + CFArrayRef requires = NULL; + + dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundle1)); + if (dict) { + requires = CFDictionaryGetValue(dict, kSCBundleRequires); + requires = isA_CFArray(requires); + } + if (bundleID1 == NULL || requires == NULL) { + CFArrayInsertValueAtIndex(new, 0, bundle1); + CFArrayRemoveValueAtIndex(orig, i); + inserted = TRUE; + break; + } + count = CFArrayGetCount(requires); + for (j = 0; j < CFArrayGetCount(requires); j++) { + int k; + CFStringRef r = CFArrayGetValueAtIndex(requires, j); + + for (k = 0; k < CFArrayGetCount(new); k++) { + CFBundleRef bundle2 = CFArrayGetValueAtIndex(new, k); + CFStringRef bundleID2 = CFBundleGetIdentifier(bundle2); + + if (bundleID2 && CFEqual(bundleID2, r)) { + count--; + } + } + } + if (count == 0) { + /* all dependencies are met, append */ + CFArrayAppendValue(new, bundle1); + CFArrayRemoveValueAtIndex(orig, i); + inserted = TRUE; + break; + } + } + + if (inserted == FALSE) { + SCLog(TRUE, LOG_NOTICE, CFSTR("Bundles have circular dependency!!!")); + break; + } + } + if (CFArrayGetCount(orig) > 0) { + /* we have a circular dependency, append remaining items on new array */ + CFArrayAppendArray(new, orig, CFRangeMake(0, CFArrayGetCount(orig))); + } + else { + /* new one is a sorted version of original */ + } + + CFArrayRemoveAllValues(orig); + CFArrayAppendArray(orig, new, CFRangeMake(0, CFArrayGetCount(new))); + CFRelease(new); return; } @@ -429,66 +466,113 @@ timerCallback(CFRunLoopTimerRef timer, void *info) void * plugin_exec(void *arg) { - NSSearchPathEnumerationState state; - char path[MAXPATHLEN]; + CFIndex nLoaded = 0; - /* keep track of loaded plugins */ - plugins = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + /* keep track of bundles */ + allBundles = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); if (arg == NULL) { + char path[MAXPATHLEN]; + NSSearchPathEnumerationState state; + /* - * identify and load all plugins + * identify and load all bundles */ state = NSStartSearchPathEnumeration(NSLibraryDirectory, NSLocalDomainMask|NSSystemDomainMask); while ((state = NSGetNextSearchPathEnumeration(state, path))) { - /* load any available plugins */ + CFArrayRef bundles; + CFURLRef url; + + /* load any available bundle */ strcat(path, BUNDLE_DIRECTORY); - SCDLog(LOG_DEBUG, CFSTR("searching for plugins in \"%s\""), path); - loadAll(path); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("searching for bundles in \".\"")); + url = CFURLCreateFromFileSystemRepresentation(NULL, + path, + strlen(path), + TRUE); + bundles = CFBundleCreateBundlesFromDirectory(NULL, url, CFSTR(".bundle")); + CFRelease(url); + + if (bundles) { + CFArrayAppendArray(allBundles, + bundles, + CFRangeMake(0, CFArrayGetCount(bundles))); + CFRelease(bundles); + } } - if (SCDOptionGet(NULL, kSCDOptionDebug)) { - SCDLog(LOG_DEBUG, CFSTR("searching for plugins in \".\"")); - loadAll("."); - } + sortBundles(allBundles); } else { + CFBundleRef bundle; + CFURLRef url; + /* - * load the plugin specified on the command line + * load (only) the specified bundle */ - char *bn, *bd; - - if ((bn = strrchr((char *)arg, '/')) != NULL) { - int len; - - /* plug-in directory */ - len = bn - (char *)arg; - if (len == 0) - len++; /* if plugin is in the root directory */ - - bd = CFAllocatorAllocate(NULL, len + 1, 0); - bd[0] = '\0'; - (void) strncat(bd, (char *)arg, len); + url = CFURLCreateFromFileSystemRepresentation(NULL, + (char *)arg, + strlen((char *)arg), + TRUE); + bundle = CFBundleCreate(NULL, url); + if (bundle) { + CFArrayAppendValue(allBundles, bundle); + CFRelease(bundle); + } + CFRelease(url); + } - /* plug-in name */ - bn++; /* name starts just after trailing path separator */ - } else { - /* plug-in (in current) directory */ - bd = CFAllocatorAllocate(NULL, sizeof("."), 0); - (void) strcpy(bd, "."); + /* + * load each bundle and, if defined, call its load() function. This + * function (or the start() function) should initialize any variables, + * open any sessions with "configd", and register any needed notifications. + * + * Note: Establishing initial information in the store should be + * deferred until the prime() initialization function so that + * any bundles which want to receive a notification that the + * data has changed will have an opportunity to install a + * notification handler. + */ + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle load() functions")); + CFArrayApplyFunction(allBundles, + CFRangeMake(0, CFArrayGetCount(allBundles)), + loadBundle, + &nLoaded); - /* plug-in name */ - bn = (char *)arg; /* no path separators */ - } + /* + * If defined, call each bundles start() function. This function is + * called after the bundle has been loaded and its load() function has + * been called. It should initialize any variables, open any sessions + * with "configd", and register any needed notifications. + * + * Note: Establishing initial information in the store should be + * deferred until the prime() initialization function so that + * any bundles which want to receive a notification that the + * data has changed will have an opportunity to install a + * notification handler. + */ + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle start() functions")); + CFArrayApplyFunction(allBundles, + CFRangeMake(0, CFArrayGetCount(allBundles)), + startBundle, + NULL); - loadOne(bd, bn); + /* + * If defined, call each bundles prime() function. This function is + * called after the bundle has been loaded and its load() and start() + * functions have been called. It should initialize any configuration + * information and/or state in the store. + */ + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle prime() functions")); + CFArrayApplyFunction(allBundles, + CFRangeMake(0, CFArrayGetCount(allBundles)), + primeBundle, + NULL); - CFAllocatorDeallocate(NULL, bd); + if (arg == NULL && (nLoaded > 0)) { + CFRunLoopTimerRef timer; /* allocate a periodic event (to help show we're not blocking) */ - if (CFArrayGetCount(plugins)) { - CFRunLoopTimerRef timer; - timer = CFRunLoopTimerCreate(NULL, /* allocator */ CFAbsoluteTimeGetCurrent() + 1.0, /* fireDate */ 60.0, /* interval */ @@ -499,40 +583,10 @@ plugin_exec(void *arg) CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); CFRelease(timer); } - } - - /* - * execute each plugins start() function which should initialize any - * variables, open any sessions with "configd", and register any needed - * notifications. Establishing initial information in the cache should - * be deferred until the prime() initialization function so that any - * plug-ins which want to receive a notification that the data has - * changed will have an opportunity to install a notification handler. - */ - SCDLog(LOG_DEBUG, CFSTR("calling plugin start() functions")); - CFArrayApplyFunction(plugins, - CFRangeMake(0, CFArrayGetCount(plugins)), - bundleStart, - NULL); - - /* - * execute each plugins prime() function which should initialize any - * configuration information and/or state in the cache. - */ - SCDLog(LOG_DEBUG, CFSTR("calling plugin prime() functions")); - CFArrayApplyFunction(plugins, - CFRangeMake(0, CFArrayGetCount(plugins)), - bundlePrime, - NULL); - - /* - * all plugins have been loaded and started. - */ - CFRelease(plugins); - if (!SCDOptionGet(NULL, kSCDOptionDebug) && (arg == NULL)) { - /* synchronize with parent process */ - kill(getppid(), SIGTERM); + if (_configd_fork) { + /* synchronize with parent process */ + kill(getppid(), SIGTERM); } /* @@ -542,9 +596,9 @@ plugin_exec(void *arg) * needs to wait and/or block at any time it should do so only in its a * private thread. */ - SCDLog(LOG_DEBUG, CFSTR("starting plugin CFRunLoop")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("starting plugin CFRunLoop")); CFRunLoopRun(); - SCDLog(LOG_INFO, CFSTR("what, no more work for the \"configd\" plugins?")); + SCLog(_configd_verbose, LOG_INFO, CFSTR("what, no more work for the \"configd\" bundles?")); return NULL; } @@ -555,14 +609,14 @@ plugin_init() pthread_attr_t tattr; pthread_t tid; - SCDLog(LOG_DEBUG, CFSTR("Starting thread for plug-ins...")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Starting thread for plug-ins...")); pthread_attr_init(&tattr); pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); // pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack pthread_create(&tid, &tattr, plugin_exec, NULL); pthread_attr_destroy(&tattr); - SCDLog(LOG_DEBUG, CFSTR(" thread id=0x%08x"), tid); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" thread id=0x%08x"), tid); return; } diff --git a/configd.tproj/plugin_support.h b/configd.tproj/plugin_support.h index 072e3c1..5097a4c 100644 --- a/configd.tproj/plugin_support.h +++ b/configd.tproj/plugin_support.h @@ -20,6 +20,13 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * May 26, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _S_PLUGIN_SUPPORT_H #define _S_PLUGIN_SUPPORT_H @@ -27,8 +34,8 @@ __BEGIN_DECLS -void plugin_init __P(()); -void plugin_exec __P((void *arg)); +void plugin_init (); +void plugin_exec (void *arg); __END_DECLS diff --git a/configd.tproj/session.c b/configd.tproj/session.c index 88577cd..0ded56d 100644 --- a/configd.tproj/session.c +++ b/configd.tproj/session.c @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #include "configd.h" #include "configd_server.h" #include "session.h" @@ -35,7 +45,7 @@ getSession(mach_port_t server) int i; if (server == MACH_PORT_NULL) { - SCDLog(LOG_NOTICE, CFSTR("Excuse me, why is getSession() being called with an invalid port?")); + SCLog(_configd_verbose, LOG_NOTICE, CFSTR("Excuse me, why is getSession() being called with an invalid port?")); return NULL; } @@ -48,9 +58,9 @@ getSession(mach_port_t server) continue; } else if (thisSession->key == server) { return thisSession; /* we've seen this server before */ - } else if ((thisSession->session != NULL) && - (((SCDSessionPrivateRef)thisSession->session)->notifySignalTask == server)) { - return thisSession; + } else if (thisSession->store && + (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) { + return thisSession; } } } @@ -86,12 +96,12 @@ addSession(CFMachPortRef server) } } - SCDLog(LOG_DEBUG, CFSTR("Allocating new session for port %d"), CFMachPortGetPort(server)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Allocating new session for port %d"), CFMachPortGetPort(server)); sessions[n] = malloc(sizeof(serverSession)); sessions[n]->key = CFMachPortGetPort(server); sessions[n]->serverPort = server; sessions[n]->serverRunLoopSource = NULL; - sessions[n]->session = NULL; + sessions[n]->store = NULL; sessions[n]->callerEUID = 1; /* not "root" */ sessions[n]->callerEGID = 1; /* not "wheel" */ @@ -152,21 +162,21 @@ cleanupSession(mach_port_t server) * Ensure that any changes made while we held the "lock" * are discarded. */ - if (SCDOptionGet(NULL, kSCDOptionIsLocked) && - SCDOptionGet(thisSession->session, kSCDOptionIsLocked)) { + if ((storeLocked > 0) && + ((SCDynamicStorePrivateRef)thisSession->store)->locked) { /* - * swap cache and associated data which, after + * swap store and associated data which, after * being closed, will result in the restoration * of the original pre-"locked" data. */ - _swapLockedCacheData(); + _swapLockedStoreData(); } /* * Close any open connections including cancelling any outstanding * notification requests and releasing any locks. */ - (void) _SCDClose(&thisSession->session); + (void) __SCDynamicStoreClose(&thisSession->store); /* * Lastly, remove the session entry. @@ -195,8 +205,8 @@ listSessions() fprintf(stderr, " %d", thisSession->key); - if (thisSession->session != NULL) { - task_t task = ((SCDSessionPrivateRef)thisSession->session)->notifySignalTask; + if (thisSession->store) { + task_t task = ((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask; if (task != TASK_NULL) { fprintf(stderr, "/%d", task); diff --git a/configd.tproj/session.h b/configd.tproj/session.h index 9d431de..023fd70 100644 --- a/configd.tproj/session.h +++ b/configd.tproj/session.h @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * March 24, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _S_SESSION_H #define _S_SESSION_H @@ -33,10 +43,10 @@ typedef struct { /* mach port associated with this session */ CFMachPortRef serverPort; - CFRunLoopSourceRef serverRunLoopSource; /* XXX CFMachPortInvalidate() doesn't work */ + CFRunLoopSourceRef serverRunLoopSource; /* data associated with this "open" session */ - SCDSessionRef session; + SCDynamicStoreRef store; /* credentials associated with this "open" session */ int callerEUID; @@ -46,15 +56,15 @@ typedef struct { __BEGIN_DECLS -serverSessionRef getSession __P((mach_port_t server)); +serverSessionRef getSession (mach_port_t server); -serverSessionRef addSession __P((CFMachPortRef server)); +serverSessionRef addSession (CFMachPortRef server); -void removeSession __P((mach_port_t server)); +void removeSession (mach_port_t server); -void cleanupSession __P((mach_port_t server)); +void cleanupSession (mach_port_t server); -void listSessions __P(()); +void listSessions (); __END_DECLS diff --git a/scselect.tproj/Makefile b/scselect.tproj/Makefile index 64e8cfc..87fc31c 100644 --- a/scselect.tproj/Makefile +++ b/scselect.tproj/Makefile @@ -29,7 +29,8 @@ DEBUG_LIBS = $(LIBS) PROF_LIBS = $(LIBS) -FRAMEWORKS = -framework SystemConfiguration +NEXTSTEP_PB_CFLAGS = -DUSE_SYSTEMCONFIGURATION_PUBLIC_APIS +FRAMEWORKS = -framework CoreFoundation -framework SystemConfiguration NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc diff --git a/scselect.tproj/PB.project b/scselect.tproj/PB.project index 5e4c7da..32e4349 100644 --- a/scselect.tproj/PB.project +++ b/scselect.tproj/PB.project @@ -1,7 +1,7 @@ { DYNAMIC_CODE_GEN = YES; FILESTABLE = { - FRAMEWORKS = (SystemConfiguration.framework); + FRAMEWORKS = (CoreFoundation.framework, SystemConfiguration.framework); H_FILES = (); OTHER_LINKED = (scselect.c); OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, m.template, h.template); @@ -13,6 +13,7 @@ LANGUAGE = English; MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; + NEXTSTEP_COMPILEROPTIONS = "-DUSE_SYSTEMCONFIGURATION_PUBLIC_APIS"; NEXTSTEP_INSTALLDIR = /usr/sbin; NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; diff --git a/scselect.tproj/scselect.c b/scselect.tproj/scselect.c index b889b4f..7abf11e 100644 --- a/scselect.tproj/scselect.c +++ b/scselect.tproj/scselect.c @@ -20,17 +20,29 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * January 1, 2001 Allan Nathanson + * - initial revision + */ + #include +#include +#include + -boolean_t apply = TRUE; +Boolean apply = TRUE; void usage(const char *command) { - SCDLog(LOG_ERR, CFSTR("usage: %s [-n] new-set-name"), command); + SCPrint(TRUE, stderr, CFSTR("usage: %s [-n] new-set-name\n"), command); return; } @@ -46,8 +58,7 @@ main(int argc, char **argv) CFStringRef newSet = NULL; /* set key */ CFStringRef newSetUDN = NULL; /* user defined name */ CFStringRef prefix; - SCPStatus status; - SCPSessionRef session; + SCPreferencesRef session; CFDictionaryRef sets; CFIndex nSets; void **setKeys; @@ -56,15 +67,14 @@ main(int argc, char **argv) /* process any arguments */ - SCDOptionSet(NULL, kSCDOptionUseSyslog, FALSE); - while ((opt = getopt(argc, argv, "dvn")) != -1) switch(opt) { case 'd': - SCDOptionSet(NULL, kSCDOptionDebug, TRUE); + _sc_debug = TRUE; + _sc_log = FALSE; /* enable framework logging */ break; case 'v': - SCDOptionSet(NULL, kSCDOptionVerbose, TRUE); + _sc_verbose = TRUE; break; case 'n': apply = FALSE; @@ -82,11 +92,9 @@ main(int argc, char **argv) ? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman) : CFSTR(""); - status = SCPOpen(&session, CFSTR("Select Set Command"), NULL, 0); - if (status != SCP_OK) { - SCDLog(LOG_ERR, - CFSTR("SCPOpen() failed: %s"), - SCPError(status)); + session = SCPreferencesCreate(NULL, CFSTR("Select Set Command"), NULL); + if (!session) { + SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n")); exit (1); } @@ -100,7 +108,7 @@ main(int argc, char **argv) range = CFStringFind(str, CFSTR("/"), 0); if (range.location != kCFNotFound) { - SCDLog(LOG_ERR, CFSTR("Set \"%@\" not available."), newSet); + SCPrint(TRUE, stderr, CFSTR("Set \"%@\" not available\n."), newSet); exit (1); } @@ -108,32 +116,26 @@ main(int argc, char **argv) newSet = str; } - status = SCPGet(session, kSCPrefSets, (CFPropertyListRef *)&sets); - if (status != SCP_OK) { - SCDLog(LOG_ERR, CFSTR("SCDGet(...,%s,...) failed: %s"), SCPError(status)); + sets = SCPreferencesGetValue(session, kSCPrefSets); + if (!sets) { + SCPrint(TRUE, stderr, CFSTR("SCPreferencesGetValue(...,%s,...) failed\n")); exit (1); } - status = SCPGet(session, kSCPrefCurrentSet, (CFPropertyListRef *)¤t); - switch (status) { - case SCP_OK : - if (CFStringHasPrefix(current, prefix)) { - CFMutableStringRef tmp; - - tmp = CFStringCreateMutableCopy(NULL, 0, current); - CFStringDelete(tmp, CFRangeMake(0, CFStringGetLength(prefix))); - current = tmp; - } else { - currentMatched = -1; /* not prefixed */ - } - break; - case SCP_NOKEY : - current = CFSTR(""); - currentMatched = -2; /* not defined */ - break; - default : - SCDLog(LOG_ERR, CFSTR("SCDGet(...,%s,...) failed: %s"), SCPError(status)); - exit (1); + current = SCPreferencesGetValue(session, kSCPrefCurrentSet); + if (current) { + if (CFStringHasPrefix(current, prefix)) { + CFMutableStringRef tmp; + + tmp = CFStringCreateMutableCopy(NULL, 0, current); + CFStringDelete(tmp, CFRangeMake(0, CFStringGetLength(prefix))); + current = tmp; + } else { + currentMatched = -1; /* not prefixed */ + } + } else { + current = CFSTR(""); + currentMatched = -2; /* not defined */ } nSets = CFDictionaryGetCount(sets); @@ -174,23 +176,23 @@ main(int argc, char **argv) } if (argc == 2) { - SCDLog(LOG_ERR, CFSTR("Set \"%@\" not available."), newSet); + SCPrint(TRUE, stderr, CFSTR("Set \"%@\" not available.\n"), newSet); } else { usage(command); } - SCDLog(LOG_ERR, CFSTR("")); - SCDLog(LOG_ERR, - CFSTR("Defined sets include:%s"), - (currentMatched > 0) ? " (* == current set)" : ""); + SCPrint(TRUE, stderr, CFSTR("\n")); + SCPrint(TRUE, stderr, + CFSTR("Defined sets include:%s\n"), + (currentMatched > 0) ? " (* == current set)" : ""); for (i=0; i 0) && CFEqual(key, current)) ? "*" : " ", key, udn ? udn : CFSTR("")); @@ -198,16 +200,13 @@ main(int argc, char **argv) switch (currentMatched) { case -2 : - SCDLog(LOG_ERR, CFSTR("")); - SCDLog(LOG_ERR, CFSTR("CurrentSet not defined")); + SCPrint(TRUE, stderr, CFSTR("\nCurrentSet not defined.\n")); break; case -1 : - SCDLog(LOG_ERR, CFSTR("")); - SCDLog(LOG_ERR, CFSTR("CurrentSet \"%@\" may not be valid"), current); + SCPrint(TRUE, stderr, CFSTR("\nCurrentSet \"%@\" may not be valid\n"), current); break; case 0 : - SCDLog(LOG_ERR, CFSTR("")); - SCDLog(LOG_ERR, CFSTR("CurrentSet \"%@\" not valid"), current); + SCPrint(TRUE, stderr, CFSTR("\nCurrentSet \"%@\" not valid\n"), current); break; default : break; @@ -217,38 +216,30 @@ main(int argc, char **argv) found : - status = SCPSet(session, kSCPrefCurrentSet, current); - if (status != SCP_OK) { - SCDLog(LOG_ERR, - CFSTR("SCDSet(...,%@,%@) failed: %s"), + if (!SCPreferencesSetValue(session, kSCPrefCurrentSet, current)) { + SCPrint(TRUE, stderr, + CFSTR("SCPreferencesSetValue(...,%@,%@) failed\n"), kSCPrefCurrentSet, - current, - SCPError(status)); + current); exit (1); } - status = SCPCommit(session); - if (status != SCP_OK) { - SCDLog(LOG_ERR, CFSTR("SCPCommit() failed: %s"), SCPError(status)); + if (!SCPreferencesCommitChanges(session)) { + SCPrint(TRUE, stderr, CFSTR("SCPreferencesCommitChanges() failed\n")); exit (1); } if (apply) { - status = SCPApply(session); - if (status != SCP_OK) { - SCDLog(LOG_ERR, CFSTR("SCPApply() failed: %s"), SCPError(status)); + if (!SCPreferencesApplyChanges(session)) { + SCPrint(TRUE, stderr, CFSTR("SCPreferencesApplyChanges() failed\n")); exit (1); } } - status = SCPClose(&session); - if (status != SCP_OK) { - SCDLog(LOG_ERR, CFSTR("SCPClose() failed: %s"), SCPError(status)); - exit (1); - } + CFRelease(session); - SCDLog(LOG_NOTICE, - CFSTR("%@ updated to %@ (%@)"), + SCPrint(TRUE, stdout, + CFSTR("%@ updated to %@ (%@)\n"), kSCPrefCurrentSet, newSet, newSetUDN ? newSetUDN : CFSTR("")); diff --git a/scutil.tproj/Makefile b/scutil.tproj/Makefile index c23c5f1..4daf58e 100644 --- a/scutil.tproj/Makefile +++ b/scutil.tproj/Makefile @@ -13,13 +13,13 @@ PROJECTVERSION = 2.8 PROJECT_TYPE = Tool HFILES = scutil.h commands.h dictionary.h session.h cache.h notify.h\ - tests.h + tests.h CFILES = scutil.c commands.c dictionary.c session.c cache.c notify.c\ - tests.c + tests.c OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\ - h.template + h.template MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles @@ -28,12 +28,13 @@ MAKEFILE = tool.make NEXTSTEP_INSTALLDIR = /usr/sbin WINDOWS_INSTALLDIR = /Library/Executables PDO_UNIX_INSTALLDIR = /bin -LIBS = +LIBS = DEBUG_LIBS = $(LIBS) PROF_LIBS = $(LIBS) -FRAMEWORKS = -framework SystemConfiguration +NEXTSTEP_PB_CFLAGS = -DUSE_SYSTEMCONFIGURATION_PUBLIC_APIS +FRAMEWORKS = -framework CoreFoundation -framework SystemConfiguration NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc diff --git a/scutil.tproj/PB.project b/scutil.tproj/PB.project index c1ceca4..e506062 100644 --- a/scutil.tproj/PB.project +++ b/scutil.tproj/PB.project @@ -1,28 +1,32 @@ { - DYNAMIC_CODE_GEN = YES; + DYNAMIC_CODE_GEN = YES; FILESTABLE = { - FRAMEWORKS = (SystemConfiguration.framework); - FRAMEWORKSEARCH = (); - H_FILES = (scutil.h, commands.h, dictionary.h, session.h, cache.h, notify.h, tests.h); - OTHER_LINKED = (scutil.c, commands.c, dictionary.c, session.c, cache.c, notify.c, tests.c); - OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, m.template, h.template); - SUBPROJECTS = (); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; - NEXTSTEP_INSTALLDIR = /usr/sbin; - NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; - NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; - PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; - PDO_UNIX_INSTALLDIR = /bin; - PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; - PROJECTNAME = scutil; - PROJECTTYPE = Tool; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_INSTALLDIR = /Library/Executables; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; + FRAMEWORKS = (CoreFoundation.framework, SystemConfiguration.framework); + FRAMEWORKSEARCH = (); + H_FILES = (scutil.h, commands.h, dictionary.h, session.h, cache.h, notify.h, tests.h); + OTHER_LINKED = (scutil.c, commands.c, dictionary.c, session.c, cache.c, notify.c, tests.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, m.template, h.template); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; + NEXTSTEP_COMPILEROPTIONS = "-DUSE_SYSTEMCONFIGURATION_PUBLIC_APIS"; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_INSTALLDIR = /bin; + PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = scutil; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_INSTALLDIR = /Library/Executables; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; } diff --git a/scutil.tproj/cache.c b/scutil.tproj/cache.c index 759959b..3739acb 100644 --- a/scutil.tproj/cache.c +++ b/scutil.tproj/cache.c @@ -20,43 +20,69 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #include #include "scutil.h" + +static CFComparisonResult +sort_keys(const void *p1, const void *p2, void *context) { + CFStringRef key1 = (CFStringRef)p1; + CFStringRef key2 = (CFStringRef)p2; + return CFStringCompare(key1, key2, 0); +} + + void do_list(int argc, char **argv) { - CFStringRef key; - int regexOptions = 0; - SCDStatus status; + int i; + CFStringRef pattern; CFArrayRef list; CFIndex listCnt; - int i; + CFMutableArrayRef sortedList; - key = CFStringCreateWithCString(NULL, - (argc >= 1) ? argv[0] : "", - kCFStringEncodingMacRoman); + pattern = CFStringCreateWithCString(NULL, + (argc >= 1) ? argv[0] : ".*", + kCFStringEncodingMacRoman); - if (argc == 2) - regexOptions = kSCDRegexKey; - - status = SCDList(session, key, regexOptions, &list); - CFRelease(key); - if (status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDList: %s"), SCDError(status)); + list = SCDynamicStoreCopyKeyList(store, pattern); + CFRelease(pattern); + if (!list) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); return; } listCnt = CFArrayGetCount(list); + sortedList = CFArrayCreateMutableCopy(NULL, listCnt, list); + CFRelease(list); + CFArraySortValues(sortedList, + CFRangeMake(0, listCnt), + sort_keys, + NULL); + if (listCnt > 0) { for (i=0; i + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _CACHE_H #define _CACHE_H @@ -27,12 +37,14 @@ __BEGIN_DECLS -void do_list __P((int argc, char **argv)); -void do_add __P((int argc, char **argv)); -void do_get __P((int argc, char **argv)); -void do_set __P((int argc, char **argv)); -void do_remove __P((int argc, char **argv)); -void do_touch __P((int argc, char **argv)); +void do_list (int argc, char **argv); +void do_add (int argc, char **argv); +void do_get (int argc, char **argv); +void do_set (int argc, char **argv); +void do_show (int argc, char **argv); +void do_remove (int argc, char **argv); +void do_notify (int argc, char **argv); +void do_touch (int argc, char **argv); __END_DECLS diff --git a/scutil.tproj/commands.c b/scutil.tproj/commands.c index 501b23f..482341b 100644 --- a/scutil.tproj/commands.c +++ b/scutil.tproj/commands.c @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #include #include #include @@ -32,103 +42,110 @@ #include "notify.h" #include "tests.h" -#include "SCDPrivate.h" +#include + const cmdInfo commands[] = { - /* cmd minArgs maxArgs func */ - /* usage */ + /* cmd minArgs maxArgs func group ctype */ + /* usage */ - { "help", 0, 0, do_help, 0, - " help : list available commands" }, + { "help", 0, 0, do_help, 0, 0, + " help : list available commands" }, - { "f.read", 1, 1, do_readFile, 0, - " f.read file : process commands from file" }, + { "f.read", 1, 1, do_readFile, 0, 0, + " f.read file : process commands from file" }, /* local dictionary manipulation commands */ - { "d.init", 0, 0, do_dictInit, 1, - " d.init : initialize (empty) dictionary" }, + { "d.init", 0, 0, do_dictInit, 1, 0, + " d.init : initialize (empty) dictionary" }, - { "d.show", 0, 0, do_dictShow, 1, - " d.show : show dictionary contents" }, + { "d.show", 0, 0, do_dictShow, 1, 0, + " d.show : show dictionary contents" }, - { "d.add", 2, 101, do_dictSetKey, 1, - " d.add key [*#?] val [v2 ...] : add information to dictionary\n" + { "d.add", 2, 101, do_dictSetKey, 1, 0, + " d.add key [*#?] val [v2 ...] : add information to dictionary\n" " (*=array, #=number, ?=boolean)" }, - { "d.remove", 1, 1, do_dictRemoveKey, 1, - " d.remove key : remove key from dictionary" }, + { "d.remove", 1, 1, do_dictRemoveKey, 1, 0, + " d.remove key : remove key from dictionary" }, /* data store manipulation commands */ - { "open", 0, 0, do_open, 2, - " open : open a session with \"configd\"" }, + { "open", 0, 0, do_open, 2, 0, + " open : open a session with \"configd\"" }, + + { "close", 0, 0, do_close, 2, 0, + " close : close current \"configd\" session" }, + + { "lock", 0, 0, do_lock, 3, 1, + " lock : secures write access to data store" }, - { "close", 0, 0, do_close, 2, - " close : close current \"configd\" session" }, + { "unlock", 0, 0, do_unlock, 3, 1, + " unlock : secures write access to data store" }, - { "lock", 0, 0, do_lock, 3, - " lock : secures write access to data store" }, + { "list", 0, 2, do_list, 4, 0, + " list [pattern] : list keys in data store" }, - { "unlock", 0, 0, do_unlock, 3, - " unlock : secures write access to data store" }, + { "add", 1, 2, do_add, 4, 0, + " add key [\"temporary\"] : add key in data store w/current dict" }, - { "list", 0, 2, do_list, 4, - " list [prefix] [regex] : list keys in data store" }, + { "get", 1, 1, do_get, 4, 0, + " get key : get dict from data store w/key" }, - { "add", 1, 2, do_add, 4, - " add key [session] : add key in data store w/current dict" }, + { "set", 1, 1, do_set, 4, 0, + " set key : set key in data store w/current dict" }, - { "get", 1, 1, do_get, 4, - " get key : get dict from data store w/key" }, + { "show", 1, 1, do_show, 4, 1, + " show key : show dict in data store w/key" }, - { "set", 1, 1, do_set, 4, - " set key : set key in data store w/current dict" }, + { "remove", 1, 1, do_remove, 4, 0, + " remove key : remove key from data store" }, - { "remove", 1, 1, do_remove, 4, - " remove key : remove key from data store" }, + { "notify", 1, 1, do_notify, 4, 0, + " notify key : notify key in data store" }, - { "touch", 1, 1, do_touch, 4, - " touch key : touch key in data store" }, + { "touch", 1, 1, do_touch, 4, 1, + " touch key : touch key in data store" }, - { "n.list", 0, 1, do_notify_list, 5, - " n.list [regex] : list notification keys" }, + { "n.list", 0, 1, do_notify_list, 5, 0, + " n.list [\"pattern\"] : list notification keys" }, - { "n.add", 1, 2, do_notify_add, 5, - " n.add key [regex] : add notification key" }, + { "n.add", 1, 2, do_notify_add, 5, 0, + " n.add key [\"pattern\"] : add notification key" }, - { "n.remove", 1, 2, do_notify_remove, 5, - " n.remove key [regex] : remove notification key" }, + { "n.remove", 1, 2, do_notify_remove, 5, 0, + " n.remove key [\"pattern\"] : remove notification key" }, - { "n.changes", 0, 0, do_notify_changes, 5, - " n.changes : list changed keys" }, + { "n.changes", 0, 0, do_notify_changes, 5, 0, + " n.changes : list changed keys" }, - { "n.wait", 0, 0, do_notify_wait, 5, - " n.wait : wait for changes" }, + { "n.watch", 0, 1, do_notify_watch, 5, 0, + " n.watch [verbose] : watch for changes" }, - { "n.watch", 0, 1, do_notify_callback, 5, - " n.watch [verbose] : watch for changes" }, + { "n.wait", 0, 0, do_notify_wait, 5, 2, + " n.wait : wait for changes" }, - { "n.signal", 1, 2, do_notify_signal, 5, - " n.signal sig [pid] : signal changes" }, + { "n.callback", 0, 1, do_notify_callback, 5, 2, + " n.callback [\"verbose\"] : watch for changes" }, - { "n.file", 0, 1, do_notify_file, 5, - " n.file [identifier] : watch for changes via file" }, + { "n.signal", 1, 2, do_notify_signal, 5, 2, + " n.signal sig [pid] : signal changes" }, - { "n.cancel", 0, 1, do_notify_cancel, 5, - " n.cancel : cancel notification requests" }, + { "n.file", 0, 1, do_notify_file, 5, 2, + " n.file [identifier] : watch for changes via file" }, - { "snapshot", 0, 0, do_snapshot, 9, - " snapshot : save snapshot of cache and session data" }, + { "n.cancel", 0, 1, do_notify_cancel, 5, 0, + " n.cancel : cancel notification requests" }, -#ifdef DEBUG - { "t.ocleak", 0, 1, test_openCloseLeak, 9, - " t.ocleak [#] : test for leaks (open/close)" }, -#endif /* DEBUG */ + { "snapshot", 0, 0, do_snapshot, 9, 2, + " snapshot : save snapshot of store and session data" }, }; const int nCommands = (sizeof(commands)/sizeof(cmdInfo)); +Boolean enablePrivateAPI = FALSE; + void do_command(int argc, char **argv) @@ -137,14 +154,18 @@ do_command(int argc, char **argv) char *cmd = argv[0]; for (i=0; i 1) && !enablePrivateAPI) { + continue; /* if "private" API and access has not been enabled */ + } + if (strcasecmp(cmd, commands[i].cmd) == 0) { --argc; argv++; if (argc < commands[i].minArgs) { - SCDLog(LOG_INFO, CFSTR("%s: too few arguments"), cmd); + SCPrint(TRUE, stdout, CFSTR("%s: too few arguments\n"), cmd); return; } else if (argc > commands[i].maxArgs) { - SCDLog(LOG_INFO, CFSTR("%s: too many arguments"), cmd); + SCPrint(TRUE, stdout, CFSTR("%s: too many arguments\n"), cmd); return; } commands[i].func(argc, argv); @@ -152,7 +173,7 @@ do_command(int argc, char **argv) } } - SCDLog(LOG_INFO, CFSTR("%s: unknown, type \"help\" for command info"), cmd); + SCPrint(TRUE, stdout, CFSTR("%s: unknown, type \"help\" for command info\n"), cmd); return; } @@ -163,16 +184,22 @@ do_help(int argc, char **argv) int g = -1; /* current group */ int i; - SCDLog(LOG_NOTICE, CFSTR("")); - SCDLog(LOG_NOTICE, CFSTR("Available commands:")); + SCPrint(TRUE, stdout, CFSTR("\nAvailable commands:\n")); for (i=0; i 0) && !enablePrivateAPI) { + continue; /* if "private" API and access has not been enabled */ + } + + /* check if this is a new command group */ if (g != commands[i].group) { - SCDLog(LOG_NOTICE, CFSTR("")); + SCPrint(TRUE, stdout, CFSTR("\n")); g = commands[i].group; } - SCDLog(LOG_NOTICE, CFSTR("%s"), commands[i].usage); + + /* display the command */ + SCPrint(TRUE, stdout, CFSTR("%s\n"), commands[i].usage); } - SCDLog(LOG_NOTICE, CFSTR("")); + SCPrint(TRUE, stdout, CFSTR("\n")); return; } @@ -181,62 +208,52 @@ do_help(int argc, char **argv) void do_readFile(int argc, char **argv) { - FILE *fp = fopen(argv[0], "r"); - boolean_t ok; + CFSocketContext context; + FILE *fp = fopen(argv[0], "r"); + CFSocketRef in; + CFRunLoopSourceRef rls; if (fp == NULL) { - SCDLog(LOG_INFO, CFSTR("f.read: could not open file (%s)."), strerror(errno)); + SCPrint(TRUE, stdout, CFSTR("f.read: could not open file (%s).\n"), strerror(errno)); return; } /* open file, increase nesting level */ - SCDLog(LOG_DEBUG, CFSTR("f.read: reading file (%s)."), argv[0]); + SCPrint(TRUE, stdout, CFSTR("f.read: reading file (%s).\n"), argv[0]); nesting++; - if (SCDOptionGet(NULL, kSCDOptionUseCFRunLoop)) { - CFSocketRef in; - CFSocketContext context = { 0, fp, NULL, NULL, NULL }; - CFRunLoopSourceRef rls; - - /* create a "socket" reference with the file descriptor associated with stdin */ - in = CFSocketCreateWithNative(NULL, - fileno(fp), - kCFSocketReadCallBack, - runLoopProcessInput, - &context); - - /* Create and add a run loop source for the file descriptor */ - rls = CFSocketCreateRunLoopSource(NULL, in, nesting); - - /* - * Remove the current input file from the run loop sources. We - * will reactivate the current input file source when we are - * finished reading data from the new file. - */ - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), - (CFRunLoopSourceRef) CFArrayGetValueAtIndex(sources, 0), - kCFRunLoopDefaultMode); - - /* keep track of this new source */ - CFArrayInsertValueAtIndex(sources, 0, rls); - - /* add this source to the run loop */ - CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); - - CFRelease(rls); - CFRelease(in); - } else { - do { - /* debug information, diagnostics */ - _showMachPortStatus(); - - /* process command */ - ok = process_line(fp); - } while (ok); - - /* decrement the nesting level */ - nesting--; - } + /* create a "socket" reference with the file descriptor associated with stdin */ + context.version = 0; + context.info = fp; + context.retain = NULL; + context.release = NULL; + context.copyDescription = NULL; + in = CFSocketCreateWithNative(NULL, + fileno(fp), + kCFSocketReadCallBack, + runLoopProcessInput, + &context); + + /* Create and add a run loop source for the file descriptor */ + rls = CFSocketCreateRunLoopSource(NULL, in, nesting); + + /* + * Remove the current input file from the run loop sources. We + * will reactivate the current input file source when we are + * finished reading data from the new file. + */ + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), + (CFRunLoopSourceRef) CFArrayGetValueAtIndex(sources, 0), + kCFRunLoopDefaultMode); + + /* keep track of this new source */ + CFArrayInsertValueAtIndex(sources, 0, rls); + + /* add this source to the run loop */ + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + + CFRelease(rls); + CFRelease(in); return; } diff --git a/scutil.tproj/commands.h b/scutil.tproj/commands.h index c36a766..00b7ecd 100644 --- a/scutil.tproj/commands.h +++ b/scutil.tproj/commands.h @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _COMMANDS_H #define _COMMANDS_H @@ -31,17 +41,19 @@ typedef struct { int maxArgs; void (*func)(); int group; + int ctype; /* 0==normal, 1==limited, 2==private */ char *usage; } cmdInfo; extern const cmdInfo commands[]; extern const int nCommands; +extern Boolean enablePrivateAPI; __BEGIN_DECLS -void do_command __P((int argc, char **argv)); -void do_help __P((int argc, char **argv)); -void do_readFile __P((int argc, char **argv)); +void do_command (int argc, char **argv); +void do_help (int argc, char **argv); +void do_readFile (int argc, char **argv); __END_DECLS diff --git a/scutil.tproj/dictionary.c b/scutil.tproj/dictionary.c index 35371d4..55f5660 100644 --- a/scutil.tproj/dictionary.c +++ b/scutil.tproj/dictionary.c @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #include "scutil.h" @@ -30,20 +40,15 @@ void do_dictInit(int argc, char **argv) { - CFMutableDictionaryRef dict; - - if (data != NULL) { - SCDHandleRelease(data); + if (value != NULL) { + CFRelease(value); } - data = SCDHandleInit(); - dict = CFDictionaryCreateMutable(NULL + value = CFDictionaryCreateMutable(NULL ,0 ,&kCFTypeDictionaryKeyCallBacks ,&kCFTypeDictionaryValueCallBacks ); - SCDHandleSetData(data, dict); - CFRelease(dict); return; } @@ -52,18 +57,12 @@ do_dictInit(int argc, char **argv) void do_dictShow(int argc, char **argv) { - int instance; - CFPropertyListRef store; - - if (data == NULL) { - SCDLog(LOG_INFO, CFSTR("d.show: dictionary must be initialized.")); + if (value == NULL) { + SCPrint(TRUE, stdout, CFSTR("d.show: dictionary must be initialized.\n")); return; } - instance = SCDHandleGetInstance(data); - store = SCDHandleGetData(data); - - SCDLog(LOG_NOTICE, CFSTR("dict (instance = %d) = \n\t%@"), instance, store); + SCPrint(TRUE, stdout, CFSTR("%@\n"), value); return; } @@ -72,25 +71,26 @@ do_dictShow(int argc, char **argv) void do_dictSetKey(int argc, char **argv) { - CFPropertyListRef store; - CFStringRef key; - CFPropertyListRef value = NULL; CFMutableArrayRef array = NULL; - boolean_t doArray = FALSE; - boolean_t doBoolean = FALSE; - boolean_t doNumeric = FALSE; + Boolean doArray = FALSE; + Boolean doBoolean = FALSE; + Boolean doNumeric = FALSE; + CFStringRef key; + CFTypeRef val; - if (data == NULL) { - SCDLog(LOG_INFO, CFSTR("d.add: dictionary must be initialized.")); + if (value == NULL) { + SCPrint(TRUE, stdout, CFSTR("d.add: dictionary must be initialized.\n")); return; } - store = SCDHandleGetData(data); - if (CFGetTypeID(store) != CFDictionaryGetTypeID()) { - SCDLog(LOG_INFO, CFSTR("d.add: data (fetched from configuration server) is not a dictionary")); + if (CFGetTypeID(value) != CFDictionaryGetTypeID()) { + SCPrint(TRUE, stdout, CFSTR("d.add: data (fetched from configuration server) is not a dictionary.\n")); return; } + val = CFDictionaryCreateMutableCopy(NULL, 0, value); + CFRelease(value); + value = val; key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); argv++; argc--; @@ -117,7 +117,7 @@ do_dictSetKey(int argc, char **argv) if (argc > 1) { doArray = TRUE; } else if (!doArray && (argc == 0)) { - SCDLog(LOG_INFO, CFSTR("d.add: no values")); + SCPrint(TRUE, stdout, CFSTR("d.add: no values.\n")); return; } @@ -132,15 +132,15 @@ do_dictSetKey(int argc, char **argv) (strcasecmp(argv[0], "yes" ) == 0) || (strcasecmp(argv[0], "y" ) == 0) || (strcmp (argv[0], "1" ) == 0)) { - value = CFRetain(kCFBooleanTrue); + val = CFRetain(kCFBooleanTrue); } else if ((strcasecmp(argv[0], "false") == 0) || (strcasecmp(argv[0], "f" ) == 0) || (strcasecmp(argv[0], "no" ) == 0) || (strcasecmp(argv[0], "n" ) == 0) || (strcmp (argv[0], "0" ) == 0)) { - value = CFRetain(kCFBooleanFalse); + val = CFRetain(kCFBooleanFalse); } else { - SCDLog(LOG_INFO, CFSTR("d.add: invalid data")); + SCPrint(TRUE, stdout, CFSTR("d.add: invalid data.\n")); if (doArray) { CFRelease(array); } @@ -150,31 +150,31 @@ do_dictSetKey(int argc, char **argv) int intValue; if (sscanf(argv[0], "%d", &intValue) == 1) { - value = CFNumberCreate(NULL, kCFNumberIntType, &intValue); + val = CFNumberCreate(NULL, kCFNumberIntType, &intValue); } else { - SCDLog(LOG_INFO, CFSTR("d.add: invalid data")); + SCPrint(TRUE, stdout, CFSTR("d.add: invalid data.\n")); if (doArray) { CFRelease(array); } return; } } else { - value = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); + val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); } if (doArray) { - CFArrayAppendValue(array, value); + CFArrayAppendValue(array, val); } argv++; argc--; } if (doArray) { - value = array; + val = array; } - CFDictionarySetValue((CFMutableDictionaryRef)store, key, value); - CFRelease(value); + CFDictionarySetValue((CFMutableDictionaryRef)value, key, val); + CFRelease(val); CFRelease(key); return; @@ -184,22 +184,26 @@ do_dictSetKey(int argc, char **argv) void do_dictRemoveKey(int argc, char **argv) { - CFPropertyListRef store; CFStringRef key; + CFMutableDictionaryRef val; - if (data == NULL) { - SCDLog(LOG_INFO, CFSTR("d.remove: dictionary must be initialized.")); + if (value == NULL) { + SCPrint(TRUE, stdout, CFSTR("d.remove: dictionary must be initialized.\n")); return; } - store = SCDHandleGetData(data); - if (CFGetTypeID(store) == CFDictionaryGetTypeID()) { - key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); - CFDictionaryRemoveValue((CFMutableDictionaryRef)store, key); - CFRelease(key); - } else { - SCDLog(LOG_INFO, CFSTR("d.add: data (fetched from configuration server) is not a dictionary")); + if (CFGetTypeID(value) != CFDictionaryGetTypeID()) { + SCPrint(TRUE, stdout, CFSTR("d.remove: data (fetched from configuration server) is not a dictionary.\n")); + return; } + val = CFDictionaryCreateMutableCopy(NULL, 0, value); + CFRelease(value); + value = val; + + key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); + CFDictionaryRemoveValue((CFMutableDictionaryRef)value, key); + CFRelease(key); + return; } diff --git a/scutil.tproj/dictionary.h b/scutil.tproj/dictionary.h index 8ea9cfe..0a521a0 100644 --- a/scutil.tproj/dictionary.h +++ b/scutil.tproj/dictionary.h @@ -20,6 +20,13 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _DICTIONARY_H #define _DICTIONARY_H @@ -27,10 +34,10 @@ __BEGIN_DECLS -void do_dictInit __P((int argc, char **argv)); -void do_dictShow __P((int argc, char **argv)); -void do_dictSetKey __P((int argc, char **argv)); -void do_dictRemoveKey __P((int argc, char **argv)); +void do_dictInit (int argc, char **argv); +void do_dictShow (int argc, char **argv); +void do_dictSetKey (int argc, char **argv); +void do_dictRemoveKey (int argc, char **argv); __END_DECLS diff --git a/scutil.tproj/notify.c b/scutil.tproj/notify.c index b19df55..6629a6b 100644 --- a/scutil.tproj/notify.c +++ b/scutil.tproj/notify.c @@ -20,6 +20,16 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #include #include #include @@ -27,36 +37,85 @@ #include "scutil.h" -static int osig; -static struct sigaction *oact = NULL; +#include +#include "v1Compatibility.h" + + +static int osig; +static struct sigaction *oact = NULL; + + +static CFComparisonResult +sort_keys(const void *p1, const void *p2, void *context) { + CFStringRef key1 = (CFStringRef)p1; + CFStringRef key2 = (CFStringRef)p2; + return CFStringCompare(key1, key2, 0); +} + void -do_notify_list(int argc, char **argv) +storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) { - int regexOptions = 0; - SCDStatus status; - CFArrayRef list; - CFIndex listCnt; int i; + CFIndex n; + + SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store); + + n = CFArrayGetCount(changedKeys); + if (n > 0) { + for (i=0; i 0) { for (i=0; i 0) { for (i=0; i= NSIG)) { - printf("signal must be in the range of 1 .. %d\n", NSIG-1); + SCPrint(TRUE, stdout, CFSTR("signal must be in the range of 1 .. %d.\n"), NSIG-1); return; } } else { @@ -291,13 +352,22 @@ do_notify_signal(int argc, char **argv) break; } if (sig >= NSIG) { - printf("Signal must be one of the following:"); + CFMutableStringRef str; + + SCPrint(TRUE, stdout, CFSTR("Signal must be one of the following:\n")); + + str = CFStringCreateMutable(NULL, 0); for (sig=1; sig + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _NOTIFY_H #define _NOTIFY_H @@ -27,15 +37,20 @@ __BEGIN_DECLS -void do_notify_list __P((int argc, char **argv)); -void do_notify_add __P((int argc, char **argv)); -void do_notify_remove __P((int argc, char **argv)); -void do_notify_changes __P((int argc, char **argv)); -void do_notify_wait __P((int argc, char **argv)); -void do_notify_callback __P((int argc, char **argv)); -void do_notify_signal __P((int argc, char **argv)); -void do_notify_file __P((int argc, char **argv)); -void do_notify_cancel __P((int argc, char **argv)); +void storeCallback (SCDynamicStoreRef store, + CFArrayRef changedKeys, + void *info); + +void do_notify_list (int argc, char **argv); +void do_notify_add (int argc, char **argv); +void do_notify_remove (int argc, char **argv); +void do_notify_changes (int argc, char **argv); +void do_notify_watch (int argc, char **argv); +void do_notify_wait (int argc, char **argv); +void do_notify_callback (int argc, char **argv); +void do_notify_signal (int argc, char **argv); +void do_notify_file (int argc, char **argv); +void do_notify_cancel (int argc, char **argv); __END_DECLS diff --git a/scutil.tproj/scutil.c b/scutil.tproj/scutil.c index b46c128..fc844b4 100644 --- a/scutil.tproj/scutil.c +++ b/scutil.tproj/scutil.c @@ -20,6 +20,21 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * July 9, 2001 Allan Nathanson + * - added "-r" option for checking network reachability + * - added "-w" option to check/wait for the presence of a + * dynamic store key. + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #include #include #include @@ -33,16 +48,22 @@ #endif /* DEBUG */ #include "scutil.h" -#include "SCDPrivate.h" #include "commands.h" #include "dictionary.h" +#include "tests.h" + +#include +#include "SCDynamicStoreInternal.h" + #define LINE_LENGTH 256 -SCDSessionRef session = NULL; -SCDHandleRef data = NULL; -int nesting = 0; -CFMutableArrayRef sources = NULL; + +int nesting = 0; +CFRunLoopSourceRef notifyRls = NULL; +CFMutableArrayRef sources = NULL; +SCDynamicStoreRef store = NULL; +CFPropertyListRef value = NULL; static char * @@ -119,7 +140,7 @@ getString(char **line) } -boolean_t +Boolean process_line(FILE *fp) { char line[LINE_LENGTH], *s, *arg, **argv = NULL; @@ -129,8 +150,8 @@ process_line(FILE *fp) if (getLine(line, sizeof(line), fp) == NULL) return FALSE; - if ((nesting > 0) && SCDOptionGet(NULL, kSCDOptionVerbose)) { - SCDLog(LOG_NOTICE, CFSTR("%d> %s"), nesting, line); + if (nesting > 0) { + SCPrint(TRUE, stdout, CFSTR("%d> %s"), nesting, line); } /* if requested, exit */ @@ -196,97 +217,126 @@ runLoopProcessInput(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, nesting--; } - if (SCDOptionGet(NULL, kSCDOptionUseCFRunLoop)) { - /* debug information, diagnostics */ - _showMachPortStatus(); + /* debug information, diagnostics */ + __showMachPortStatus(); - /* if necessary, re-issue prompt */ - if ((CFArrayGetCount(sources) == 1) && isatty(STDIN_FILENO)) { - printf("> "); - fflush(stdout); - } + /* if necessary, re-issue prompt */ + if ((CFArrayGetCount(sources) == 1) && isatty(STDIN_FILENO)) { + printf("> "); + fflush(stdout); } return; } +void +usage(const char *command) +{ + SCPrint(TRUE, stderr, CFSTR("usage: %s\n"), command); + SCPrint(TRUE, stderr, CFSTR(" or: %s -r node-or-address\n"), command); + SCPrint(TRUE, stderr, CFSTR("\t-r\tcheck reachability of node/address\n")); + SCPrint(TRUE, stderr, CFSTR(" or: %s -w dynamic-store-key [ -t timeout ]\n"), command); + SCPrint(TRUE, stderr, CFSTR("\t-w\twait for presense of dynamic store key\n")); + SCPrint(TRUE, stderr, CFSTR("\t-t\ttime to wait for key\n")); + SCPrint(TRUE, stderr, CFSTR("\n")); + SCPrint(TRUE, stderr, CFSTR("Note: you may only specify one of \"-r\" or \"-w\".\n")); + exit (EX_USAGE); +} + + int main(int argc, const char *argv[]) { - extern int optind; - int opt; - boolean_t ok; + CFSocketContext context = { 0, stdin, NULL, NULL, NULL }; + char *dest = NULL; + CFSocketRef in; + extern int optind; + int opt; + const char *prog = argv[0]; + CFRunLoopSourceRef rls; + int timeout = 15; /* default timeout (in seconds) */ + char *wait = NULL; /* process any arguments */ - SCDOptionSet(NULL, kSCDOptionUseCFRunLoop, FALSE); - - while ((opt = getopt(argc, argv, "dvr")) != -1) + while ((opt = getopt(argc, argv, "dvpr:t:w:")) != -1) switch(opt) { case 'd': - SCDOptionSet(NULL, kSCDOptionDebug, TRUE); + _sc_debug = TRUE; + _sc_log = FALSE; /* enable framework logging */ break; case 'v': - SCDOptionSet(NULL, kSCDOptionVerbose, TRUE); + _sc_verbose = TRUE; + _sc_log = FALSE; /* enable framework logging */ + break; + case 'p': + enablePrivateAPI = TRUE; break; case 'r': - SCDOptionSet(NULL, kSCDOptionUseCFRunLoop, TRUE); + dest = optarg; + break; + case 't': + timeout = atoi(optarg); + break; + case 'w': + wait = optarg; break; case '?': default : - do_help(0, NULL); + usage(prog); } argc -= optind; argv += optind; + if (dest && wait) { + usage(prog); + } + + /* are we checking the reachability of a host/address */ + if (dest) { + do_checkReachability(dest); + /* NOT REACHED */ + } + + /* are we waiting on the presense of a dynamic store key */ + if (wait) { + do_wait(wait, timeout); + /* NOT REACHED */ + } + /* start with an empty dictionary */ do_dictInit(0, NULL); - if (SCDOptionGet(NULL, kSCDOptionUseCFRunLoop)) { - CFSocketRef in; - CFSocketContext context = { 0, stdin, NULL, NULL, NULL }; - CFRunLoopSourceRef rls; + /* create a "socket" reference with the file descriptor associated with stdin */ + in = CFSocketCreateWithNative(NULL, + STDIN_FILENO, + kCFSocketReadCallBack, + runLoopProcessInput, + &context); - /* create a "socket" reference with the file descriptor associated with stdin */ - in = CFSocketCreateWithNative(NULL, - STDIN_FILENO, - kCFSocketReadCallBack, - runLoopProcessInput, - &context); + /* Create a run loop source for the (stdin) file descriptor */ + rls = CFSocketCreateRunLoopSource(NULL, in, nesting); - /* Create a run loop source for the (stdin) file descriptor */ - rls = CFSocketCreateRunLoopSource(NULL, in, nesting); + /* keep track of input file sources */ + sources = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(sources, rls); - /* keep track of input file sources */ - sources = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(sources, rls); + /* add this source to the run loop */ + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + CFRelease(rls); + CFRelease(in); - /* add this source to the run loop */ - CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + /* show (initial) debug information, diagnostics */ + __showMachPortStatus(); - CFRelease(rls); - CFRelease(in); + /* issue (initial) prompt */ + if (isatty(STDIN_FILENO)) { + printf("> "); + fflush(stdout); } - do { - /* debug information, diagnostics */ - _showMachPortStatus(); - - /* issue prompt */ - if (isatty(STDIN_FILENO)) { - printf("> "); - fflush(stdout); - } - - if (SCDOptionGet(NULL, kSCDOptionUseCFRunLoop)) { - CFRunLoopRun(); /* process input, process events */ - ok = FALSE; /* if the RunLoop exited */ - } else { - /* process command */ - ok = process_line(stdin); - } - } while (ok); + CFRunLoopRun(); /* process input, process events */ exit (EX_OK); // insure the process exit status is 0 return 0; // ...and make main fit the ANSI spec. diff --git a/scutil.tproj/scutil.h b/scutil.tproj/scutil.h index b1d13dd..ebeae2e 100644 --- a/scutil.tproj/scutil.h +++ b/scutil.tproj/scutil.h @@ -20,27 +20,41 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _SC_H #define _SC_H #include -#include +#include +#include + -extern SCDSessionRef session; -extern SCDHandleRef data; extern int nesting; +extern CFRunLoopSourceRef notifyRls; extern CFMutableArrayRef sources; +extern SCDynamicStoreRef store; +extern CFPropertyListRef value; + __BEGIN_DECLS -boolean_t process_line __P((FILE *fp)); +Boolean process_line (FILE *fp); -void runLoopProcessInput __P((CFSocketRef s, - CFSocketCallBackType type, - CFDataRef address, - const void *data, - void *info)); +void runLoopProcessInput (CFSocketRef s, + CFSocketCallBackType type, + CFDataRef address, + const void *data, + void *info); __END_DECLS diff --git a/scutil.tproj/session.c b/scutil.tproj/session.c index 7a8287e..82a6f43 100644 --- a/scutil.tproj/session.c +++ b/scutil.tproj/session.c @@ -20,32 +20,27 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #include "scutil.h" +#include "notify.h" void do_open(int argc, char **argv) { - SCDStatus status; + if (store) CFRelease(store); - if (session != NULL) { - status = SCDClose(&session); - switch (status) { - case SCD_OK : - case SCD_NOSESSION : - /* - * if the "close" was successful or if we had an open - * session but can no talk to the server - */ - break; - default : - SCDLog(LOG_INFO, CFSTR("SCDClose: %s"), SCDError(status)); - return; - } - } - - status = SCDOpen(&session, CFSTR("sc")); - if (status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDOpen: %s"), SCDError(status)); + store = SCDynamicStoreCreate(NULL, CFSTR("scutil"), storeCallback, NULL); + if (!store) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); return; } @@ -56,11 +51,15 @@ do_open(int argc, char **argv) void do_close(int argc, char **argv) { - SCDStatus status; + if (notifyRls) { + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifyRls, kCFRunLoopDefaultMode); + CFRelease(notifyRls); + notifyRls = NULL; + } - status = SCDClose(&session); - if (status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDClose: %s"), SCDError(status)); + if (store) { + CFRelease(store); + store = NULL; } return; } @@ -69,11 +68,8 @@ do_close(int argc, char **argv) void do_lock(int argc, char **argv) { - SCDStatus status; - - status = SCDLock(session); - if (status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDLock: %s"), SCDError(status)); + if (!SCDynamicStoreLock(store)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); } return; } @@ -82,11 +78,8 @@ do_lock(int argc, char **argv) void do_unlock(int argc, char **argv) { - SCDStatus status; - - status = SCDUnlock(session); - if (status != SCD_OK) { - SCDLog(LOG_INFO, CFSTR("SCDUnlock: %s"), SCDError(status)); + if (!SCDynamicStoreUnlock(store)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); } return; } diff --git a/scutil.tproj/session.h b/scutil.tproj/session.h index 8a3f8bb..211ddb7 100644 --- a/scutil.tproj/session.h +++ b/scutil.tproj/session.h @@ -20,6 +20,13 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _SESSION_H #define _SESSION_H @@ -27,10 +34,10 @@ __BEGIN_DECLS -void do_open __P((int argc, char **argv)); -void do_close __P((int argc, char **argv)); -void do_lock __P((int argc, char **argv)); -void do_unlock __P((int argc, char **argv)); +void do_open (int argc, char **argv); +void do_close (int argc, char **argv); +void do_lock (int argc, char **argv); +void do_unlock (int argc, char **argv); __END_DECLS diff --git a/scutil.tproj/tests.c b/scutil.tproj/tests.c index 703ef5f..e6d9ed0 100644 --- a/scutil.tproj/tests.c +++ b/scutil.tproj/tests.c @@ -20,68 +20,173 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * July 9, 2001 Allan Nathanson + * - added "-r" option for checking network reachability + * - added "-w" option to check/wait for the presence of a + * dynamic store key. + * + * June 1, 2001 Allan Nathanson + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #include "scutil.h" -#include "SCDPrivate.h" + +#include +#include +#include +#include + void -do_snapshot(int argc, char **argv) +do_checkReachability(char *node) { - SCDStatus status; + SCNetworkConnectionFlags flags = 0; + Boolean ok = FALSE; + + if (isdigit(node[0])) { + struct sockaddr_in sin; + + bzero(&sin, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr(node); + if (inet_aton(node, &sin.sin_addr) == 0) { + SCPrint(TRUE, stderr, CFSTR("Could not interpret address \"%s\"\n"), node); + exit(1); + } + ok = SCNetworkCheckReachabilityByAddress((struct sockaddr *)&sin, + sizeof(sin), + &flags); + + } else { + ok = SCNetworkCheckReachabilityByName(node, + &flags); + } + + if (!ok) { + SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError())); + exit(1); + } + + SCPrint(_sc_debug, stdout, CFSTR("flags = 0x%x"), flags); + if (flags != 0) { + SCPrint(_sc_debug, stdout, CFSTR(" (")); + if (flags & kSCNetworkFlagsReachable) { + SCPrint(TRUE, stdout, CFSTR("Reachable")); + flags &= ~kSCNetworkFlagsReachable; + SCPrint(flags != 0, stdout, CFSTR(",")); + } + if (flags & kSCNetworkFlagsTransientConnection) { + SCPrint(TRUE, stdout, CFSTR("Transient Connection")); + flags &= ~kSCNetworkFlagsTransientConnection; + SCPrint(flags != 0, stdout, CFSTR(",")); + } + if (flags & kSCNetworkFlagsConnectionRequired) { + SCPrint(TRUE, stdout, CFSTR("Connection Required")); + flags &= ~kSCNetworkFlagsConnectionRequired; + SCPrint(flags != 0, stdout, CFSTR(",")); + } + if (flags & kSCNetworkFlagsConnectionAutomatic) { + SCPrint(TRUE, stdout, CFSTR("Connection Automatic")); + flags &= ~kSCNetworkFlagsConnectionAutomatic; + SCPrint(flags != 0, stdout, CFSTR(",")); + } + if (flags & kSCNetworkFlagsInterventionRequired) { + SCPrint(TRUE, stdout, CFSTR("Intervention Required")); + flags &= ~kSCNetworkFlagsInterventionRequired; + SCPrint(flags != 0, stdout, CFSTR(",")); + } + SCPrint(_sc_debug, stdout, CFSTR(")")); + } else { + SCPrint(_sc_debug, stdout, CFSTR(" (")); + SCPrint(TRUE, stdout, CFSTR("Not Reachable")); + SCPrint(_sc_debug, stdout, CFSTR(")")); + } + SCPrint(TRUE, stdout, CFSTR("\n")); + exit(0); +} - status = SCDSnapshot(session); - if (status != SCD_OK) { - printf("SCDSnapshot: %s\n", SCDError(status)); + +void +do_snapshot(int argc, char **argv) +{ + if (!SCDynamicStoreSnapshot(store)) { + SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError())); } return; } -#ifdef DEBUG +static void +waitKeyFound() +{ + exit(0); +} + + +static void +waitTimeout(int sigraised) +{ + exit(1); +} + void -test_openCloseLeak(int argc, char **argv) +do_wait(char *waitKey, int timeout) { - SCDStatus status; - int i, loopCnt; - SCDSessionRef *sessions; + struct itimerval itv; + CFStringRef key; + CFMutableArrayRef keys; - if ((argc == 0) || (sscanf(argv[0], "%d", &loopCnt) != 1)) { - loopCnt = 100; + store = SCDynamicStoreCreate(NULL, CFSTR("scutil (wait)"), waitKeyFound, NULL); + if (!store) { + SCPrint(TRUE, stderr, + CFSTR("SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError())); + exit(1); } - sessions = malloc(loopCnt * sizeof(SCDSessionRef)); + keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + key = CFStringCreateWithCString(NULL, waitKey, kCFStringEncodingMacRoman); + CFArrayAppendValue(keys, key); - /* open, close, open, close, open, close, ... */ - for (i=0; i 0) { + signal(SIGALRM, waitTimeout); + bzero(&itv, sizeof(itv)); + itv.it_value.tv_sec = timeout; + if (setitimer(ITIMER_REAL, &itv, NULL) < 0) { + SCPrint(TRUE, stderr, + CFSTR("setitimer() failed: %s\n"), strerror(errno)); + exit(1); } } - return; + CFRunLoopRun(); } -#endif /* DEBUG */ diff --git a/scutil.tproj/tests.h b/scutil.tproj/tests.h index 38d9b9b..0d28080 100644 --- a/scutil.tproj/tests.h +++ b/scutil.tproj/tests.h @@ -20,6 +20,18 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * Modification History + * + * July 9, 2001 Allan Nathanson + * - added "-r" option for checking network reachability + * - added "-w" option to check/wait for the presence of a + * dynamic store key. + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + #ifndef _TESTS_H #define _TESTS_H @@ -27,12 +39,9 @@ __BEGIN_DECLS -void do_snapshot __P((int argc, char **argv)); - -#ifdef DEBUG -void test_setServer __P((int argc, char **argv)); -void test_openCloseLeak __P((int argc, char **argv)); -#endif /* DEBUG */ +void do_checkReachability (char *node); +void do_snapshot (int argc, char **argv); +void do_wait (char *waitKey, int timeout); __END_DECLS -- 2.47.2