From 009ee3c6fe2929a4c90ae5c9eb1925573e17956b Mon Sep 17 00:00:00 2001 From: Apple Date: Fri, 24 Oct 2003 22:46:25 +0000 Subject: [PATCH] configd-84.tar.gz --- Makefile.postamble | 7 +- PB.project | 39 +- SystemConfiguration.fproj/CustomInfo.plist | 2 +- SystemConfiguration.fproj/DHCP.c | 34 +- .../DHCPClientPreferences.h | 29 +- SystemConfiguration.fproj/DeviceOnHold.c | 66 +- SystemConfiguration.fproj/DeviceOnHold.h | 29 +- SystemConfiguration.fproj/LinkConfiguration.c | 126 +- SystemConfiguration.fproj/LinkConfiguration.h | 29 +- SystemConfiguration.fproj/Makefile | 37 +- SystemConfiguration.fproj/Makefile.postamble | 13 +- SystemConfiguration.fproj/Makefile.preamble | 17 +- SystemConfiguration.fproj/PB.project | 286 +- SystemConfiguration.fproj/SCD.c | 209 +- SystemConfiguration.fproj/SCD.h | 36 - SystemConfiguration.fproj/SCDAdd.c | 47 +- SystemConfiguration.fproj/SCDAddSession.c | 47 +- SystemConfiguration.fproj/SCDConsoleUser.c | 164 +- SystemConfiguration.fproj/SCDConsoleUser.h | 37 - SystemConfiguration.fproj/SCDGet.c | 63 +- SystemConfiguration.fproj/SCDHostName.c | 75 +- SystemConfiguration.fproj/SCDHostName.h | 38 - SystemConfiguration.fproj/SCDKeys.c | 29 +- SystemConfiguration.fproj/SCDKeys.h | 37 - SystemConfiguration.fproj/SCDList.c | 45 +- SystemConfiguration.fproj/SCDLock.c | 29 +- SystemConfiguration.fproj/SCDNotifierAdd.c | 64 +- SystemConfiguration.fproj/SCDNotifierCancel.c | 35 +- .../SCDNotifierGetChanges.c | 33 +- .../SCDNotifierInformViaCallback.c | 86 +- .../SCDNotifierInformViaFD.c | 29 +- .../SCDNotifierInformViaMachPort.c | 29 +- .../SCDNotifierInformViaSignal.c | 29 +- SystemConfiguration.fproj/SCDNotifierList.c | 63 - SystemConfiguration.fproj/SCDNotifierRemove.c | 65 +- .../SCDNotifierSetKeys.c | 192 +- SystemConfiguration.fproj/SCDNotifierWait.c | 29 +- SystemConfiguration.fproj/SCDNotify.c | 51 +- SystemConfiguration.fproj/SCDOpen.c | 213 +- SystemConfiguration.fproj/SCDPlugin.c | 100 +- SystemConfiguration.fproj/SCDPlugin.h | 123 +- SystemConfiguration.fproj/SCDPrivate.c | 376 ++- SystemConfiguration.fproj/SCDRemove.c | 43 +- SystemConfiguration.fproj/SCDSet.c | 76 +- SystemConfiguration.fproj/SCDSnapshot.c | 29 +- SystemConfiguration.fproj/SCDTouch.c | 43 +- SystemConfiguration.fproj/SCDUnlock.c | 29 +- SystemConfiguration.fproj/SCDynamicStore.h | 29 +- .../SCDynamicStoreCopyDHCPInfo.h | 29 +- .../SCDynamicStoreCopySpecific.h | 37 +- .../SCDynamicStoreCopySpecificPrivate.h | 75 + .../SCDynamicStoreInternal.h | 45 +- SystemConfiguration.fproj/SCDynamicStoreKey.h | 29 +- .../SCDynamicStorePrivate.h | 35 +- .../SCDynamicStoreSetSpecificPrivate.h | 64 +- SystemConfiguration.fproj/SCLocation.c | 29 +- SystemConfiguration.fproj/SCNetwork.c | 1429 +-------- SystemConfiguration.fproj/SCNetwork.h | 107 +- .../SCNetworkConnection.c | 1201 ++++++++ .../SCNetworkConnection.h | 477 +++ .../SCNetworkReachability.c | 2580 +++++++++++++++++ .../SCNetworkReachability.h | 214 ++ SystemConfiguration.fproj/SCP.c | 98 +- SystemConfiguration.fproj/SCP.h | 37 - SystemConfiguration.fproj/SCPAdd.c | 39 +- SystemConfiguration.fproj/SCPApply.c | 29 +- SystemConfiguration.fproj/SCPCommit.c | 106 +- SystemConfiguration.fproj/SCPGet.c | 37 +- SystemConfiguration.fproj/SCPList.c | 33 +- SystemConfiguration.fproj/SCPLock.c | 38 +- SystemConfiguration.fproj/SCPOpen.c | 167 +- SystemConfiguration.fproj/SCPPath.c | 79 +- SystemConfiguration.fproj/SCPPath.h | 37 - SystemConfiguration.fproj/SCPRemove.c | 37 +- SystemConfiguration.fproj/SCPSet.c | 39 +- SystemConfiguration.fproj/SCPUnlock.c | 29 +- SystemConfiguration.fproj/SCPreferences.h | 42 +- .../SCPreferencesInternal.h | 44 +- SystemConfiguration.fproj/SCPreferencesPath.h | 34 +- .../SCPreferencesPrivate.h | 67 +- .../SCPreferencesSetSpecific.h | 29 +- SystemConfiguration.fproj/SCPrivate.h | 154 +- SystemConfiguration.fproj/SCProxies.c | 33 +- SystemConfiguration.fproj/SCValidation.h | 29 +- .../SystemConfiguration.h | 37 +- SystemConfiguration.fproj/config.defs | 41 +- SystemConfiguration.fproj/config_types.h | 33 +- SystemConfiguration.fproj/dy_framework.c | 86 +- SystemConfiguration.fproj/dy_framework.h | 56 +- SystemConfiguration.fproj/genSCPreferences.c | 378 ++- SystemConfiguration.fproj/moh.c | 38 +- SystemConfiguration.fproj/moh.h | 33 +- SystemConfiguration.fproj/moh_msg.h | 51 +- SystemConfiguration.fproj/ppp.c | 481 +-- SystemConfiguration.fproj/ppp.h | 117 +- SystemConfiguration.fproj/ppp_msg.h | 243 -- SystemConfiguration.fproj/v1Compatibility.c | 816 ------ SystemConfiguration.fproj/v1Compatibility.h | 378 --- configd.tproj/Makefile | 17 +- configd.tproj/Makefile.postamble | 5 + configd.tproj/Makefile.preamble | 3 +- configd.tproj/PB.project | 6 +- configd.tproj/_SCD.c | 351 +-- configd.tproj/_SCD.h | 120 +- configd.tproj/_configadd.c | 79 +- configd.tproj/_configadd_s.c | 67 +- configd.tproj/_configclose.c | 134 +- configd.tproj/_configget.c | 187 +- configd.tproj/_configlist.c | 172 +- configd.tproj/_configlock.c | 50 +- configd.tproj/_confignotify.c | 81 +- configd.tproj/_configopen.c | 59 +- configd.tproj/_configremove.c | 71 +- configd.tproj/_configset.c | 233 +- configd.tproj/_configtouch.c | 103 +- configd.tproj/_configunlock.c | 187 +- configd.tproj/_notifyadd.c | 400 ++- configd.tproj/_notifycancel.c | 44 +- configd.tproj/_notifychanges.c | 44 +- configd.tproj/_notifyremove.c | 168 +- configd.tproj/_notifyviafd.c | 46 +- configd.tproj/_notifyviaport.c | 48 +- configd.tproj/_notifyviasignal.c | 51 +- configd.tproj/_snapshot.c | 139 +- configd.tproj/config.defs | 24 + configd.tproj/configd.h | 33 +- configd.tproj/configd.m | 295 +- configd.tproj/configd.plist | 12 + configd.tproj/configd_server.c | 419 ++- configd.tproj/configd_server.h | 47 +- configd.tproj/notify.c | 56 +- configd.tproj/notify.h | 29 +- configd.tproj/notify_server.c | 78 +- configd.tproj/notify_server.h | 29 +- configd.tproj/pattern.c | 470 +++ configd.tproj/pattern.h | 61 + configd.tproj/plugin_support.c | 58 +- configd.tproj/plugin_support.h | 29 +- configd.tproj/session.c | 74 +- configd.tproj/session.h | 29 +- preferences.xml | 15 +- scselect.tproj/Makefile.postamble | 1 + scselect.tproj/scselect.c | 59 +- scutil.tproj/Makefile | 5 +- scutil.tproj/Makefile.postamble | 1 + scutil.tproj/PB.project | 67 +- scutil.tproj/cache.c | 48 +- scutil.tproj/cache.h | 29 +- scutil.tproj/commands.c | 93 +- scutil.tproj/commands.h | 29 +- scutil.tproj/dictionary.c | 30 +- scutil.tproj/dictionary.h | 29 +- scutil.tproj/notify.c | 156 +- scutil.tproj/notify.h | 29 +- scutil.tproj/prefs.c | 289 ++ scutil.tproj/prefs.h | 46 + scutil.tproj/scutil.c | 283 +- scutil.tproj/scutil.h | 51 +- scutil.tproj/session.c | 50 +- scutil.tproj/session.h | 29 +- scutil.tproj/tests.c | 106 +- scutil.tproj/tests.h | 33 +- 162 files changed, 12204 insertions(+), 7594 deletions(-) delete mode 100644 SystemConfiguration.fproj/SCD.h delete mode 100644 SystemConfiguration.fproj/SCDConsoleUser.h delete mode 100644 SystemConfiguration.fproj/SCDHostName.h delete mode 100644 SystemConfiguration.fproj/SCDKeys.h delete mode 100644 SystemConfiguration.fproj/SCDNotifierList.c create mode 100644 SystemConfiguration.fproj/SCDynamicStoreCopySpecificPrivate.h create mode 100644 SystemConfiguration.fproj/SCNetworkConnection.c create mode 100644 SystemConfiguration.fproj/SCNetworkConnection.h create mode 100644 SystemConfiguration.fproj/SCNetworkReachability.c create mode 100644 SystemConfiguration.fproj/SCNetworkReachability.h delete mode 100644 SystemConfiguration.fproj/SCP.h delete mode 100644 SystemConfiguration.fproj/SCPPath.h delete mode 100644 SystemConfiguration.fproj/ppp_msg.h delete mode 100644 SystemConfiguration.fproj/v1Compatibility.c delete mode 100644 SystemConfiguration.fproj/v1Compatibility.h create mode 100644 configd.tproj/configd.plist create mode 100644 configd.tproj/pattern.c create mode 100644 configd.tproj/pattern.h create mode 100644 scutil.tproj/prefs.c create mode 100644 scutil.tproj/prefs.h diff --git a/Makefile.postamble b/Makefile.postamble index 05b58f4..8198896 100644 --- a/Makefile.postamble +++ b/Makefile.postamble @@ -98,7 +98,8 @@ # owned by the top-level Makefile API and no context has been set up for where # derived files should go. # -SYSCONFIG_PREFS_DIR = /private/var/db/SystemConfiguration +PREFS_DIR = /Library/Preferences/SystemConfiguration install_extra: - $(MKDIRS) $(DSTROOT)$(SYSCONFIG_PREFS_DIR) - install -c -m 644 preferences.xml $(DSTROOT)$(SYSCONFIG_PREFS_DIR)/preferences.xml + $(MKDIRS) $(DSTROOT)$(PREFS_DIR) + $(CHMOD) 755 $(DSTROOT)$(PREFS_DIR) + install -c -m 644 preferences.xml $(DSTROOT)$(PREFS_DIR)/preferences.plist diff --git a/PB.project b/PB.project index 1be2515..2890710 100644 --- a/PB.project +++ b/PB.project @@ -1,25 +1,30 @@ { - DYNAMIC_CODE_GEN = YES; + "DYNAMIC_CODE_GEN" = YES; FILESTABLE = { - H_FILES = (); - OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, preferences.xml); - PRECOMPILED_HEADERS = (); - PROJECT_HEADERS = (); - PUBLIC_HEADERS = (); - SUBPROJECTS = (SystemConfiguration.fproj, configd.tproj, scselect.tproj, scutil.tproj); + "H_FILES" = (); + "OTHER_SOURCES" = ("Makefile.preamble", Makefile, "Makefile.postamble", "preferences.xml"); + "PRECOMPILED_HEADERS" = (); + "PROJECT_HEADERS" = (); + "PUBLIC_HEADERS" = (); + SUBPROJECTS = ( + "SystemConfiguration.fproj", + "configd.tproj", + "scselect.tproj", + "scutil.tproj" + ); }; LANGUAGE = English; MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - 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; - PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + "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"; + "PDO_UNIX_JAVA_COMPILER" = "$(JDKBINDIR)/javac"; + "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc"; PROJECTNAME = configd; PROJECTTYPE = Aggregate; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; + PROJECTVERSION = "2.8"; + "WINDOWS_BUILDTOOL" = "$NEXT_ROOT/Developer/Executables/make"; + "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe"; + "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc"; } diff --git a/SystemConfiguration.fproj/CustomInfo.plist b/SystemConfiguration.fproj/CustomInfo.plist index 3150982..e71549b 100644 --- a/SystemConfiguration.fproj/CustomInfo.plist +++ b/SystemConfiguration.fproj/CustomInfo.plist @@ -1,5 +1,5 @@ { CFBundleName = "SystemConfiguration"; CFBundleIdentifier = "com.apple.SystemConfiguration"; - CFBundleShortVersionString = "1.3.0"; + CFBundleShortVersionString = "1.4.0"; } diff --git a/SystemConfiguration.fproj/DHCP.c b/SystemConfiguration.fproj/DHCP.c index f4b7a24..778f9ff 100644 --- a/SystemConfiguration.fproj/DHCP.c +++ b/SystemConfiguration.fproj/DHCP.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2001-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -77,8 +80,9 @@ static void my_CFArrayAppendUniqueValue(CFMutableArrayRef arr, CFTypeRef new) { int i; + int n = CFArrayGetCount(arr); - for (i = 0; i < CFArrayGetCount(arr); i++) { + for (i = 0; i < n; i++) { CFStringRef element = CFArrayGetValueAtIndex(arr, i); if (CFEqual(element, new)) { return; diff --git a/SystemConfiguration.fproj/DHCPClientPreferences.h b/SystemConfiguration.fproj/DHCPClientPreferences.h index 725f4d3..aa30111 100644 --- a/SystemConfiguration.fproj/DHCPClientPreferences.h +++ b/SystemConfiguration.fproj/DHCPClientPreferences.h @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/DeviceOnHold.c b/SystemConfiguration.fproj/DeviceOnHold.c index fbeea30..48c93b1 100644 --- a/SystemConfiguration.fproj/DeviceOnHold.c +++ b/SystemConfiguration.fproj/DeviceOnHold.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -46,7 +49,7 @@ #include "DeviceOnHold.h" -#define kIODeviceSupportsHoldKey "DeviceSupportsHold" +#define kIODeviceSupportsHoldKey "V92Modem" typedef struct { @@ -111,7 +114,6 @@ static const CFRuntimeClass __DeviceOnHoldClass = { static pthread_once_t initialized = PTHREAD_ONCE_INIT; - static void __DeviceOnHoldInitialize(void) { @@ -120,11 +122,11 @@ __DeviceOnHoldInitialize(void) } -DeviceOnHoldRef +static DeviceOnHoldPrivateRef __DeviceOnHoldCreatePrivate(CFAllocatorRef allocator) { - DeviceOnHoldPrivateRef devicePrivate; - UInt32 size; + DeviceOnHoldPrivateRef devicePrivate; + uint32_t size; /* initialize runtime */ pthread_once(&initialized, __DeviceOnHoldInitialize); @@ -142,7 +144,14 @@ __DeviceOnHoldCreatePrivate(CFAllocatorRef allocator) devicePrivate->name = NULL; devicePrivate->sock = -1; - return (DeviceOnHoldRef)devicePrivate; + return devicePrivate; +} + + +CFTypeID +DeviceOnHoldGetTypeID(void) { + pthread_once(&initialized, __DeviceOnHoldInitialize); /* initialize runtime */ + return __kDeviceOnHoldTypeID; } @@ -158,7 +167,7 @@ IsDeviceOnHoldSupported(CFStringRef deviceName, // "modem" CFDictionaryRef options) { CFMutableDictionaryRef deviceToMatch; - u_int32_t deviceSupportsHoldValue; + uint32_t deviceSupportsHoldValue; kern_return_t kr; mach_port_t masterPort; io_iterator_t matchingServices; @@ -183,7 +192,7 @@ IsDeviceOnHoldSupported(CFStringRef deviceName, // "modem" goto errorExit; } - for ( ; service = IOIteratorNext(matchingServices) ; IOObjectRelease(service)) { + for ( ; (service = IOIteratorNext(matchingServices)) ; IOObjectRelease(service)) { io_string_t path; kr = IORegistryEntryGetPath(service, kIOServicePlane, path); @@ -225,7 +234,6 @@ DeviceOnHoldCreate(CFAllocatorRef allocator, CFStringRef deviceName, // "modem" CFDictionaryRef options) { - DeviceOnHoldRef device = NULL; DeviceOnHoldPrivateRef devicePrivate; int status; @@ -233,22 +241,20 @@ DeviceOnHoldCreate(CFAllocatorRef allocator, return NULL; } - device = __DeviceOnHoldCreatePrivate(allocator); - if (!device) { + devicePrivate = __DeviceOnHoldCreatePrivate(allocator); + if (!devicePrivate) { return NULL; } - devicePrivate = (DeviceOnHoldPrivateRef)device; - status = MOHInit(&devicePrivate->sock, deviceName); if (status != 0) { - CFRelease(device); + CFRelease(devicePrivate); return NULL; } - devicePrivate->name = CFRetain(deviceName); + devicePrivate->name = CFStringCreateCopy(NULL, deviceName); - return device; + return (DeviceOnHoldRef)devicePrivate; } diff --git a/SystemConfiguration.fproj/DeviceOnHold.h b/SystemConfiguration.fproj/DeviceOnHold.h index effb404..7d9d1ce 100644 --- a/SystemConfiguration.fproj/DeviceOnHold.h +++ b/SystemConfiguration.fproj/DeviceOnHold.h @@ -2,21 +2,24 @@ * Copyright (c) 2002 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/LinkConfiguration.c b/SystemConfiguration.fproj/LinkConfiguration.c index 159b4e0..8ea15fa 100644 --- a/SystemConfiguration.fproj/LinkConfiguration.c +++ b/SystemConfiguration.fproj/LinkConfiguration.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -46,48 +49,19 @@ #include "dy_framework.h" -static struct ifmedia_description ifm_subtype_shared_descriptions[] = +static const struct ifmedia_description ifm_subtype_shared_descriptions[] = IFM_SUBTYPE_SHARED_DESCRIPTIONS; -static struct ifmedia_description ifm_subtype_ethernet_descriptions[] = +static const struct ifmedia_description ifm_subtype_ethernet_descriptions[] = IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; -static struct ifmedia_description ifm_shared_option_descriptions[] = +static const struct ifmedia_description ifm_shared_option_descriptions[] = IFM_SHARED_OPTION_DESCRIPTIONS; -static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = +static const struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; -static char * -cfstring_to_cstring(CFStringRef cfstr, char *buf, int bufLen) -{ - CFIndex len = CFStringGetLength(cfstr); - - if (!buf) { - bufLen = len + 1; - buf = CFAllocatorAllocate(NULL, bufLen, 0); - } - - if (len >= bufLen) { - len = bufLen - 1; - } - - (void)CFStringGetBytes(cfstr, - CFRangeMake(0, len), - kCFStringEncodingASCII, - 0, - FALSE, - buf, - bufLen, - NULL); - buf[len] = '\0'; - - return buf; -} - - - static CFDictionaryRef __createMediaDictionary(int media_options, Boolean filter) { @@ -112,7 +86,7 @@ __createMediaDictionary(int media_options, Boolean filter) /* subtype */ val = NULL; - for (i=0; !val && ifm_subtype_shared_descriptions[i].ifmt_string; i++) { + for (i = 0; !val && ifm_subtype_shared_descriptions[i].ifmt_string; i++) { if (IFM_SUBTYPE(media_options) == ifm_subtype_shared_descriptions[i].ifmt_word) { val = CFStringCreateWithCString(NULL, ifm_subtype_shared_descriptions[i].ifmt_string, @@ -121,7 +95,7 @@ __createMediaDictionary(int media_options, Boolean filter) } } - for (i=0; !val && ifm_subtype_ethernet_descriptions[i].ifmt_string; i++) { + for (i = 0; !val && ifm_subtype_ethernet_descriptions[i].ifmt_string; i++) { if (IFM_SUBTYPE(media_options) == ifm_subtype_ethernet_descriptions[i].ifmt_word) { val = CFStringCreateWithCString(NULL, ifm_subtype_ethernet_descriptions[i].ifmt_string, @@ -146,7 +120,7 @@ __createMediaDictionary(int media_options, Boolean filter) } val = NULL; - for (i=0; !val && ifm_shared_option_descriptions[i].ifmt_string; i++) { + for (i = 0; !val && ifm_shared_option_descriptions[i].ifmt_string; i++) { if (IFM_OPTIONS(media_options) & ifm_shared_option_descriptions[i].ifmt_word) { val = CFStringCreateWithCString(NULL, ifm_shared_option_descriptions[i].ifmt_string, @@ -156,7 +130,7 @@ __createMediaDictionary(int media_options, Boolean filter) } } - for (i=0; !val && ifm_subtype_ethernet_option_descriptions[i].ifmt_string; i++) { + for (i = 0; !val && ifm_subtype_ethernet_option_descriptions[i].ifmt_string; i++) { if (IFM_OPTIONS(media_options) & ifm_subtype_ethernet_option_descriptions[i].ifmt_word) { val = CFStringCreateWithCString(NULL, ifm_subtype_ethernet_option_descriptions[i].ifmt_string, @@ -185,6 +159,7 @@ __createMediaOptions(CFDictionaryRef media_options) CFIndex i; Boolean match; int ifm_new = IFM_ETHER; + CFIndex n; CFArrayRef options; char *str; CFStringRef val; @@ -196,13 +171,13 @@ __createMediaOptions(CFDictionaryRef media_options) return -1; } - str = cfstring_to_cstring(val, NULL, 0); - if (!str) { + str = _SC_cfstring_to_cstring(val, NULL, 0, kCFStringEncodingASCII); + if (str == NULL) { return -1; } match = FALSE; - for (i=0; !match && ifm_subtype_shared_descriptions[i].ifmt_string; i++) { + for (i = 0; !match && ifm_subtype_shared_descriptions[i].ifmt_string; i++) { if (strcasecmp(str, ifm_subtype_shared_descriptions[i].ifmt_string) == 0) { ifm_new |= ifm_subtype_shared_descriptions[i].ifmt_word; match = TRUE; @@ -210,7 +185,7 @@ __createMediaOptions(CFDictionaryRef media_options) } } - for (i=0; !match && ifm_subtype_ethernet_descriptions[i].ifmt_string; i++) { + for (i = 0; !match && ifm_subtype_ethernet_descriptions[i].ifmt_string; i++) { if (strcasecmp(str, ifm_subtype_ethernet_descriptions[i].ifmt_string) == 0) { ifm_new |= ifm_subtype_ethernet_descriptions[i].ifmt_word; match = TRUE; @@ -231,7 +206,8 @@ __createMediaOptions(CFDictionaryRef media_options) return -1; } - for (i=0; i $@ + SCSchemaDefinitions.h: $(OFILE_DIR)/genSCPreferences - $(CD) $(SFILE_DIR) && $(OFILE_DIR)/genSCPreferences header > $@ + $(CD) $(SFILE_DIR) && $(OFILE_DIR)/genSCPreferences header > $@ SCSchemaDefinitions.c: $(OFILE_DIR)/genSCPreferences - $(CD) $(SFILE_DIR) && $(OFILE_DIR)/genSCPreferences cfile > $@ + $(CD) $(SFILE_DIR) && $(OFILE_DIR)/genSCPreferences cfile > $@ genSCFiles: cc -o /tmp/genSCFiles genSCPreferences.c -framework CoreFoundation - /tmp/genSCFiles header > /tmp/SCSchemaDefinitions.h - /tmp/genSCFiles cfile > /tmp/SCSchemaDefinitions.c + /tmp/genSCFiles header > /tmp/SCSchemaDefinitions.h + /tmp/genSCFiles header-x > /tmp/SCSchemaDefinitions_10_1.h + /tmp/genSCFiles cfile > /tmp/SCSchemaDefinitions.c dhcp: DHCP.c cc -Wall -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 d541ec9..07d79b1 100644 --- a/SystemConfiguration.fproj/Makefile.preamble +++ b/SystemConfiguration.fproj/Makefile.preamble @@ -141,6 +141,7 @@ OTHER_PRIVATE_HEADERS += config.defs config.h OTHER_PRIVATE_HEADERS += SCPrivate.h OTHER_PRIVATE_HEADERS += SCDynamicStorePrivate.h +OTHER_PRIVATE_HEADERS += SCDynamicStoreCopySpecificPrivate.h OTHER_PRIVATE_HEADERS += SCDynamicStoreSetSpecificPrivate.h OTHER_PRIVATE_HEADERS += SCPreferencesPrivate.h OTHER_PRIVATE_HEADERS += SCValidation.h @@ -148,17 +149,6 @@ OTHER_PRIVATE_HEADERS += SCDPlugin.h OTHER_PRIVATE_HEADERS += DeviceOnHold.h OTHER_PRIVATE_HEADERS += LinkConfiguration.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 # @@ -167,7 +157,10 @@ OTHER_OFILES += configUser.o # Additional options to create generated headers, source BEFORE_INSTALLHDRS = before_installhdrs OTHER_SOURCEFILES += genSCPreferences.c -OTHER_GENERATED_SRCFILES += SCSchemaDefinitions.h SCSchemaDefinitions.c +OTHER_GENERATED_SRCFILES += SCSchemaDefinitions_10_1.h +OTHER_GENERATED_SRCFILES += SCSchemaDefinitions.h +OTHER_GENERATED_SRCFILES += SCSchemaDefinitions.c +OTHER_PUBLIC_HEADERS += SCSchemaDefinitions_10_1.h OTHER_PUBLIC_HEADERS += SCSchemaDefinitions.h OTHER_OFILES += SCSchemaDefinitions.o diff --git a/SystemConfiguration.fproj/PB.project b/SystemConfiguration.fproj/PB.project index 1d21bfb..63378a2 100644 --- a/SystemConfiguration.fproj/PB.project +++ b/SystemConfiguration.fproj/PB.project @@ -1,157 +1,161 @@ { - CURRENTLY_ACTIVE_VERSION = YES; - DEPLOY_WITH_VERSION_NAME = A; - DYNAMIC_CODE_GEN = YES; + "CURRENTLY_ACTIVE_VERSION" = YES; + "DEPLOY_WITH_VERSION_NAME" = A; + "DYNAMIC_CODE_GEN" = YES; FILESTABLE = { - FRAMEWORKS = (CoreFoundation.framework); + FRAMEWORKS = ("CoreFoundation.framework"); 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, - SCP.h, - SCPPath.h, - SCDConsoleUser.h, - SCDHostName.h, - DHCPClientPreferences.h, - SCDynamicStoreCopyDHCPInfo.h, - moh_msg.h, - moh.h, - DeviceOnHold.h, - LinkConfiguration.h, - dy_framework.h + HEADERSEARCH = ( + "$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders" ); - OTHER_LINKED = ( - SCD.c, - SCDKeys.c, - SCDPrivate.c, - SCDPlugin.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, - SCPLock.c, - SCPUnlock.c, - SCPList.c, - SCPGet.c, - SCPAdd.c, - SCPSet.c, - SCPRemove.c, - SCPCommit.c, - SCPApply.c, - SCPPath.c, - SCDConsoleUser.c, - SCDHostName.c, - SCLocation.c, - SCNetwork.c, - SCProxies.c, - ppp.c, - v1Compatibility.c, - DHCP.c, - moh.c, - DeviceOnHold.c, - LinkConfiguration.c, - dy_framework.c + "H_FILES" = ( + "SystemConfiguration.h", + "SCPrivate.h", + "SCDPlugin.h", + "config_types.h", + "SCDynamicStoreInternal.h", + "SCDynamicStore.h", + "SCDynamicStorePrivate.h", + "SCDynamicStoreKey.h", + "SCDynamicStoreCopySpecific.h", + "SCDynamicStoreCopySpecificPrivate.h", + "SCDynamicStoreSetSpecificPrivate.h", + "SCPreferencesInternal.h", + "SCPreferences.h", + "SCPreferencesPrivate.h", + "SCPreferencesPath.h", + "SCPreferencesSetSpecific.h", + "SCNetwork.h", + "SCNetworkConnection.h", + "SCNetworkReachability.h", + "SCValidation.h", + "ppp.h", + "DHCPClientPreferences.h", + "SCDynamicStoreCopyDHCPInfo.h", + "moh_msg.h", + "moh.h", + "DeviceOnHold.h", + "LinkConfiguration.h", + "dy_framework.h" ); - OTHER_SOURCES = ( - Makefile.preamble, + "OTHER_LIBS" = (); + "OTHER_LINKED" = ( + "SCD.c", + "SCDKeys.c", + "SCDPrivate.c", + "SCDPlugin.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", + "SCDNotifierAdd.c", + "SCDNotifierRemove.c", + "SCDNotifierGetChanges.c", + "SCDNotifierWait.c", + "SCDNotifierInformViaCallback.c", + "SCDNotifierInformViaMachPort.c", + "SCDNotifierInformViaFD.c", + "SCDNotifierInformViaSignal.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", + "SCLocation.c", + "SCNetwork.c", + "SCNetworkConnection.c", + "SCNetworkReachability.c", + "SCProxies.c", + "ppp.c", + "DHCP.c", + "moh.c", + "DeviceOnHold.c", + "LinkConfiguration.c", + "dy_framework.c" + ); + "OTHER_SOURCES" = ( + "Makefile.preamble", Makefile, - Makefile.postamble, - m.template, - h.template, - config.defs, - genSCPreferences.c, - CustomInfo.plist + "Makefile.postamble", + "m.template", + "h.template", + "config.defs", + "genSCPreferences.c", + "CustomInfo.plist" ); - PRECOMPILED_HEADERS = (); - PROJECT_HEADERS = ( - 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, - SystemConfiguration.h, - v1Compatibility.h + "PRECOMPILED_HEADERS" = (); + "PROJECT_HEADERS" = ( + "SystemConfiguration.h", + "SCPrivate.h", + "config_types.h", + "SCDynamicStoreInternal.h", + "SCDynamicStore.h", + "SCDynamicStorePrivate.h", + "SCDynamicStoreKey.h", + "SCDynamicStoreCopySpecific.h", + "SCDynamicStoreCopySpecificPrivate.h", + "SCDynamicStoreSetSpecificPrivate.h", + "SCPreferencesInternal.h", + "SCPreferences.h", + "SCPreferencesPrivate.h", + "SCPreferencesPath.h", + "SCPreferencesSetSpecific.h", + "SCNetwork.h", + "SCNetworkConnection.h", + "SCNetworkReachability.h", + "SCValidation.h" ); - PUBLIC_HEADERS = ( - SystemConfiguration.h, - SCDynamicStore.h, - SCDynamicStoreKey.h, - SCDynamicStoreCopySpecific.h, - SCPreferences.h, - SCPreferencesPath.h, - SCPreferencesSetSpecific.h, - SCNetwork.h, - DHCPClientPreferences.h, - SCDynamicStoreCopyDHCPInfo.h + "PUBLIC_HEADERS" = ( + "SystemConfiguration.h", + "SCDynamicStore.h", + "SCDynamicStoreKey.h", + "SCDynamicStoreCopySpecific.h", + "SCPreferences.h", + "SCPreferencesPath.h", + "SCPreferencesSetSpecific.h", + "SCNetwork.h", + "SCNetworkConnection.h", + "SCNetworkReachability.h", + "DHCPClientPreferences.h", + "SCDynamicStoreCopyDHCPInfo.h" ); SUBPROJECTS = (); }; LANGUAGE = English; MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; - 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; - PDO_UNIX_INSTALLDIR = /Library/Frameworks; - PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + "NEXTSTEP_BUILDTOOL" = "/usr/bin/gnumake"; + "NEXTSTEP_COMPILEROPTIONS" = "-fconstant-cfstrings -DBIND_8_COMPAT -DCHECK_IPV6_REACHABILITY"; + "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"; + "PDO_UNIX_INSTALLDIR" = "/Library/Frameworks"; + "PDO_UNIX_JAVA_COMPILER" = "$(JDKBINDIR)/javac"; + "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc"; PROJECTNAME = SystemConfiguration; PROJECTTYPE = Framework; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_INSTALLDIR = /Library/Frameworks; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; + PROJECTVERSION = "2.8"; + "WINDOWS_BUILDTOOL" = "$NEXT_ROOT/Developer/Executables/make"; + "WINDOWS_INSTALLDIR" = "/Library/Frameworks"; + "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe"; + "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc"; } diff --git a/SystemConfiguration.fproj/SCD.c b/SystemConfiguration.fproj/SCD.c index b476211..e58d4f9 100644 --- a/SystemConfiguration.fproj/SCD.c +++ b/SystemConfiguration.fproj/SCD.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -76,6 +79,8 @@ static const struct sc_errmsg { // from extern CFStringRef _CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc, CFStringRef (*copyDescFunc)(void *, CFDictionaryRef), CFDictionaryRef formatOptions, CFStringRef format, va_list arguments); +#define N_QUICK 32 + static CFStringRef _SCCopyDescription(void *info, CFDictionaryRef formatOptions) { @@ -106,7 +111,7 @@ _SCCopyDescription(void *info, CFDictionaryRef formatOptions) } if (type == CFDataGetTypeID()) { - const u_int8_t *data; + const uint8_t *data; CFIndex dataLen; CFIndex i; CFMutableStringRef str; @@ -168,7 +173,8 @@ _SCCopyDescription(void *info, CFDictionaryRef formatOptions) } if (type == CFArrayGetTypeID()) { - const void **elements; + const void * elements_q[32]; + const void ** elements = elements_q; CFIndex i; CFIndex nElements; CFMutableStringRef str; @@ -178,9 +184,10 @@ _SCCopyDescription(void *info, CFDictionaryRef formatOptions) nElements = CFArrayGetCount(info); if (nElements > 0) { - elements = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + if (nElements > (CFIndex)(sizeof(elements_q)/sizeof(CFTypeRef))) + elements = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); CFArrayGetValues(info, CFRangeMake(0, nElements), elements); - for (i=0; i {"), prefix1); nElements = CFDictionaryGetCount(info); if (nElements > 0) { - keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); - values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { + keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + } CFDictionaryGetKeysAndValues(info, keys, values); - 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); + __SCPrint((LOG_PRI(level) > LOG_NOTICE) ? stderr : stdout, + formatString, + formatArguments, + FALSE, // trace + TRUE); // add newline } - CFRelease(resultString); + va_end(formatArguments); + return; } @@ -391,27 +440,33 @@ SCLog(Boolean condition, int level, CFStringRef formatString, ...) void SCPrint(Boolean condition, FILE *stream, CFStringRef formatString, ...) { - va_list argList; - CFStringRef resultString; + va_list formatArguments; 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); + va_start(formatArguments, formatString); + __SCPrint(stream, formatString, formatArguments, FALSE, FALSE); + va_end(formatArguments); + + return; +} + + +void +SCTrace(Boolean condition, FILE *stream, CFStringRef formatString, ...) +{ + va_list formatArguments; + + if (!condition) { + return; + } + + va_start(formatArguments, formatString); + __SCPrint(stream, formatString, formatArguments, TRUE, FALSE); + va_end(formatArguments); - __SCPrint(stream, resultString); - CFRelease(resultString); return; } @@ -481,7 +536,7 @@ SCErrorString(int status) { int i; - for (i = 0; i < nSC_ERRMSGS; i++) { + for (i = 0; i < (int)nSC_ERRMSGS; i++) { if (sc_errmsgs[i].status == status) { return sc_errmsgs[i].message; } diff --git a/SystemConfiguration.fproj/SCD.h b/SystemConfiguration.fproj/SCD.h deleted file mode 100644 index 9a2ef16..0000000 --- a/SystemConfiguration.fproj/SCD.h +++ /dev/null @@ -1,36 +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 _SCD_H -#define _SCD_H - -#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 2c32812..b643c73 100644 --- a/SystemConfiguration.fproj/SCDAdd.c +++ b/SystemConfiguration.fproj/SCDAdd.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -43,7 +46,7 @@ SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; kern_return_t status; - CFDataRef xmlKey; /* serialized key */ + CFDataRef utfKey; /* serialized key */ xmlData_t myKeyRef; CFIndex myKeyLen; CFDataRef xmlData; /* serialized data */ @@ -52,9 +55,11 @@ SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR int newInstance; int sc_status; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value); + } if (!store) { /* sorry, you must provide a session */ @@ -69,14 +74,14 @@ SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR } /* serialize the key */ - if (!_SCSerialize(key, &xmlKey, (void **)&myKeyRef, &myKeyLen)) { + if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) { _SCErrorSet(kSCStatusFailed); return FALSE; } /* serialize the data */ if (!_SCSerialize(value, &xmlData, (void **)&myDataRef, &myDataLen)) { - CFRelease(xmlKey); + CFRelease(utfKey); _SCErrorSet(kSCStatusFailed); return FALSE; } @@ -91,7 +96,7 @@ SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR (int *)&sc_status); /* clean up */ - CFRelease(xmlKey); + CFRelease(utfKey); CFRelease(xmlData); if (status != KERN_SUCCESS) { diff --git a/SystemConfiguration.fproj/SCDAddSession.c b/SystemConfiguration.fproj/SCDAddSession.c index 897f67f..9a265fe 100644 --- a/SystemConfiguration.fproj/SCDAddSession.c +++ b/SystemConfiguration.fproj/SCDAddSession.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -43,7 +46,7 @@ SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFProp { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; kern_return_t status; - CFDataRef xmlKey; /* serialized key */ + CFDataRef utfKey; /* serialized key */ xmlData_t myKeyRef; CFIndex myKeyLen; CFDataRef xmlData; /* serialized data */ @@ -52,9 +55,11 @@ SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFProp int newInstance; int sc_status; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddTemporaryValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddTemporaryValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value); + } if (!store) { /* sorry, you must provide a session */ @@ -69,14 +74,14 @@ SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFProp } /* serialize the key */ - if (!_SCSerialize(key, &xmlKey, (void **)&myKeyRef, &myKeyLen)) { + if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) { _SCErrorSet(kSCStatusFailed); return FALSE; } /* serialize the data */ if (!_SCSerialize(value, &xmlData, (void **)&myDataRef, &myDataLen)) { - CFRelease(xmlKey); + CFRelease(utfKey); _SCErrorSet(kSCStatusFailed); return FALSE; } @@ -91,7 +96,7 @@ SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFProp (int *)&sc_status); /* clean up */ - CFRelease(xmlKey); + CFRelease(utfKey); CFRelease(xmlData); if (status != KERN_SUCCESS) { diff --git a/SystemConfiguration.fproj/SCDConsoleUser.c b/SystemConfiguration.fproj/SCDConsoleUser.c index 1eb518a..06c2858 100644 --- a/SystemConfiguration.fproj/SCDConsoleUser.c +++ b/SystemConfiguration.fproj/SCDConsoleUser.c @@ -1,28 +1,34 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT 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 1, 2003 Allan Nathanson + * - add console [session] information SPIs + * * June 1, 2001 Allan Nathanson * - public API conversion * @@ -34,6 +40,31 @@ #include #include + +#ifndef kSCPropUsersConsoleUserName +#define kSCPropUsersConsoleUserName CFSTR("Name") +#endif + +#ifndef kSCPropUsersConsoleUserUID +#define kSCPropUsersConsoleUserUID CFSTR("UID") +#endif + +#ifndef kSCPropUsersConsoleUserGID +#define kSCPropUsersConsoleUserGID CFSTR("GID") +#endif + +#ifndef kSCPropUsersConsoleSessionInfo +#define kSCPropUsersConsoleSessionInfo CFSTR("SessionInfo") +#endif + + +const CFStringRef kSCConsoleSessionID = CFSTR("kCGSSessionIDKey"); /* value is CFNumber */ +const CFStringRef kSCConsoleSessionUserName = CFSTR("kCGSSessionUserNameKey"); /* value is CFString */ +const CFStringRef kSCConsoleSessionUID = CFSTR("kCGSSessionUserIDKey"); /* value is CFNumber */ +const CFStringRef kSCConsoleSessionConsoleSet = CFSTR("kCGSSessionConsoleSetKey"); /* value is CFNumber */ +const CFStringRef kSCConsoleSessionOnConsole = CFSTR("kCGSSessionOnConsoleKey"); /* value is CFBoolean */ + + CFStringRef SCDynamicStoreKeyCreateConsoleUser(CFAllocatorRef allocator) { @@ -113,7 +144,112 @@ SCDynamicStoreCopyConsoleUser(SCDynamicStoreRef store, if (tempSession) CFRelease(store); if (dict) CFRelease(dict); return consoleUser; +} + + +CFArrayRef +SCDynamicStoreCopyConsoleInformation(SCDynamicStoreRef store) +{ + CFDictionaryRef dict = NULL; + CFArrayRef info = NULL; + CFStringRef key; + Boolean tempSession = FALSE; + + if (!store) { + store = SCDynamicStoreCreate(NULL, + CFSTR("SCDynamicStoreCopyConsoleUser"), + NULL, + NULL); + if (!store) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + return NULL; + } + tempSession = TRUE; + } + + key = SCDynamicStoreKeyCreateConsoleUser(NULL); + dict = SCDynamicStoreCopyValue(store, key); + CFRelease(key); + if (!isA_CFDictionary(dict)) { + _SCErrorSet(kSCStatusNoKey); + goto done; + } + info = CFDictionaryGetValue(dict, kSCPropUsersConsoleSessionInfo); + info = isA_CFArray(info); + if (!info) { + _SCErrorSet(kSCStatusNoKey); + goto done; + } + + CFRetain(info); + + done : + + if (tempSession) CFRelease(store); + if (dict) CFRelease(dict); + return info; +} + + +Boolean +SCDynamicStoreSetConsoleInformation(SCDynamicStoreRef store, + const char *user, + uid_t uid, + gid_t gid, + CFArrayRef sessions) +{ + CFStringRef consoleUser; + CFMutableDictionaryRef dict = NULL; + CFStringRef key = SCDynamicStoreKeyCreateConsoleUser(NULL); + CFNumberRef num; + Boolean ok = TRUE; + Boolean tempSession = FALSE; + + if (!store) { + store = SCDynamicStoreCreate(NULL, + CFSTR("SCDynamicStoreSetConsoleUser"), + NULL, + NULL); + if (!store) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + return FALSE; + } + tempSession = TRUE; + } + + if (user == NULL) { + ok = SCDynamicStoreRemoveValue(store, key); + goto done; + } + + dict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + consoleUser = CFStringCreateWithCString(NULL, user, kCFStringEncodingMacRoman); + CFDictionarySetValue(dict, kSCPropUsersConsoleUserName, consoleUser); + CFRelease(consoleUser); + + num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&uid); + CFDictionarySetValue(dict, kSCPropUsersConsoleUserUID, num); + CFRelease(num); + + num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&gid); + CFDictionarySetValue(dict, kSCPropUsersConsoleUserGID, num); + CFRelease(num); + + CFDictionarySetValue(dict, kSCPropUsersConsoleSessionInfo, sessions); + + ok = SCDynamicStoreSetValue(store, key, dict); + + done : + + if (dict) CFRelease(dict); + if (key) CFRelease(key); + if (tempSession) CFRelease(store); + return ok; } diff --git a/SystemConfiguration.fproj/SCDConsoleUser.h b/SystemConfiguration.fproj/SCDConsoleUser.h deleted file mode 100644 index ded9eb5..0000000 --- a/SystemConfiguration.fproj/SCDConsoleUser.h +++ /dev/null @@ -1,37 +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 _SCDCONSOLEUSER_H -#define _SCDCONSOLEUSER_H - -#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 299fd00..d691cd1 100644 --- a/SystemConfiguration.fproj/SCDGet.c +++ b/SystemConfiguration.fproj/SCDGet.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -55,11 +58,14 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, xmlDataOut_t xmlDictRef; /* dict (serialized) */ CFIndex xmlDictLen; CFDictionaryRef dict = NULL; /* dict (un-serialized) */ + CFDictionaryRef expDict = NULL; /* dict (un-serialized / expanded) */ int sc_status; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyMultiple:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" keys = %@"), keys); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" patterns = %@"), patterns); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyMultiple:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" keys = %@"), keys); + SCLog(TRUE, LOG_DEBUG, CFSTR(" patterns = %@"), patterns); + } if (!store) { /* sorry, you must provide a session */ @@ -123,14 +129,17 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, } /* un-serialize the dictionary */ - if (!_SCUnserialize((CFPropertyListRef *)&dict, xmlDictRef, xmlDictLen)) { + if (!_SCUnserialize((CFPropertyListRef *)&dict, NULL, xmlDictRef, xmlDictLen)) { _SCErrorSet(kSCStatusFailed); return NULL; } - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), dict); + expDict = _SCUnserializeMultiple(dict); + CFRelease(dict); + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), expDict); - return dict; + return expDict; } @@ -139,7 +148,7 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; kern_return_t status; - CFDataRef xmlKey; /* key (XML serialized) */ + CFDataRef utfKey; /* key (XML serialized) */ xmlData_t myKeyRef; /* key (serialized) */ CFIndex myKeyLen; xmlDataOut_t xmlDataRef; /* data (serialized) */ @@ -148,8 +157,10 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) int newInstance; int sc_status; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + } if (!store) { /* sorry, you must provide a session */ @@ -163,7 +174,7 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) } /* serialize the key */ - if (!_SCSerialize(key, &xmlKey, (void **)&myKeyRef, &myKeyLen)) { + if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) { _SCErrorSet(kSCStatusFailed); return NULL; } @@ -178,7 +189,7 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) (int *)&sc_status); /* clean up */ - CFRelease(xmlKey); + CFRelease(utfKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) @@ -200,7 +211,7 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) } /* un-serialize the data */ - if (!_SCUnserialize(&data, xmlDataRef, xmlDataLen)) { + if (!_SCUnserialize(&data, NULL, xmlDataRef, xmlDataLen)) { _SCErrorSet(kSCStatusFailed); return NULL; } diff --git a/SystemConfiguration.fproj/SCDHostName.c b/SystemConfiguration.fproj/SCDHostName.c index 23ec5d4..6d62ee4 100644 --- a/SystemConfiguration.fproj/SCDHostName.c +++ b/SystemConfiguration.fproj/SCDHostName.c @@ -2,21 +2,24 @@ * Copyright (c) 2000-2002 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -227,11 +230,13 @@ _SC_stringIsValidDNSName(const char *name) char next = *(scan + 1); if (prev == '.' || prev == '\0') { - if (isalpha(ch) == 0) { + if (isalnum(ch) == 0) { + /* a label must begin with a letter or digit */ return FALSE; } } else if (next == '\0' || next == '.') { if (isalnum(ch) == 0) { + /* a label must end with a letter or digit */ return FALSE; } } else if (isalnum(ch) == 0) { @@ -239,10 +244,12 @@ _SC_stringIsValidDNSName(const char *name) case '.': case '-': if (prev == '.' || prev == '-') { + /* a label cannot begin or end with a hyphen */ return FALSE; } break; default: + /* an invalid character */ return FALSE; break; } @@ -257,31 +264,19 @@ Boolean _SC_CFStringIsValidDNSName(CFStringRef name) { Boolean clean = FALSE; - CFIndex len; char *str = NULL; if (!isA_CFString(name)) { - goto failed; - } - - len = CFStringGetLength(name) + 1; - if (len == 0) { - goto failed; + return FALSE; } - str = CFAllocatorAllocate(NULL, len, 0); + str = _SC_cfstring_to_cstring(name, NULL, 0, kCFStringEncodingASCII); if (str == NULL) { - goto failed; - } - - if (!CFStringGetCString(name, str, len, kCFStringEncodingASCII)) { - goto failed; + return FALSE; } clean = _SC_stringIsValidDNSName(str); - failed: - if (str) CFAllocatorDeallocate(NULL, str); return clean; } @@ -289,7 +284,7 @@ _SC_CFStringIsValidDNSName(CFStringRef name) Boolean SCPreferencesSetLocalHostName(SCPreferencesRef session, - CFStringRef name) + CFStringRef name) { CFDictionaryRef dict; CFMutableDictionaryRef newDict = NULL; @@ -297,21 +292,29 @@ SCPreferencesSetLocalHostName(SCPreferencesRef session, CFStringRef path = NULL; if (name) { + CFIndex len; + if (!isA_CFString(name)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; } - if (CFStringGetLength(name) == 0) { + len = CFStringGetLength(name); + if (len > 0) { + if (!_SC_CFStringIsValidDNSName(name)) { + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + + if (CFStringFindWithOptions(name, CFSTR("."), CFRangeMake(0, len), 0, NULL)) { + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + } else { name = NULL; } } - if (name && !_SC_CFStringIsValidDNSName(name)) { - _SCErrorSet(kSCStatusInvalidArgument); - return FALSE; - } - path = CFStringCreateWithFormat(NULL, NULL, CFSTR("/%@/%@/%@"), diff --git a/SystemConfiguration.fproj/SCDHostName.h b/SystemConfiguration.fproj/SCDHostName.h deleted file mode 100644 index ac0440a..0000000 --- a/SystemConfiguration.fproj/SCDHostName.h +++ /dev/null @@ -1,38 +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 _SCDHOSTNAME_H -#define _SCDHOSTNAME_H - -#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 1070ba4..a3cb2a1 100644 --- a/SystemConfiguration.fproj/SCDKeys.c +++ b/SystemConfiguration.fproj/SCDKeys.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDKeys.h b/SystemConfiguration.fproj/SCDKeys.h deleted file mode 100644 index b2ee9d7..0000000 --- a/SystemConfiguration.fproj/SCDKeys.h +++ /dev/null @@ -1,37 +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 _SCDKEYS_H -#define _SCDKEYS_H - -#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 e21798b..cee6ec9 100644 --- a/SystemConfiguration.fproj/SCDList.c +++ b/SystemConfiguration.fproj/SCDList.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -43,7 +46,7 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; kern_return_t status; - CFDataRef xmlPattern; /* serialized pattern */ + CFDataRef utfPattern; /* serialized pattern */ xmlData_t myPatternRef; CFIndex myPatternLen; xmlDataOut_t xmlDataRef; /* serialized data */ @@ -51,8 +54,10 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern) int sc_status; CFArrayRef allKeys; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyKeyList:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" pattern = %@"), pattern); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyKeyList:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" pattern = %@"), pattern); + } if (!store) { /* sorry, you must provide a session */ @@ -66,7 +71,7 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern) } /* serialize the pattern */ - if (!_SCSerialize(pattern, &xmlPattern, (void **)&myPatternRef, &myPatternLen)) { + if (!_SCSerializeString(pattern, &utfPattern, (void **)&myPatternRef, &myPatternLen)) { _SCErrorSet(kSCStatusFailed); return NULL; } @@ -81,7 +86,7 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern) (int *)&sc_status); /* clean up */ - CFRelease(xmlPattern); + CFRelease(utfPattern); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) @@ -103,7 +108,7 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern) } /* un-serialize the list of keys */ - if (!_SCUnserialize((CFPropertyListRef *)&allKeys, xmlDataRef, xmlDataLen)) { + if (!_SCUnserialize((CFPropertyListRef *)&allKeys, NULL, xmlDataRef, xmlDataLen)) { _SCErrorSet(kSCStatusFailed); return NULL; } diff --git a/SystemConfiguration.fproj/SCDLock.c b/SystemConfiguration.fproj/SCDLock.c index 227c583..6a08e8d 100644 --- a/SystemConfiguration.fproj/SCDLock.c +++ b/SystemConfiguration.fproj/SCDLock.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDNotifierAdd.c b/SystemConfiguration.fproj/SCDNotifierAdd.c index 3a8cd55..c10977f 100644 --- a/SystemConfiguration.fproj/SCDNotifierAdd.c +++ b/SystemConfiguration.fproj/SCDNotifierAdd.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -43,14 +46,16 @@ SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean is { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; kern_return_t status; - CFDataRef xmlKey; /* serialized key */ + CFDataRef utfKey; /* serialized key */ xmlData_t myKeyRef; CFIndex myKeyLen; int sc_status; - 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 (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddWatchedKey:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE"); + } if (!store) { /* sorry, you must provide a session */ @@ -64,27 +69,8 @@ SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean is return FALSE; } - /* - * add new key after checking if key has already been defined - */ - 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(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 */ - if (!_SCSerialize(key, &xmlKey, (void **)&myKeyRef, &myKeyLen)) { + if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) { _SCErrorSet(kSCStatusFailed); return FALSE; } @@ -97,7 +83,7 @@ SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean is (int *)&sc_status); /* clean up */ - CFRelease(xmlKey); + CFRelease(utfKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) diff --git a/SystemConfiguration.fproj/SCDNotifierCancel.c b/SystemConfiguration.fproj/SCDNotifierCancel.c index 890b089..25c57d5 100644 --- a/SystemConfiguration.fproj/SCDNotifierCancel.c +++ b/SystemConfiguration.fproj/SCDNotifierCancel.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -74,16 +77,16 @@ SCDynamicStoreNotifyCancel(SCDynamicStoreRef store) storePrivate->callbackRunLoopSource, kCFRunLoopDefaultMode); CFRelease(storePrivate->callbackRunLoopSource); + storePrivate->callbackRunLoop = NULL; + storePrivate->callbackRunLoopSource = NULL; /* invalidate port */ CFMachPortInvalidate(storePrivate->callbackPort); CFRelease(storePrivate->callbackPort); + storePrivate->callbackPort = NULL; storePrivate->callbackArgument = NULL; storePrivate->callbackFunction = NULL; - storePrivate->callbackRunLoop = NULL; - storePrivate->callbackRunLoopSource = NULL; - storePrivate->callbackPort = NULL; break; default : break; diff --git a/SystemConfiguration.fproj/SCDNotifierGetChanges.c b/SystemConfiguration.fproj/SCDNotifierGetChanges.c index f139ee1..3d37574 100644 --- a/SystemConfiguration.fproj/SCDNotifierGetChanges.c +++ b/SystemConfiguration.fproj/SCDNotifierGetChanges.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -87,7 +90,7 @@ SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store) } /* un-serialize the list of keys which have changed */ - if (!_SCUnserialize((CFPropertyListRef *)&allKeys, xmlDataRef, xmlDataLen)) { + if (!_SCUnserialize((CFPropertyListRef *)&allKeys, NULL, xmlDataRef, xmlDataLen)) { _SCErrorSet(kSCStatusFailed); return NULL; } diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c b/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c index 2a4385e..74096c5 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -38,8 +41,6 @@ #include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ -#include "v1Compatibility.h" - static void informCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) { @@ -75,22 +76,22 @@ informCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) #endif /* DEBUG */ /* remove the run loop source */ - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), + CFRunLoopRemoveSource(storePrivate->callbackRunLoop, storePrivate->callbackRunLoopSource, kCFRunLoopDefaultMode); CFRelease(storePrivate->callbackRunLoopSource); + storePrivate->callbackRunLoop = NULL; + storePrivate->callbackRunLoopSource = NULL; /* invalidate port */ CFMachPortInvalidate(storePrivate->callbackPort); CFRelease(storePrivate->callbackPort); + storePrivate->callbackPort = NULL; /* disable notifier */ storePrivate->notifyStatus = NotifierNotRegistered; storePrivate->callbackArgument = NULL; storePrivate->callbackFunction = NULL; - storePrivate->callbackPort = NULL; - storePrivate->callbackRunLoop = NULL; - storePrivate->callbackRunLoopSource = NULL; return; } @@ -244,7 +245,7 @@ rlsPortInvalidate(CFMachPortRef mp, void *info) { // A simple deallocate won't get rid of all the references we've accumulated SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" invalidate = %d"), port); - mach_port_destroy(mach_task_self(), port); + (void)mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1); } @@ -322,7 +323,10 @@ rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) storePrivate->callbackRunLoopSource = CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0); } - CFRunLoopAddSource(rl, storePrivate->callbackRunLoopSource, mode); + if (storePrivate->callbackRunLoopSource) { + CFRunLoopAddSource(rl, storePrivate->callbackRunLoopSource, mode); + } + return; } @@ -335,7 +339,9 @@ rlsCancel(void *info, CFRunLoopRef rl, CFStringRef mode) SCLog(_sc_verbose, LOG_DEBUG, CFSTR("cancel notifications for mode %@"), mode); - CFRunLoopRemoveSource(rl, storePrivate->callbackRunLoopSource, mode); + if (storePrivate->callbackRunLoopSource) { + CFRunLoopRemoveSource(rl, storePrivate->callbackRunLoopSource, mode); + } if (--storePrivate->rlsRefs == 0) { int sc_status; @@ -343,27 +349,34 @@ rlsCancel(void *info, CFRunLoopRef rl, CFStringRef mode) SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" cancel callback runloop source")); - /* remove the run loop source */ - CFRelease(storePrivate->callbackRunLoopSource); - storePrivate->callbackRunLoopSource = NULL; + if (storePrivate->callbackRunLoopSource) { + /* remove the run loop source */ + CFRelease(storePrivate->callbackRunLoopSource); + storePrivate->callbackRunLoopSource = NULL; + } - /* invalidate port */ - CFMachPortInvalidate(storePrivate->callbackPort); - CFRelease(storePrivate->callbackPort); - storePrivate->callbackPort = NULL; + if (storePrivate->callbackPort) { + /* invalidate port */ + CFMachPortInvalidate(storePrivate->callbackPort); + CFRelease(storePrivate->callbackPort); + storePrivate->callbackPort = NULL; + } - status = notifycancel(storePrivate->server, (int *)&sc_status); - if (status != KERN_SUCCESS) { - if (status != MACH_SEND_INVALID_DEST) + if (storePrivate->server) { + 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; + (void) mach_port_destroy(mach_task_self(), storePrivate->server); + storePrivate->server = MACH_PORT_NULL; + return; + } } } return; } + static void rlsPerform(void *info) { @@ -417,6 +430,7 @@ rlsRetain(CFTypeRef cf) return cf; } + static void rlsRelease(CFTypeRef cf) { diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaFD.c b/SystemConfiguration.fproj/SCDNotifierInformViaFD.c index 88f5de0..e91cd8b 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaFD.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaFD.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c b/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c index 63ce3d3..42fffca 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c b/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c index 7036a90..9672770 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDNotifierList.c b/SystemConfiguration.fproj/SCDNotifierList.c deleted file mode 100644 index 35fee92..0000000 --- a/SystemConfiguration.fproj/SCDNotifierList.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2000-2002 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 - * - public API conversion - * - * March 24, 2000 Allan Nathanson - * - initial revision - */ - -#include -#include - -#include -#include -#include "SCDynamicStoreInternal.h" - -CFArrayRef -SCDynamicStoreCopyWatchedKeyList(SCDynamicStoreRef store, Boolean isRegex) -{ - SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; - CFIndex keyCnt; - CFSetRef keys; - const void **keyRefs; - CFArrayRef watchedKeys = NULL; - - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyWatchedKeyList:")); - - keys = isRegex ? storePrivate->reKeys : storePrivate->keys; - keyCnt = CFSetGetCount(keys); - if (keyCnt > 0) { - keyRefs = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); - CFSetGetValues(keys, keyRefs); - watchedKeys = CFArrayCreate(NULL, keyRefs, keyCnt, &kCFTypeArrayCallBacks); - CFAllocatorDeallocate(NULL, keyRefs); - } else { - watchedKeys = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); - } - - return watchedKeys; -} diff --git a/SystemConfiguration.fproj/SCDNotifierRemove.c b/SystemConfiguration.fproj/SCDNotifierRemove.c index 8a56811..1cffd11 100644 --- a/SystemConfiguration.fproj/SCDNotifierRemove.c +++ b/SystemConfiguration.fproj/SCDNotifierRemove.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -43,14 +46,16 @@ SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; kern_return_t status; - CFDataRef xmlKey; /* serialized key */ + CFDataRef utfKey; /* serialized key */ xmlData_t myKeyRef; CFIndex myKeyLen; int sc_status; - 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 (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveWatchedKey:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE"); + } if (!store) { /* sorry, you must provide a session */ @@ -64,28 +69,8 @@ SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean return FALSE; } - /* - * remove key from this sessions notifier list after checking that - * it was previously defined. - */ - 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(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 */ - if (!_SCSerialize(key, &xmlKey, (void **)&myKeyRef, &myKeyLen)) { + if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) { _SCErrorSet(kSCStatusFailed); return FALSE; } @@ -98,7 +83,7 @@ SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean (int *)&sc_status); /* clean up */ - CFRelease(xmlKey); + CFRelease(utfKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) diff --git a/SystemConfiguration.fproj/SCDNotifierSetKeys.c b/SystemConfiguration.fproj/SCDNotifierSetKeys.c index f504f7c..483e549 100644 --- a/SystemConfiguration.fproj/SCDNotifierSetKeys.c +++ b/SystemConfiguration.fproj/SCDNotifierSetKeys.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -36,94 +39,26 @@ #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); + 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; + int sc_status; + + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetNotificationKeys:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" keys = %@"), keys); + SCLog(TRUE, LOG_DEBUG, CFSTR(" patterns = %@"), patterns); + } if (!store) { /* sorry, you must provide a session */ @@ -132,39 +67,52 @@ SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, } if (storePrivate->server == MACH_PORT_NULL) { - /* sorry, you must have an open session to play */ _SCErrorSet(kSCStatusNoStoreServer); - return FALSE; + return FALSE; /* you must have an open session to play */ } - 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 */ + /* serialize the keys */ if (keys) { - CFArrayApplyFunction(keys, - CFRangeMake(0, CFArrayGetCount(keys)), - addNewKey, - &myContext); + if (!_SCSerialize(keys, &xmlKeys, (void **)&myKeysRef, &myKeysLen)) { + _SCErrorSet(kSCStatusFailed); + return FALSE; + } } - /* remove any previously registered patterns */ - myContext.newKeys = patterns; - myContext.isRegex = TRUE; - my_CFSetApplyFunction(storePrivate->reKeys, removeOldKey, &myContext); - - /* register any new patterns */ + /* serialize the patterns */ if (patterns) { - CFArrayApplyFunction(patterns, - CFRangeMake(0, CFArrayGetCount(patterns)), - addNewKey, - &myContext); + if (!_SCSerialize(patterns, &xmlPatterns, (void **)&myPatternsRef, &myPatternsLen)) { + CFRelease(xmlKeys); + _SCErrorSet(kSCStatusFailed); + return FALSE; + } + } + + /* send the keys and patterns, fetch the associated result from the server */ + status = notifyset(storePrivate->server, + myKeysRef, + myKeysLen, + myPatternsRef, + myPatternsLen, + (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("notifyset(): %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 myContext.ok; + return TRUE; } diff --git a/SystemConfiguration.fproj/SCDNotifierWait.c b/SystemConfiguration.fproj/SCDNotifierWait.c index fa59f2b..c0992dc 100644 --- a/SystemConfiguration.fproj/SCDNotifierWait.c +++ b/SystemConfiguration.fproj/SCDNotifierWait.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDNotify.c b/SystemConfiguration.fproj/SCDNotify.c index f634973..fafcea0 100644 --- a/SystemConfiguration.fproj/SCDNotify.c +++ b/SystemConfiguration.fproj/SCDNotify.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -41,13 +44,15 @@ SCDynamicStoreNotifyValue(SCDynamicStoreRef store, { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; kern_return_t status; - CFDataRef xmlKey; /* serialized key */ + CFDataRef utfKey; /* 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 (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + } if (!store) { /* sorry, you must provide a session */ @@ -61,11 +66,11 @@ SCDynamicStoreNotifyValue(SCDynamicStoreRef store, return FALSE; } - /* serialize the key */ - if (!_SCSerialize(key, &xmlKey, (void **)&myKeyRef, &myKeyLen)) { - _SCErrorSet(kSCStatusFailed); - return FALSE; - } + /* serialize the key */ + if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) { + _SCErrorSet(kSCStatusFailed); + return FALSE; + } /* send the key to the server */ status = confignotify(storePrivate->server, @@ -74,7 +79,7 @@ SCDynamicStoreNotifyValue(SCDynamicStoreRef store, (int *)&sc_status); /* clean up */ - CFRelease(xmlKey); + CFRelease(utfKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) diff --git a/SystemConfiguration.fproj/SCDOpen.c b/SystemConfiguration.fproj/SCDOpen.c index d78ac73..39ffade 100644 --- a/SystemConfiguration.fproj/SCDOpen.c +++ b/SystemConfiguration.fproj/SCDOpen.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -56,7 +59,6 @@ __SCDynamicStoreCopyDescription(CFTypeRef cf) { static void __SCDynamicStoreDeallocate(CFTypeRef cf) { - CFIndex keyCnt; int oldThreadState; int sc_status; kern_return_t status; @@ -67,44 +69,6 @@ __SCDynamicStoreDeallocate(CFTypeRef cf) (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldThreadState); - /* Remove notification keys */ - keyCnt = CFSetGetCount(storePrivate->keys); - if (keyCnt > 0) { - const 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); - if (keyCnt > 0) { - const 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; ikeys); - CFRelease(storePrivate->reKeys); + CFRelease(storePrivate->patterns); return; } @@ -157,7 +121,6 @@ static const CFRuntimeClass __SCDynamicStoreClass = { static pthread_once_t initialized = PTHREAD_ONCE_INIT; - static void __SCDynamicStoreInitialize(void) { __kSCDynamicStoreTypeID = _CFRuntimeRegisterClass(&__SCDynamicStoreClass); @@ -165,76 +128,76 @@ __SCDynamicStoreInitialize(void) { } -SCDynamicStoreRef +SCDynamicStorePrivateRef __SCDynamicStoreCreatePrivate(CFAllocatorRef allocator, const CFStringRef name, SCDynamicStoreCallBack callout, SCDynamicStoreContext *context) { - SCDynamicStorePrivateRef store; - UInt32 size; + uint32_t size; + SCDynamicStorePrivateRef storePrivate; /* initialize runtime */ pthread_once(&initialized, __SCDynamicStoreInitialize); /* allocate session */ size = sizeof(SCDynamicStorePrivate) - sizeof(CFRuntimeBase); - store = (SCDynamicStorePrivateRef)_CFRuntimeCreateInstance(allocator, - __kSCDynamicStoreTypeID, - size, - NULL); - if (!store) { + storePrivate = (SCDynamicStorePrivateRef)_CFRuntimeCreateInstance(allocator, + __kSCDynamicStoreTypeID, + size, + NULL); + if (!storePrivate) { return NULL; } /* server side of the "configd" session */ - store->server = MACH_PORT_NULL; + storePrivate->server = MACH_PORT_NULL; /* flags */ - store->locked = FALSE; - - /* SCDKeys being watched */ - store->keys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); - store->reKeys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); + storePrivate->locked = FALSE; /* Notification status */ - store->notifyStatus = NotifierNotRegistered; + storePrivate->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; + storePrivate->rlsRefs = 0; + storePrivate->rls = NULL; + storePrivate->rlsFunction = callout; + storePrivate->rlsContext.info = NULL; + storePrivate->rlsContext.retain = NULL; + storePrivate->rlsContext.release = NULL; + storePrivate->rlsContext.copyDescription = NULL; if (context) { - bcopy(context, &store->rlsContext, sizeof(SCDynamicStoreContext)); + bcopy(context, &storePrivate->rlsContext, sizeof(SCDynamicStoreContext)); if (context->retain) { - store->rlsContext.info = (void *)context->retain(context->info); + storePrivate->rlsContext.info = (void *)context->retain(context->info); } } /* "client" information associated with SCDynamicStoreNotifyCallback() */ - store->callbackFunction = NULL; - store->callbackArgument = NULL; - store->callbackPort = NULL; - store->callbackRunLoop = NULL; - store->callbackRunLoopSource = NULL; + storePrivate->callbackFunction = NULL; + storePrivate->callbackArgument = NULL; + storePrivate->callbackPort = NULL; + storePrivate->callbackRunLoop = NULL; + storePrivate->callbackRunLoopSource = NULL; + + /* "server" information associated with SCDynamicStoreSetNotificationKeys() */ + storePrivate->keys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); + storePrivate->patterns = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); /* "server" information associated with SCDynamicStoreNotifyMachPort(); */ - store->notifyPort = MACH_PORT_NULL; - store->notifyPortIdentifier = 0; + storePrivate->notifyPort = MACH_PORT_NULL; + storePrivate->notifyPortIdentifier = 0; /* "server" information associated with SCDynamicStoreNotifyFileDescriptor(); */ - store->notifyFile = -1; - store->notifyFileIdentifier = 0; + storePrivate->notifyFile = -1; + storePrivate->notifyFileIdentifier = 0; /* "server" information associated with SCDynamicStoreNotifySignal(); */ - store->notifySignal = 0; - store->notifySignalTask = TASK_NULL; + storePrivate->notifySignal = 0; + storePrivate->notifySignalTask = TASK_NULL; - return (SCDynamicStoreRef)store; + return storePrivate; } @@ -244,30 +207,32 @@ SCDynamicStoreCreate(CFAllocatorRef allocator, SCDynamicStoreCallBack callout, SCDynamicStoreContext *context) { - SCDynamicStoreRef store; SCDynamicStorePrivateRef storePrivate; kern_return_t status; mach_port_t bootstrap_port; + CFBundleRef bundle; + CFStringRef bundleID = NULL; mach_port_t server; char *server_name; - CFDataRef xmlName; /* serialized name */ + CFDataRef utfName; /* 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); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCreate:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" name = %@"), name); + } /* * allocate and initialize a new session */ - store = __SCDynamicStoreCreatePrivate(allocator, name, callout, context); - storePrivate = (SCDynamicStorePrivateRef)store; + storePrivate = __SCDynamicStoreCreatePrivate(allocator, name, callout, context); status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port); if (status != KERN_SUCCESS) { SCLog(_sc_verbose, LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status)); - CFRelease(store); + CFRelease(storePrivate); _SCErrorSet(status); return NULL; } @@ -284,51 +249,85 @@ SCDynamicStoreCreate(CFAllocatorRef allocator, break; case BOOTSTRAP_UNKNOWN_SERVICE : /* service not currently registered, try again later */ - CFRelease(store); + CFRelease(storePrivate); _SCErrorSet(status); return NULL; break; default : #ifdef DEBUG - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("bootstrap_status: %s"), mach_error_string(status)); + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("bootstrap_look_up() failed: status=%d"), status); #endif /* DEBUG */ - CFRelease(store); + CFRelease(storePrivate); _SCErrorSet(status); return NULL; } /* serialize the name */ - if (!_SCSerialize(name, &xmlName, (void **)&myNameRef, &myNameLen)) { + bundle = CFBundleGetMainBundle(); + if (bundle) { + bundleID = CFBundleGetIdentifier(bundle); + if (bundleID) { + CFRetain(bundleID); + } else { + CFURLRef url; + + url = CFBundleCopyExecutableURL(bundle); + if (url) { + bundleID = CFURLCopyPath(url); + CFRelease(url); + } + } + } + + if (bundleID) { + CFStringRef fullName; + + if (CFEqual(bundleID, CFSTR("/"))) { + CFRelease(bundleID); + bundleID = CFStringCreateWithFormat(NULL, NULL, CFSTR("(%d)"), getpid()); + } + + fullName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"), bundleID, name); + name = fullName; + CFRelease(bundleID); + } else { + CFRetain(name); + } + + if (!_SCSerializeString(name, &utfName, (void **)&myNameRef, &myNameLen)) { + CFRelease(name); _SCErrorSet(kSCStatusFailed); return NULL; } + CFRelease(name); /* open a new session with the server */ status = configopen(server, myNameRef, myNameLen, &storePrivate->server, (int *)&sc_status); /* clean up */ - CFRelease(xmlName); + CFRelease(utfName); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configopen(): %s"), mach_error_string(status)); - CFRelease(store); + CFRelease(storePrivate); _SCErrorSet(status); return NULL; } if (sc_status != kSCStatusOK) { - CFRelease(store); + CFRelease(storePrivate); _SCErrorSet(sc_status); - return FALSE; + return NULL; } SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" server port = %d"), storePrivate->server); - return store; + return (SCDynamicStoreRef)storePrivate; } CFTypeID SCDynamicStoreGetTypeID(void) { + pthread_once(&initialized, __SCDynamicStoreInitialize); /* initialize runtime */ return __kSCDynamicStoreTypeID; } diff --git a/SystemConfiguration.fproj/SCDPlugin.c b/SystemConfiguration.fproj/SCDPlugin.c index 419e35b..d25a14c 100644 --- a/SystemConfiguration.fproj/SCDPlugin.c +++ b/SystemConfiguration.fproj/SCDPlugin.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2001-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -28,9 +31,13 @@ */ #include +#include #include #include +#include #include +#include +#include #include #include #include @@ -124,12 +131,12 @@ reaper(int sigraised) msg.header.msgh_id = 0; options = MACH_SEND_TIMEOUT; status = mach_msg(&msg.header, /* msg */ - MACH_SEND_MSG|options, /* options */ - msg.header.msgh_size, /* send_size */ - 0, /* rcv_size */ - MACH_PORT_NULL, /* rcv_name */ - 0, /* timeout */ - MACH_PORT_NULL); /* notify */ + MACH_SEND_MSG|options, /* options */ + msg.header.msgh_size, /* send_size */ + 0, /* rcv_size */ + MACH_PORT_NULL, /* rcv_name */ + 0, /* timeout */ + MACH_PORT_NULL); /* notify */ return; } @@ -263,12 +270,15 @@ _SCDPluginExecInit() pid_t -_SCDPluginExecCommand(SCDPluginExecCallBack callout, - void *context, - uid_t uid, - gid_t gid, - const char *path, - char * const argv[]) +_SCDPluginExecCommand2(SCDPluginExecCallBack callout, + void *context, + uid_t uid, + gid_t gid, + const char *path, + char * const argv[], + SCDPluginExecSetup setup, + void *setupContext + ) { pid_t pid; @@ -276,13 +286,14 @@ _SCDPluginExecCommand(SCDPluginExecCallBack callout, pthread_mutex_lock(&lock); pid = fork(); + switch (pid) { case -1 : { /* if error */ int status; status = errno; - printf("fork() failed: %s", strerror(status)); + printf("fork() failed: %s\n", strerror(status)); errno = status; break; } @@ -302,11 +313,21 @@ _SCDPluginExecCommand(SCDPluginExecCallBack callout, (void) setgid(gid); } - /* close any open FDs */ - for (i = getdtablesize()-1; i>=0; i--) close(i); - open("/dev/null", O_RDWR, 0); - dup(0); - dup(0); + if (setup) { + (setup)(pid, setupContext); + } else { + /* close any open FDs */ + for (i = getdtablesize()-1; i>=0; i--) close(i); + open(_PATH_DEVNULL, O_RDWR, 0); + dup(0); + dup(0); + } + + /* ensure that our PATH environment variable is somewhat reasonable */ + if (setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin", 0) == -1) { + printf("setenv() failed: %s\n", strerror(errno)); + exit(EX_OSERR); + } /* execute requested command */ (void) execv(path, argv); @@ -317,6 +338,9 @@ _SCDPluginExecCommand(SCDPluginExecCallBack callout, } default : { /* if parent */ + if (setup) { + (setup)(pid, setupContext); + } if (callout) { childInfoRef child; @@ -341,3 +365,15 @@ _SCDPluginExecCommand(SCDPluginExecCallBack callout, return pid; } + + +pid_t +_SCDPluginExecCommand(SCDPluginExecCallBack callout, + void *context, + uid_t uid, + gid_t gid, + const char *path, + char * const argv[]) +{ + return _SCDPluginExecCommand2(callout, context, uid, gid, path, argv, NULL, NULL); +} diff --git a/SystemConfiguration.fproj/SCDPlugin.h b/SystemConfiguration.fproj/SCDPlugin.h index 9933eb9..2daaa0f 100644 --- a/SystemConfiguration.fproj/SCDPlugin.h +++ b/SystemConfiguration.fproj/SCDPlugin.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -86,7 +89,7 @@ typedef void (*SCDynamicStoreBundlePrimeFunction) (); /*! - @typedef SCDPluginExecCallBack + @typedef SCDPluginExecCallBack @discussion Type of the callback function used when a child process started by a plug-in has exited. @param pid The process id of the child which has exited. @@ -94,39 +97,91 @@ typedef void (*SCDynamicStoreBundlePrimeFunction) (); @param rusage A summary of the resources used by the child process and all its children. @param context The callback argument specified on the call - to _SCDPluginExecCommand(). + to _SCDPluginExecCommand(). */ typedef void (*SCDPluginExecCallBack) (pid_t pid, - int status, - struct rusage *rusage, - void *context); + int status, + struct rusage *rusage, + void *context); + + +/*! + @typedef SCDPluginExecSetup + @discussion Type of the setup function used when a child process + is being started. + @param pid The process id of the child, zero for the child process. + @param setupContext The setup argument specified on the call + to _SCDPluginExecCommand2(). + */ +typedef void (*SCDPluginExecSetup) (pid_t pid, + void *setupContext); __BEGIN_DECLS /*! @function _SCDPluginExecCommand - @discussion Starts a child process. - @param callout The function to be called when the child + @discussion Starts a child process. + @param callout The function to be called when the child + process exits. A NULL value can be specified if no + callouts are desired. + @param context A argument which will be passed + to the callout function. + @param uid The desired user id of the child process. + @param gid The desired group id of the child process. + @param path The command to be executed. + @param argv The arguments to be passed to the child process. + @result The process ID of the child. + */ +pid_t +_SCDPluginExecCommand ( + SCDPluginExecCallBack callout, + void *context, + uid_t uid, + gid_t gid, + const char *path, + char * const argv[] + ); + +/*! + @function _SCDPluginExecCommand2 + @discussion Starts a child process. + @param callout The function to be called when the child process exits. A NULL value can be specified if no - callouts are desired. - @param context A argument which will be passed - to the callout function. - @param uid The desired user id of the child process. + callouts are desired. + @param context An argument which will be passed + to the callout function. + @param uid The desired user id of the child process. @param gid The desired group id of the child process. @param path The command to be executed. @param argv The arguments to be passed to the child process. - @result The process ID of the child. + @param setup A pointer to a function which, if specified, will + be called after the call to fork(2) but before the call + to exec(3). + The function will be called in both the parent and child + processes. + The process ID returned by fork(2) will be passed as + an argument to this function (i.e. non-zero in the parent, + zero in the child). + + Note: the setup function is responsibile for establishing + (and closing) all file descriptors that are (not) needed + by the child process. + @param setupContext An argument which will be passed + to the setup function. + @result The process ID of the child. */ pid_t -_SCDPluginExecCommand ( - SCDPluginExecCallBack callout, - void *context, - uid_t uid, - gid_t gid, - const char *path, - char * const argv[] - ); +_SCDPluginExecCommand2 ( + SCDPluginExecCallBack callout, + void *context, + uid_t uid, + gid_t gid, + const char *path, + char * const argv[], + SCDPluginExecSetup setup, + void *setupContext + ); __END_DECLS diff --git a/SystemConfiguration.fproj/SCDPrivate.c b/SystemConfiguration.fproj/SCDPrivate.c index 9ce2fd2..391f504 100644 --- a/SystemConfiguration.fproj/SCDPrivate.c +++ b/SystemConfiguration.fproj/SCDPrivate.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -31,6 +34,7 @@ */ #include +#include #include #include @@ -38,19 +42,56 @@ #include #include -Boolean -_SCSerialize(CFPropertyListRef obj, - CFDataRef *xml, - void **dataRef, - CFIndex *dataLen) +#define N_QUICK 32 + + +char * +_SC_cfstring_to_cstring(CFStringRef cfstr, char *buf, int bufLen, CFStringEncoding encoding) { - CFDataRef myXml; + CFIndex last; + CFIndex len = CFStringGetLength(cfstr); + + /* how much buffer space will we really need? */ + (void)CFStringGetBytes(cfstr, + CFRangeMake(0, len), + encoding, + 0, + FALSE, + NULL, + 0, + &len); + + if (!buf) { + bufLen = len + 1; + buf = CFAllocatorAllocate(NULL, bufLen, 0); + if (!buf) { + return NULL; + } + } - if (!obj) { - /* if no object to serialize */ - return FALSE; + if (len >= bufLen) { + len = bufLen - 1; } + (void)CFStringGetBytes(cfstr, + CFRangeMake(0, len), + encoding, + 0, + FALSE, + buf, + bufLen, + &last); + buf[last] = '\0'; + + return buf; +} + + +Boolean +_SCSerialize(CFPropertyListRef obj, CFDataRef *xml, void **dataRef, CFIndex *dataLen) +{ + CFDataRef myXml; + if (!xml && !(dataRef && dataLen)) { /* if not keeping track of allocated space */ return FALSE; @@ -98,31 +139,33 @@ _SCSerialize(CFPropertyListRef obj, Boolean -_SCUnserialize(CFPropertyListRef *obj, - void *dataRef, - CFIndex dataLen) +_SCUnserialize(CFPropertyListRef *obj, CFDataRef xml, void *dataRef, CFIndex dataLen) { - kern_return_t status; - CFDataRef xml; - CFStringRef xmlError; + CFStringRef xmlError; - if (!obj) { - return FALSE; - } + if (!xml) { + kern_return_t status; - xml = CFDataCreate(NULL, (void *)dataRef, dataLen); - status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen); - if (status != KERN_SUCCESS) { - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); - /* non-fatal???, proceed */ + xml = CFDataCreateWithBytesNoCopy(NULL, (void *)dataRef, dataLen, kCFAllocatorNull); + *obj = CFPropertyListCreateFromXMLData(NULL, + xml, + kCFPropertyListImmutable, + &xmlError); + CFRelease(xml); + + status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen); + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + /* non-fatal???, proceed */ + } + } else { + *obj = CFPropertyListCreateFromXMLData(NULL, + xml, + kCFPropertyListImmutable, + &xmlError); } - *obj = CFPropertyListCreateFromXMLData(NULL, - xml, - kCFPropertyListImmutable, - &xmlError); - CFRelease(xml); - if (!obj) { + if (*obj == NULL) { if (xmlError) { SCLog(TRUE, LOG_ERR, @@ -138,6 +181,251 @@ _SCUnserialize(CFPropertyListRef *obj, } +Boolean +_SCSerializeString(CFStringRef str, CFDataRef *data, void **dataRef, CFIndex *dataLen) +{ + CFDataRef myData; + + if (!isA_CFString(str)) { + /* if not a CFString */ + return FALSE; + } + + if (!data && !(dataRef && dataLen)) { + /* if not keeping track of allocated space */ + return FALSE; + } + + myData = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0); + if (!myData) { + SCLog(TRUE, LOG_ERR, CFSTR("CFStringCreateExternalRepresentation() failed")); + if (data) *data = NULL; + if (dataRef) *dataRef = NULL; + if (dataLen) *dataLen = 0; + return FALSE; + } + + if (data) { + *data = myData; + if (dataRef) { + *dataRef = (void *)CFDataGetBytePtr(myData); + } + if (dataLen) { + *dataLen = CFDataGetLength(myData); + } + } else { + kern_return_t status; + + *dataLen = CFDataGetLength(myData); + status = vm_allocate(mach_task_self(), (void *)dataRef, *dataLen, TRUE); + if (status != KERN_SUCCESS) { + SCLog(TRUE, + LOG_ERR, + CFSTR("vm_allocate(): %s"), + mach_error_string(status)); + CFRelease(myData); + *dataRef = NULL; + *dataLen = 0; + return FALSE; + } + + bcopy((char *)CFDataGetBytePtr(myData), *dataRef, *dataLen); + CFRelease(myData); + } + + return TRUE; +} + + +Boolean +_SCUnserializeString(CFStringRef *str, CFDataRef utf8, void *dataRef, CFIndex dataLen) +{ + if (!utf8) { + kern_return_t status; + + utf8 = CFDataCreateWithBytesNoCopy(NULL, dataRef, dataLen, kCFAllocatorNull); + *str = CFStringCreateFromExternalRepresentation(NULL, utf8, kCFStringEncodingUTF8); + CFRelease(utf8); + + status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen); + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + /* non-fatal???, proceed */ + } + } else { + *str = CFStringCreateFromExternalRepresentation(NULL, utf8, kCFStringEncodingUTF8); + } + + if (*str == NULL) { + SCLog(TRUE, LOG_ERR, CFSTR("CFStringCreateFromExternalRepresentation() failed")); + return FALSE; + } + + return TRUE; +} + + +Boolean +_SCSerializeData(CFDataRef data, void **dataRef, CFIndex *dataLen) +{ + kern_return_t status; + + if (!isA_CFData(data)) { + /* if not a CFData */ + return FALSE; + } + + *dataLen = CFDataGetLength(data); + status = vm_allocate(mach_task_self(), (void *)dataRef, *dataLen, TRUE); + if (status != KERN_SUCCESS) { + SCLog(TRUE, + LOG_ERR, + CFSTR("vm_allocate(): %s"), + mach_error_string(status)); + *dataRef = NULL; + *dataLen = 0; + return FALSE; + } + + bcopy((char *)CFDataGetBytePtr(data), *dataRef, *dataLen); + + return TRUE; +} + + +Boolean +_SCUnserializeData(CFDataRef *data, void *dataRef, CFIndex dataLen) +{ + kern_return_t status; + + *data = CFDataCreate(NULL, dataRef, dataLen); + status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen); + if (status != KERN_SUCCESS) { + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); + _SCErrorSet(kSCStatusFailed); + return FALSE; + } + + return TRUE; +} + + +CFDictionaryRef +_SCSerializeMultiple(CFDictionaryRef dict) +{ + const void * keys_q[N_QUICK]; + const void ** keys = keys_q; + CFIndex nElements; + CFDictionaryRef newDict = NULL; + const void * pLists_q[N_QUICK]; + const void ** pLists = pLists_q; + const void * values_q[N_QUICK]; + const void ** values = values_q; + + nElements = CFDictionaryGetCount(dict); + if (nElements > 0) { + CFIndex i; + + if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { + keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + pLists = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + } + bzero(pLists, nElements * sizeof(CFTypeRef)); + + CFDictionaryGetKeysAndValues(dict, keys, values); + for (i = 0; i < nElements; i++) { + if (!_SCSerialize((CFPropertyListRef)values[i], (CFDataRef *)&pLists[i], NULL, NULL)) { + goto done; + } + } + } + + newDict = CFDictionaryCreate(NULL, + keys, + pLists, + nElements, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + done : + + if (nElements > 0) { + CFIndex i; + + for (i = 0; i < nElements; i++) { + if (pLists[i]) CFRelease(pLists[i]); + } + + if (keys != keys_q) { + CFAllocatorDeallocate(NULL, keys); + CFAllocatorDeallocate(NULL, values); + CFAllocatorDeallocate(NULL, pLists); + } + } + + return newDict; +} + + +CFDictionaryRef +_SCUnserializeMultiple(CFDictionaryRef dict) +{ + const void * keys_q[N_QUICK]; + const void ** keys = keys_q; + CFIndex nElements; + CFDictionaryRef newDict = NULL; + const void * pLists_q[N_QUICK]; + const void ** pLists = pLists_q; + const void * values_q[N_QUICK]; + const void ** values = values_q; + + nElements = CFDictionaryGetCount(dict); + if (nElements > 0) { + CFIndex i; + + if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { + keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + pLists = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + } + bzero(pLists, nElements * sizeof(CFTypeRef)); + + CFDictionaryGetKeysAndValues(dict, keys, values); + for (i = 0; i < nElements; i++) { + if (!_SCUnserialize((CFPropertyListRef *)&pLists[i], values[i], NULL, NULL)) { + goto done; + } + } + } + + newDict = CFDictionaryCreate(NULL, + keys, + pLists, + nElements, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + done : + + if (nElements > 0) { + CFIndex i; + + for (i = 0; i < nElements; i++) { + if (pLists[i]) CFRelease(pLists[i]); + } + + if (keys != keys_q) { + CFAllocatorDeallocate(NULL, keys); + CFAllocatorDeallocate(NULL, values); + CFAllocatorDeallocate(NULL, pLists); + } + } + + return newDict; +} + + void __showMachPortStatus() { @@ -156,7 +444,7 @@ __showMachPortStatus() status = mach_port_names(mach_task_self(), &ports, &pn, &types, &tn); if (status == MACH_MSG_SUCCESS) { str = CFStringCreateMutable(NULL, 0); - for (pi=0; pi < pn; pi++) { + for (pi = 0; pi < pn; pi++) { char rights[16], *rp = &rights[0]; if (types[pi] != MACH_PORT_TYPE_NONE) { diff --git a/SystemConfiguration.fproj/SCDRemove.c b/SystemConfiguration.fproj/SCDRemove.c index 1051fee..c91f82b 100644 --- a/SystemConfiguration.fproj/SCDRemove.c +++ b/SystemConfiguration.fproj/SCDRemove.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -43,13 +46,15 @@ SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; kern_return_t status; - CFDataRef xmlKey; /* serialized key */ + CFDataRef utfKey; /* serialized key */ xmlData_t myKeyRef; CFIndex myKeyLen; int sc_status; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + } if (!store) { /* sorry, you must provide a session */ @@ -64,7 +69,7 @@ SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) } /* serialize the key */ - if (!_SCSerialize(key, &xmlKey, (void **)&myKeyRef, &myKeyLen)) { + if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) { _SCErrorSet(kSCStatusFailed); return FALSE; } @@ -76,7 +81,7 @@ SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) (int *)&sc_status); /* clean up */ - CFRelease(xmlKey); + CFRelease(utfKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) diff --git a/SystemConfiguration.fproj/SCDSet.c b/SystemConfiguration.fproj/SCDSet.c index 01efa6c..56cc859 100644 --- a/SystemConfiguration.fproj/SCDSet.c +++ b/SystemConfiguration.fproj/SCDSet.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -38,6 +41,7 @@ #include "SCDynamicStoreInternal.h" #include "config.h" /* MiG generated file */ + Boolean SCDynamicStoreSetMultiple(SCDynamicStoreRef store, CFDictionaryRef keysToSet, @@ -57,10 +61,12 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store, 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 (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetMultiple:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToSet = %@"), keysToSet); + SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToRemove = %@"), keysToRemove); + SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToNotify = %@"), keysToNotify); + } if (!store) { /* sorry, you must provide a session */ @@ -75,7 +81,19 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store, /* serialize the key/value pairs to set*/ if (keysToSet) { - if (!_SCSerialize(keysToSet, &xmlSet, (void **)&mySetRef, &mySetLen)) { + CFDictionaryRef newInfo; + Boolean ok; + + newInfo = _SCSerializeMultiple(keysToSet); + if (!newInfo) { + _SCErrorSet(kSCStatusFailed); + return NULL; + } + + ok = _SCSerialize(newInfo, &xmlSet, (void **)&mySetRef, &mySetLen); + CFRelease(newInfo); + + if (!ok) { _SCErrorSet(kSCStatusFailed); return NULL; } @@ -137,7 +155,7 @@ SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; kern_return_t status; - CFDataRef xmlKey; /* serialized key */ + CFDataRef utfKey; /* serialized key */ xmlData_t myKeyRef; CFIndex myKeyLen; CFDataRef xmlData; /* serialized data */ @@ -146,9 +164,11 @@ SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR 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 (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value); + } if (!store) { /* sorry, you must provide a session */ @@ -163,16 +183,16 @@ SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR } /* serialize the key */ - if (!_SCSerialize(key, &xmlKey, (void **)&myKeyRef, &myKeyLen)) { + if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) { _SCErrorSet(kSCStatusFailed); - return NULL; + return FALSE; } /* serialize the data */ if (!_SCSerialize(value, &xmlData, (void **)&myDataRef, &myDataLen)) { - CFRelease(xmlKey); + CFRelease(utfKey); _SCErrorSet(kSCStatusFailed); - return NULL; + return FALSE; } /* send the key & data to the server, get new instance id */ @@ -186,7 +206,7 @@ SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR (int *)&sc_status); /* clean up */ - CFRelease(xmlKey); + CFRelease(utfKey); CFRelease(xmlData); if (status != KERN_SUCCESS) { diff --git a/SystemConfiguration.fproj/SCDSnapshot.c b/SystemConfiguration.fproj/SCDSnapshot.c index 03bbffc..851f785 100644 --- a/SystemConfiguration.fproj/SCDSnapshot.c +++ b/SystemConfiguration.fproj/SCDSnapshot.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDTouch.c b/SystemConfiguration.fproj/SCDTouch.c index 24b1e75..b79c8bb 100644 --- a/SystemConfiguration.fproj/SCDTouch.c +++ b/SystemConfiguration.fproj/SCDTouch.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -43,13 +46,15 @@ SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; kern_return_t status; - CFDataRef xmlKey; /* serialized key */ + CFDataRef utfKey; /* serialized key */ xmlData_t myKeyRef; CFIndex myKeyLen; int sc_status; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreTouchValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreTouchValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + } if (!store) { /* sorry, you must provide a session */ @@ -64,7 +69,7 @@ SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) } /* serialize the key */ - if (!_SCSerialize(key, &xmlKey, (void **)&myKeyRef, &myKeyLen)) { + if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) { _SCErrorSet(kSCStatusFailed); return FALSE; } @@ -76,7 +81,7 @@ SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) (int *)&sc_status); /* clean up */ - CFRelease(xmlKey); + CFRelease(utfKey); if (status != KERN_SUCCESS) { if (status != MACH_SEND_INVALID_DEST) diff --git a/SystemConfiguration.fproj/SCDUnlock.c b/SystemConfiguration.fproj/SCDUnlock.c index 38e7745..8d20621 100644 --- a/SystemConfiguration.fproj/SCDUnlock.c +++ b/SystemConfiguration.fproj/SCDUnlock.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDynamicStore.h b/SystemConfiguration.fproj/SCDynamicStore.h index 9347352..b2cec8b 100644 --- a/SystemConfiguration.fproj/SCDynamicStore.h +++ b/SystemConfiguration.fproj/SCDynamicStore.h @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h b/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h index d40ceb3..4eab51c 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h +++ b/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h @@ -2,21 +2,24 @@ * Copyright (c) 2001-2002 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h b/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h index 7c63f27..b1baeaa 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h +++ b/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -75,7 +78,7 @@ SCDynamicStoreCopyComputerName ( */ CFStringRef SCDynamicStoreCopyConsoleUser ( - SCDynamicStoreRef session, + SCDynamicStoreRef store, uid_t *uid, gid_t *gid ); @@ -106,11 +109,11 @@ SCDynamicStoreCopyLocalHostName ( If NULL, a temporary session will be used. @result A string representing the current "location" identifier; NULL if no "location" identifier has been defined or if an error - was encountered. + was encountered. You must release the returned value. */ CFStringRef -SCDynamicStoreCopyLocation ( +SCDynamicStoreCopyLocation ( SCDynamicStoreRef store ); diff --git a/SystemConfiguration.fproj/SCDynamicStoreCopySpecificPrivate.h b/SystemConfiguration.fproj/SCDynamicStoreCopySpecificPrivate.h new file mode 100644 index 0000000..a47a0ea --- /dev/null +++ b/SystemConfiguration.fproj/SCDynamicStoreCopySpecificPrivate.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCDYNAMICSTORECOPYSPECIFICPRIVATE_H +#define _SCDYNAMICSTORECOPYSPECIFICPRIVATE_H + +#include +#include +#include + + +/*! + @header SCDynamicStoreCopySpecificPrivate.h + The following APIs allow an application to retrieve console + information. + */ + + +__BEGIN_DECLS + +/* + * Predefined keys for the console session dictionaries + */ +extern const CFStringRef kSCConsoleSessionID; /* value is CFNumber */ +extern const CFStringRef kSCConsoleSessionUserName; /* value is CFString */ +extern const CFStringRef kSCConsoleSessionUID; /* value is CFNumber */ +extern const CFStringRef kSCConsoleSessionConsoleSet; /* value is CFNumber */ +extern const CFStringRef kSCConsoleSessionOnConsole; /* value is CFBoolean */ + +/*! + @function SCDynamicStoreCopyConsoleInformation + @discussion Returns information about all console sessions on the system. + @param store An SCDynamicStoreRef that should be used for communication + with the server. + If NULL, a temporary session will be used. + @result An array of dictionaries containing information about each + console session on the system; NULL if no sessions are defined + or if an error was encountered. + + The contents of the returned array match that of the CoreGraphics + CGSCopySessionList() SPI. + + You must release the returned value. + */ +CFArrayRef +SCDynamicStoreCopyConsoleInformation ( + SCDynamicStoreRef store + ); + + +__END_DECLS + +#endif /* _SCDYNAMICSTORECOPYSPECIFICPRIVATE_H */ diff --git a/SystemConfiguration.fproj/SCDynamicStoreInternal.h b/SystemConfiguration.fproj/SCDynamicStoreInternal.h index f007b53..be5209a 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreInternal.h +++ b/SystemConfiguration.fproj/SCDynamicStoreInternal.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -41,7 +44,7 @@ typedef enum { Using_NotifierInformViaMachPort, Using_NotifierInformViaFD, Using_NotifierInformViaSignal, - Using_NotifierInformViaRunLoop, + Using_NotifierInformViaRunLoop } __SCDynamicStoreNotificationStatus; @@ -58,7 +61,7 @@ typedef struct { /* SCDynamicStoreKeys being watched */ CFMutableSetRef keys; - CFMutableSetRef reKeys; + CFMutableSetRef patterns; /* current status of notification requests */ __SCDynamicStoreNotificationStatus notifyStatus; @@ -93,20 +96,12 @@ typedef struct { __BEGIN_DECLS -SCDynamicStoreRef +SCDynamicStorePrivateRef __SCDynamicStoreCreatePrivate (CFAllocatorRef allocator, const CFStringRef name, SCDynamicStoreCallBack callout, SCDynamicStoreContext *context); -void -__SCLog (int level, - CFStringRef str); - -void -__SCPrint (FILE *stream, - CFStringRef str); - void __showMachPortStatus (); diff --git a/SystemConfiguration.fproj/SCDynamicStoreKey.h b/SystemConfiguration.fproj/SCDynamicStoreKey.h index f1cb7f6..25c96a7 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreKey.h +++ b/SystemConfiguration.fproj/SCDynamicStoreKey.h @@ -2,21 +2,24 @@ * Copyright (c) 2000-2002 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCDynamicStorePrivate.h b/SystemConfiguration.fproj/SCDynamicStorePrivate.h index 03d43e1..12c180b 100644 --- a/SystemConfiguration.fproj/SCDynamicStorePrivate.h +++ b/SystemConfiguration.fproj/SCDynamicStorePrivate.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -118,10 +121,6 @@ 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 diff --git a/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h b/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h index eb58171..ab325a2 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h +++ b/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2001-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -29,11 +32,40 @@ __BEGIN_DECLS +/*! + @function SCDynamicStoreSetConsoleInformation + @discussion Returns information about all console users on the system. + @param store 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/primary "Console" session. If NULL, any current + "Console" session information will be reset. + @param uid The user ID of the current/primary "Console" user. + @param gid The group ID of the current/primary "Console" user. + @param sessions An array of dictionaries containing information about + each console session on the system; NULL if no sessions are + defined. + + The contents of this array should match that of the CoreGraphics + CGSCopySessionList() SPI. + + @result A boolean indicating the success (or failure) of the call. + */ +Boolean +SCDynamicStoreSetConsoleInformation ( + SCDynamicStoreRef store, + const char *user, + uid_t uid, + gid_t gid, + CFArrayRef sessions + ); + /*! @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 + @param store 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 @@ -45,7 +77,7 @@ __BEGIN_DECLS */ Boolean SCDynamicStoreSetConsoleUser ( - SCDynamicStoreRef session, + SCDynamicStoreRef store, const char *user, uid_t uid, gid_t gid diff --git a/SystemConfiguration.fproj/SCLocation.c b/SystemConfiguration.fproj/SCLocation.c index 90ec0ac..e60486d 100644 --- a/SystemConfiguration.fproj/SCLocation.c +++ b/SystemConfiguration.fproj/SCLocation.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCNetwork.c b/SystemConfiguration.fproj/SCNetwork.c index 0d35172..550e1fd 100644 --- a/SystemConfiguration.fproj/SCNetwork.c +++ b/SystemConfiguration.fproj/SCNetwork.c @@ -1,28 +1,34 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ /* * Modification History * + * January 19, 2003 Allan Nathanson + * - add advanced reachability APIs + * * June 10, 2001 Allan Nathanson * - updated to use service-based "State:" information * @@ -33,1387 +39,86 @@ * - initial revision */ -#include -#include -#include - +#include #include -#include -#include -#include -#include #include -#include #include -#include - -#include "ppp.h" - -static int -inet_atonCF(CFStringRef cfStr, struct in_addr *addr) -{ - char cStr[sizeof("255.255.255.255")]; - - if (!CFStringGetCString(cfStr, cStr, sizeof(cStr), kCFStringEncodingMacRoman)) { - return 0; - } - - return inet_aton(cStr, addr); -} - - -/* - * Function: parse_component - * Purpose: - * Given a string 'key' and a string prefix 'prefix', - * return the next component in the slash '/' separated - * key. - * - * Examples: - * 1. key = "a/b/c" prefix = "a/" - * returns "b" - * 2. key = "a/b/c" prefix = "a/b/" - * returns "c" - */ -static CFStringRef -parse_component(CFStringRef key, CFStringRef prefix) -{ - CFMutableStringRef comp; - CFRange range; - - if (CFStringHasPrefix(key, prefix) == FALSE) { - return NULL; - } - comp = CFStringCreateMutableCopy(NULL, 0, key); - CFStringDelete(comp, CFRangeMake(0, CFStringGetLength(prefix))); - range = CFStringFind(comp, CFSTR("/"), 0); - if (range.location == kCFNotFound) { - return comp; - } - range.length = CFStringGetLength(comp) - range.location; - CFStringDelete(comp, range); - return comp; -} - - -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) -{ - initContextRef info = (initContextRef)context; - CFStringRef interface; - CFStringRef interfaceKey; - CFStringRef service; - CFStringRef serviceKey; - - if (!isA_CFString(key) || !isA_CFDictionary(value)) { - return; - } - - 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); - } - CFRelease(serviceKey); - - if (!CFArrayContainsValue(info->order, CFRangeMake(0, CFArrayGetCount(info->order)), service)) { - CFArrayAppendValue(info->order, service); - } - - 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); - } - CFRelease(serviceKey); - - if (!CFArrayContainsValue(info->order, CFRangeMake(0, CFArrayGetCount(info->order)), service)) { - CFArrayAppendValue(info->order, service); - } - - CFRelease(service); - return; - } - - 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; -} - - -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; - } - - 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; - } - - 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; - } - - done : - - CFRelease(service); - return; -} - - -static void -removeKnownAddresses(const void *key, const void *value, void *context) -{ - CFMutableDictionaryRef ifDict; - CFStringRef ifName; - CFMutableDictionaryRef interfaces = (CFMutableDictionaryRef)context; - CFMutableDictionaryRef serviceDict = (CFMutableDictionaryRef)value; - Boolean updated = FALSE; - - 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; - } - - ifDict = (CFMutableDictionaryRef)CFDictionaryGetValue(interfaces, ifName); - if (!ifDict) { - /* if the indicated interface is not active */ - return; - } - - sAddrs = isA_CFArray(CFDictionaryGetValue(serviceDict, - kSCPropNetIPv4Addresses)); - sDests = isA_CFArray(CFDictionaryGetValue(serviceDict, - kSCPropNetIPv4DestAddresses)); - sMasks = isA_CFArray(CFDictionaryGetValue(serviceDict, - kSCPropNetIPv4SubnetMasks)); - - if (!sAddrs || ((n = CFArrayGetCount(sAddrs)) == 0)) { - /* if no addresses */ - return; - } - - if (((sMasks == NULL) && (sDests == NULL)) || - ((sMasks != NULL) && (sDests != NULL))) { - /* - * sorry, we expect to have "SubnetMasks" or - * "DestAddresses" (not both). - */ - return; - } - - if (sMasks && (n != CFArrayGetCount(sMasks))) { - /* if we don't like the "SubnetMasks" */ - return; - } - - if (sDests && (n != CFArrayGetCount(sDests))) { - /* if we don't like the "DestAddresses" */ - return; - } - - iAddrs = isA_CFArray(CFDictionaryGetValue(ifDict, - kSCPropNetIPv4Addresses)); - iDests = isA_CFArray(CFDictionaryGetValue(ifDict, - kSCPropNetIPv4DestAddresses)); - iMasks = isA_CFArray(CFDictionaryGetValue(ifDict, - kSCPropNetIPv4SubnetMasks)); - - if (((iMasks == NULL) && (iDests == NULL)) || - ((iMasks != NULL) && (iDests != NULL))) { - /* - * sorry, we expect to have "SubnetMasks" or - * "DestAddresses" (not both). - */ - return; - } - - if (!iAddrs || ((i = CFArrayGetCount(iAddrs)) == 0)) { - /* if no addresses */ - return; - } - - if (iMasks && (i != CFArrayGetCount(iMasks))) { - /* if we don't like the "SubnetMasks" */ - return; - } - - if (iDests && (i != CFArrayGetCount(iDests))) { - /* if we don't like the "DestAddresses" */ - return; - } - - if (((sMasks == NULL) && (iMasks != NULL)) || - ((sDests == NULL) && (iDests != NULL))) { - /* if our addressing schemes are in conflict */ - return; - } - - nAddrs = CFArrayCreateMutableCopy(NULL, 0, iAddrs); - if (iMasks) nMasks = CFArrayCreateMutableCopy(NULL, 0, iMasks); - if (iDests) nDests = CFArrayCreateMutableCopy(NULL, 0, iDests); - for (s=0; s= 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; - } - } - } - - 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; -} - - -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; - } - - /* 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 -getAddresses(CFDictionaryRef iDict, - CFIndex *nAddrs, - CFArrayRef *addrs, - CFArrayRef *masks, - CFArrayRef *dests) -{ - *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 == NULL) && (*dests == NULL)) || - ((*masks != NULL) && (*dests != NULL))) { - /* - * sorry, we expect to have "SubnetMasks" or - * "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 Boolean -checkAddress(SCDynamicStoreRef store, - const struct sockaddr *address, - const int addrlen, - CFDictionaryRef config, - CFDictionaryRef active, - CFArrayRef serviceOrder, - struct in_addr *defaultRoute, - SCNetworkConnectionFlags *flags) -{ - CFIndex aCnt; - CFStringRef aType = NULL; - CFDictionaryRef cDict = NULL; - CFIndex i; - CFStringRef key = NULL; - int pppRef = -1; - int sc_status = kSCStatusReachabilityUnknown; - char *statusMessage = NULL; - - if (!address || !flags) { - sc_status = kSCStatusInvalidArgument; - goto done; - } - - *flags = 0; - - if (address->sa_family == AF_INET) { - struct sockaddr_in *sin = (struct sockaddr_in *)address; - - 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 - */ - aCnt = CFArrayGetCount(serviceOrder); - for (i=0; isin_addr.s_addr) & ntohl(ifMask.s_addr))) { - /* the requested address is on this subnet */ - statusMessage = "isReachable (my subnet)"; - *flags |= kSCNetworkFlagsReachable; - goto checkInterface; - } - } else { - struct in_addr destAddr; - - /* check remote address */ - if (inet_atonCF(CFArrayGetValueAtIndex(dests, j), - &destAddr) == 0) { - /* if DestAddresses string is invalid */ - break; - } - /* check local address */ - if (ntohl(sin->sin_addr.s_addr) == ntohl(ifAddr.s_addr)) { - /* the address is our side of the link */ - 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 */ - statusMessage = "isReachable (my remote address)"; - *flags |= kSCNetworkFlagsReachable; - goto checkInterface; - } - } - } - } - - /* - * 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; - } - - for (j=0; defaultRoute && js_addr) & ntohl(ifMask.s_addr))) { - /* the requested address is on this subnet */ - statusMessage = "isReachable via default route (my subnet)"; - *flags |= kSCNetworkFlagsReachable; - goto checkInterface; - } - } else { - struct in_addr destAddr; - - /* check remote address */ - if (inet_atonCF(CFArrayGetValueAtIndex(dests, j), - &destAddr) == 0) { - /* if DestAddresses string is invalid */ - break; - } - - if (ntohl(destAddr.s_addr) == ntohl(defaultRoute->s_addr)) { - /* the address is the other side of the link */ - statusMessage = "isReachable via default route (my remote address)"; - *flags |= kSCNetworkFlagsReachable; - goto checkInterface; - } - } - } - } - - /* - * Check the not active (but configured) IPv4 services - */ - for (i=0; isa_family); - sc_status = kSCStatusInvalidArgument; - goto done; - } - - goto done; - - 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. - */ - { - CFNumberRef num; - CFDictionaryRef cDict; - - /* attempt to get the interface type from the config info */ - cDict = CFDictionaryGetValue(config, key); - if (cDict) { - aType = CFDictionaryGetValue(cDict, kSCPropNetInterfaceType); - } - - 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(cDict, kSCPropNetPPPDialOnDemand); - if (num) { - int dialOnDemand; - - CFNumberGetValue(num, kCFNumberIntType, &dialOnDemand); - if (dialOnDemand != 0) { - *flags |= kSCNetworkFlagsConnectionAutomatic; - } - - } - } - - *flags |= kSCNetworkFlagsTransientConnection; - - { - u_int32_t pppLink; - struct ppp_status *pppLinkStatus; - int pppStatus; - - /* - * The service ID is available, ask the PPP controller - * for the extended status. - */ - pppStatus = PPPInit(&pppRef); - if (pppStatus != 0) { - SCLog(_sc_debug, LOG_DEBUG, CFSTR(" PPPInit() failed: status=%d"), pppStatus); - sc_status = kSCStatusReachabilityUnknown; - goto done; - } - - pppStatus = PPPGetLinkByServiceID(pppRef, key, &pppLink); - if (pppStatus != 0) { - SCLog(_sc_debug, LOG_DEBUG, CFSTR(" PPPGetLinkByServiceID() failed: status=%d"), pppStatus); - sc_status = kSCStatusReachabilityUnknown; - goto done; - } - - pppStatus = PPPStatus(pppRef, pppLink, &pppLinkStatus); - if (pppStatus != 0) { - SCLog(_sc_debug, LOG_DEBUG, CFSTR(" PPPStatus() failed: status=%d"), pppStatus); - sc_status = kSCStatusReachabilityUnknown; - goto done; - } -#ifdef DEBUG - SCLog(_sc_debug, LOG_DEBUG, CFSTR(" PPP link status = %d"), pppLinkStatus->status); -#endif /* DEBUG */ - switch (pppLinkStatus->status) { - case PPP_RUNNING : - /* if we're really UP and RUNNING */ - break; - case PPP_ONHOLD : - /* if we're effectively UP and RUNNING */ - break; - case PPP_IDLE : - /* if we're not connected at all */ - 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 */ - SCLog(_sc_debug, LOG_INFO, CFSTR(" PPP link, connection in progress")); - *flags |= kSCNetworkFlagsReachable; - *flags |= kSCNetworkFlagsConnectionRequired; - sc_status = kSCStatusOK; - break; - } - CFAllocatorDeallocate(NULL, pppLinkStatus); - } - - goto done; - - done : - - if (pppRef != -1) (void) PPPDispose(pppRef); - - if (sc_status != kSCStatusOK) { - _SCErrorSet(sc_status); - return FALSE; - } - - return TRUE; -} - - -static void -_CheckReachabilityInit(SCDynamicStoreRef store, - CFDictionaryRef *config, - CFDictionaryRef *active, - CFArrayRef *serviceOrder, - struct in_addr **defaultRoute) -{ - 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); - - /* - * collect information on the configured services and their - * associated interface type. - */ - keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - - /* - * Setup:/Network/Global/IPv4 (for the ServiceOrder) - */ - orderKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, - kSCDynamicStoreDomainSetup, - kSCEntNetIPv4); - CFArrayAppendValue(keys, orderKey); - - /* - * 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 the ServiceOrder key from the global settings. - */ - 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; - } else { - *defaultRoute = route; - } - } - } - - /* - * collect the configured services, the active services, and - * the active interfaces. - */ - 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); - - /* - * add additional information for the configured services - */ - CFDictionaryApplyFunction(dict, collectExtraInfo, &context); - - /* - * 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 - 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 -_CheckReachabilityFree(CFDictionaryRef config, - CFDictionaryRef active, - CFArrayRef serviceOrder, - struct in_addr *defaultRoute) -{ - if (config) CFRelease(config); - if (active) CFRelease(active); - if (serviceOrder) CFRelease(serviceOrder); - if (defaultRoute) CFAllocatorDeallocate(NULL, defaultRoute); - return; -} +#include +#include +#ifndef kSCEntNetRefreshConfiguration +#define kSCEntNetRefreshConfiguration CFSTR("RefreshConfiguration") +#endif kSCEntNetRefreshConfiguration Boolean SCNetworkCheckReachabilityByAddress(const struct sockaddr *address, const int addrlen, SCNetworkConnectionFlags *flags) { - CFDictionaryRef active = NULL; - CFDictionaryRef config = NULL; - struct in_addr *defaultRoute = NULL; + SCNetworkReachabilityRef networkAddress; Boolean ok; - CFArrayRef serviceOrder = NULL; - SCDynamicStoreRef store = NULL; - - *flags = 0; + struct sockaddr_storage ss; - /* - * 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; - } - } - - store = SCDynamicStoreCreate(NULL, - CFSTR("SCNetworkCheckReachabilityByAddress"), - NULL, - NULL); - if (!store) { - SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + if (!address || + (addrlen == 0) || + (addrlen > (int)sizeof(struct sockaddr_storage))) { + _SCErrorSet(kSCStatusInvalidArgument); return FALSE; } - _CheckReachabilityInit(store, &config, &active, &serviceOrder, &defaultRoute); - ok = checkAddress(store, - address, - addrlen, - config, - active, - serviceOrder, - defaultRoute, - flags); - _CheckReachabilityFree(config, active, serviceOrder, defaultRoute); + bzero(&ss, sizeof(ss)); + bcopy(address, &ss, addrlen); + ss.ss_len = addrlen; - CFRelease(store); + networkAddress = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&ss); + ok = SCNetworkReachabilityGetFlags(networkAddress, flags); + CFRelease(networkAddress); return ok; } -/* - * rankReachability() - * Not reachable == 0 - * Connection Required == 1 - * Reachable == 2 - */ -static int -rankReachability(int flags) -{ - 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; -#ifdef CHECK_IPV6_REACHABILITY - struct addrinfo *res = NULL; - struct addrinfo *resP; -#endif /* CHECK_IPV6_REACHABILITY */ - CFArrayRef serviceOrder = NULL; - SCDynamicStoreRef store = NULL; + SCNetworkReachabilityRef networkAddress; + Boolean ok; - store = SCDynamicStoreCreate(NULL, - CFSTR("SCNetworkCheckReachabilityByName"), - NULL, - NULL); - if (!store) { - SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + if (!nodename) { + _SCErrorSet(kSCStatusInvalidArgument); return FALSE; } - _CheckReachabilityInit(store, &config, &active, &serviceOrder, &defaultRoute); - - /* - * 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++) { - 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 */ - *flags = ns_flags; - } - } - - 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. - */ - *flags = 0; - - /* - * resolve the nodename into an address - */ - -#ifdef CHECK_IPV6_REACHABILITY - i = getaddrinfo(nodename, NULL, NULL, &res); - if (i != 0) { - SCLog(_sc_verbose, LOG_ERR, - CFSTR("getaddrinfo() failed: %s"), - gai_strerror(i)); - goto done; - } - - for (resP=res; resP!=NULL; resP=resP->ai_next) { - 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; - } - } + networkAddress = SCNetworkReachabilityCreateWithName(NULL, nodename); + ok = SCNetworkReachabilityGetFlags(networkAddress, flags); + CFRelease(networkAddress); + return ok; +} - 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 */ - *flags = ns_flags; - if (rankReachability(*flags) == 2) { - /* we're in luck */ - break; - } - } - } +Boolean +SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName) +{ + CFStringRef key; + Boolean ret = FALSE; + SCDynamicStoreRef store = NULL; - if (res) { + store = SCDynamicStoreCreate(NULL, + CFSTR("SCNetworkInterfaceRefreshConfiguration"), + NULL, NULL); + if (store == NULL) { goto done; } + key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, + kSCDynamicStoreDomainState, + ifName, + kSCEntNetRefreshConfiguration); + ret = SCDynamicStoreNotifyValue(store, key); + CFRelease(key); - /* - * The getaddrinfo() function call didn't return any addresses. While - * this may be the correct answer we have found that some DNS servers - * may, depending on what has been cached, not return all available - * records when issued a T_ANY query. To accomodate these servers - * we double check by using the gethostbyname() function which uses - * a simple T_A query. - */ - -#ifdef DEBUG - SCLog(_sc_debug, - LOG_INFO, - CFSTR("getaddrinfo() returned no addresses, try gethostbyname()")); -#endif /* DEBUG */ -#endif /* CHECK_IPV6_REACHABILITY */ - - h = gethostbyname(nodename); - if (h && h->h_length) { - struct in_addr **s = (struct in_addr **)h->h_addr_list; - - 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; - - 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 */ - *flags = ns_flags; - if (rankReachability(*flags) == 2) { - /* we're in luck */ - break; - } - } - - 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: + if (store != NULL) { + CFRelease(store); } - - done : - - _CheckReachabilityFree(config, active, serviceOrder, defaultRoute); - if (store) CFRelease(store); -#ifdef CHECK_IPV6_REACHABILITY - if (res) freeaddrinfo(res); -#endif /* CHECK_IPV6_REACHABILITY */ - - return ok; + return (ret); } diff --git a/SystemConfiguration.fproj/SCNetwork.h b/SystemConfiguration.fproj/SCNetwork.h index c48e342..7ac7168 100644 --- a/SystemConfiguration.fproj/SCNetwork.h +++ b/SystemConfiguration.fproj/SCNetwork.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -31,20 +34,28 @@ /*! @header SCNetwork + + SCNetworkCheckReachabilityXXX() + The SCNetworkCheckReachabilityXXX() APIs allow an application to - determine the status of the system's current network configuration. + determine the status of the system's current network configuration + and the accessibility of a target host/address. The term "reachable" reflects whether a data packet, sent by - an application into the network stack, will be able to reach - the destination host. + an application into the network stack, can be sent to the + the target host/address. Please note that their is no + guarantee that the data packet will actually be received by + the host. - 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 system's current - configuration. + SCNetworkInterfaceRefreshConfiguration() + + This API sends a notification to interested network configuration + agents to retry their configuraton immediately. For example, calling + this API will cause the DHCP client to contact the DHCP server + immediately rather than waiting until its timeout has expired. + The utility of this API is to allow the caller to give a hint to + the system that the network infrastructure/configuration has changed. */ /*! @@ -85,15 +96,27 @@ form of user intervention will be required to establish this connection (e.g. providing a password, authentication token, etc.). - */ -typedef enum { - kSCNetworkFlagsTransientConnection = 1<<0, - kSCNetworkFlagsReachable = 1<<1, - kSCNetworkFlagsConnectionRequired = 1<<2, - kSCNetworkFlagsConnectionAutomatic = 1<<3, - kSCNetworkFlagsInterventionRequired = 1<<4, -} SCNetworkConnectionFlags; + @constant kSCNetworkFlagsIsLocalAddress + This flag indicates that the specified nodename/address + is one associated with a network interface on the current + system. + + @constant kSCNetworkFlagsIsDirect + This flag indicates that network traffic to the specified + nodename/address will not go through a gateway but is routed + directly to one of the interfaces in the system. + */ +enum { + kSCNetworkFlagsTransientConnection = 1<<0, + kSCNetworkFlagsReachable = 1<<1, + kSCNetworkFlagsConnectionRequired = 1<<2, + kSCNetworkFlagsConnectionAutomatic = 1<<3, + kSCNetworkFlagsInterventionRequired = 1<<4, + kSCNetworkFlagsIsLocalAddress = 1<<16, + kSCNetworkFlagsIsDirect = 1<<17 +}; +typedef uint32_t SCNetworkConnectionFlags; __BEGIN_DECLS @@ -101,8 +124,6 @@ __BEGIN_DECLS @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 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 @@ -114,7 +135,7 @@ __BEGIN_DECLS Boolean SCNetworkCheckReachabilityByAddress ( const struct sockaddr *address, - const int addrlen, + int addrlen, SCNetworkConnectionFlags *flags ); @@ -122,9 +143,6 @@ SCNetworkCheckReachabilityByAddress ( @function SCNetworkCheckReachabilityByName @discussion Determines if the given network host/node name is reachable using the current network configuration. - - 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 that will be filled with a @@ -138,7 +156,20 @@ SCNetworkCheckReachabilityByName ( const char *nodename, SCNetworkConnectionFlags *flags ); - +/*! + @function SCNetworkInterfaceRefreshConfiguration + @discussion Sends a notification to interested configuration agents + to have them immediately retry their configuration over a + particular network interface. + Note: This API must be invoked by root (uid == 0). + + @param ifName The BSD name of the network interface e.g. CFSTR("en0"). + @result TRUE if the notification was sent; FALSE otherwise. + */ +Boolean +SCNetworkInterfaceRefreshConfiguration ( + CFStringRef ifName + ); __END_DECLS #endif /* _SCNETWORK_H */ diff --git a/SystemConfiguration.fproj/SCNetworkConnection.c b/SystemConfiguration.fproj/SCNetworkConnection.c new file mode 100644 index 0000000..b50cda0 --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkConnection.c @@ -0,0 +1,1201 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Modification History + * + * December 20, 2002 Christophe Allie + * - initial revision + */ + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +#include +#include + +#include +#include "dy_framework.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ppp.h" + + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +typedef struct { + + /* base CFType information */ + CFRuntimeBase cfBase; + + /* service ID */ + CFStringRef serviceID; /* serviceID */ + + int eventRef; /* ref to PPP controller for event messages */ + CFSocketRef eventRefCF; /* ref to PPP controller for event messages */ + int controlRef; /* ref to PPP controller for control messages */ + //u_int32_t status; /* current status of the connection */ + //char ifname[IFNAMSIZ]; /* ppp interface used for this connection */ + + /* run loop source, callout, context, rl scheduling info */ + CFRunLoopSourceRef rls; + SCNetworkConnectionCallBack rlsFunction; + SCNetworkConnectionContext rlsContext; + CFMutableArrayRef rlList; + +} SCNetworkConnectionPrivate, *SCNetworkConnectionPrivateRef; + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +static __inline__ CFTypeRef +isA_SCNetworkConnection(CFTypeRef obj) +{ + return (isA_CFType(obj, SCNetworkConnectionGetTypeID())); +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +static CFStringRef +__SCNetworkConnectionCopyDescription(CFTypeRef cf) +{ + CFAllocatorRef allocator = CFGetAllocator(cf); + CFMutableStringRef result; + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)cf; + + result = CFStringCreateMutable(allocator, 0); + CFStringAppendFormat(result, NULL, CFSTR(" {\n"), cf, allocator); + CFStringAppendFormat(result, NULL, CFSTR(" serviceID = %@ \n"), connectionPrivate->serviceID); + CFStringAppendFormat(result, NULL, CFSTR("}")); + + return result; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ +static void +__SCNetworkConnectionDeallocate(CFTypeRef cf) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)cf; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkConnectionDeallocate:")); + + /* release resources */ + if (connectionPrivate->eventRef != -1) { + while (CFArrayGetCount(connectionPrivate->rlList)) { + CFRunLoopRef runLoop; + CFStringRef runLoopMode; + + runLoop = (CFRunLoopRef)CFArrayGetValueAtIndex(connectionPrivate->rlList, 1); + runLoopMode = CFArrayGetValueAtIndex(connectionPrivate->rlList, 2); + CFRunLoopRemoveSource(runLoop, connectionPrivate->rls, runLoopMode); + + CFArrayRemoveValueAtIndex(connectionPrivate->rlList, 2); + CFArrayRemoveValueAtIndex(connectionPrivate->rlList, 1); + CFArrayRemoveValueAtIndex(connectionPrivate->rlList, 0); + } + CFRelease(connectionPrivate->rls); + CFRelease(connectionPrivate->rlList); + //PPPDispose(connectionPrivate->eventRef); + CFSocketInvalidate(connectionPrivate->eventRefCF); + CFRelease(connectionPrivate->eventRefCF); + } + if (connectionPrivate->controlRef != -1) + PPPDispose(connectionPrivate->controlRef); + if (connectionPrivate->rlsContext.release) + connectionPrivate->rlsContext.release(connectionPrivate->rlsContext.info); + if (connectionPrivate->serviceID) + CFRelease(connectionPrivate->serviceID); + + return; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +static pthread_once_t initialized = PTHREAD_ONCE_INIT; + +static CFTypeID __kSCNetworkConnectionTypeID = _kCFRuntimeNotATypeID; + +static const CFRuntimeClass __SCNetworkConnectionClass = { + 0, // version + "SCNetworkConnection", // className + NULL, // init + NULL, // copy + __SCNetworkConnectionDeallocate, // dealloc + NULL, // equal + NULL, // hash + NULL, // copyFormattingDesc + __SCNetworkConnectionCopyDescription // copyDebugDesc +}; + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +static void +__SCNetworkConnectionInitialize(void) +{ + __kSCNetworkConnectionTypeID = _CFRuntimeRegisterClass(&__SCNetworkConnectionClass); + return; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ +static SCNetworkConnectionPrivateRef +__SCNetworkConnectionCreatePrivate(CFAllocatorRef allocator, CFStringRef serviceID) +{ + SCNetworkConnectionPrivateRef connectionPrivate = 0; + uint32_t size; + struct ppp_status *stats = 0; + int error = kSCStatusFailed; + + /* initialize runtime */ + pthread_once(&initialized, __SCNetworkConnectionInitialize); + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkConnectionCreatePrivate:")); + + /* allocate NetworkConnection */ + size = sizeof(SCNetworkConnectionPrivate) - sizeof(CFRuntimeBase); + connectionPrivate = (SCNetworkConnectionPrivateRef)_CFRuntimeCreateInstance(allocator, __kSCNetworkConnectionTypeID,size, NULL); + if (connectionPrivate == 0) + goto fail; + + /* zero the data structure */ + bzero(((u_char*)connectionPrivate)+sizeof(CFRuntimeBase), size); + + /* save the serviceID */ + connectionPrivate->serviceID = CFStringCreateCopy(NULL, serviceID); + + connectionPrivate->controlRef = -1; + connectionPrivate->eventRef = -1; + + if (PPPInit(&connectionPrivate->controlRef)) + goto fail; + + if (PPPStatus(connectionPrivate->controlRef, serviceID, 0, &stats)) { + error = kSCStatusInvalidArgument; // XXX can't get status, invalid service id + goto fail; + } + + CFAllocatorDeallocate(NULL, stats); + stats = 0; + + /* success, return the connection reference */ + return connectionPrivate; + + fail: + + /* failure, clean up and leave */ + if (connectionPrivate) + CFRelease(connectionPrivate); + if (stats) + CFAllocatorDeallocate(NULL, stats); + _SCErrorSet(error); + return NULL; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +CFTypeID +SCNetworkConnectionGetTypeID (void) { + pthread_once(&initialized, __SCNetworkConnectionInitialize); /* initialize runtime */ + return __kSCNetworkConnectionTypeID; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ +static SCNetworkConnectionStatus +__SCNetworkConnectionConvertStatus (int state) +{ + SCNetworkConnectionStatus status = kSCNetworkConnectionDisconnected; + + switch (state) { + case PPP_INITIALIZE: + case PPP_CONNECTLINK: + case PPP_ESTABLISH: + case PPP_AUTHENTICATE: + case PPP_CALLBACK: + case PPP_NETWORK: + case PPP_WAITONBUSY: + status = kSCNetworkConnectionConnecting; + break; + case PPP_TERMINATE: + case PPP_DISCONNECTLINK: + case PPP_HOLDOFF: + status = kSCNetworkConnectionDisconnecting; + break; + case PPP_RUNNING: + case PPP_ONHOLD: + status = kSCNetworkConnectionConnected; + break; + case PPP_IDLE: + case PPP_STATERESERVED: + default: + status = kSCNetworkConnectionDisconnected; + } + return status; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +SCNetworkConnectionRef +SCNetworkConnectionCreateWithServiceID (CFAllocatorRef allocator, + CFStringRef serviceID, + SCNetworkConnectionCallBack callout, + SCNetworkConnectionContext *context) +{ + SCNetworkConnectionPrivateRef connectionPrivate; + + if (!isA_CFString(serviceID)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + connectionPrivate = __SCNetworkConnectionCreatePrivate(allocator, serviceID); + + if (connectionPrivate) { + connectionPrivate->rlsFunction = callout; + if (context) { + bcopy(context, &connectionPrivate->rlsContext, sizeof(SCNetworkConnectionContext)); + if (context->retain) { + connectionPrivate->rlsContext.info = (void *)context->retain(context->info); + } + } + } + + return (SCNetworkConnectionRef)connectionPrivate; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +CFStringRef +SCNetworkConnectionCopyServiceID (SCNetworkConnectionRef connection) +{ + if (!isA_SCNetworkConnection(connection)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + return CFRetain(((SCNetworkConnectionPrivateRef)connection)->serviceID); +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +CFDictionaryRef +SCNetworkConnectionCopyStatistics (SCNetworkConnectionRef connection) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + int error = kSCStatusFailed; + struct ppp_status *stats = 0; + CFMutableDictionaryRef dict = 0; + CFMutableDictionaryRef statsdict = 0; + +#define ADDNUMBER(d, k, n) \ +{ \ + CFNumberRef num; \ + num = CFNumberCreate(NULL, kCFNumberSInt32Type, n); \ + if (num) { \ + CFDictionaryAddValue(d, k, num); \ + CFRelease(num); \ + } \ +} + + if (!isA_SCNetworkConnection(connection)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + /* get status and check connected state */ + if (PPPStatus(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &stats)) + goto fail; + + if (__SCNetworkConnectionConvertStatus(stats->status) != kSCNetworkConnectionConnected) + goto fail; + + /* create dictionaries */ + if ((statsdict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0) + goto fail; + + if ((dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0) + goto fail; + + /* add statistics */ + ADDNUMBER(dict, kSCNetworkConnectionBytesIn, &stats->s.run.inBytes); + ADDNUMBER(dict, kSCNetworkConnectionBytesOut, &stats->s.run.outBytes); + ADDNUMBER(dict, kSCNetworkConnectionPacketsIn, &stats->s.run.inPackets); + ADDNUMBER(dict, kSCNetworkConnectionPacketsOut, &stats->s.run.outPackets); + ADDNUMBER(dict, kSCNetworkConnectionErrorsIn, &stats->s.run.inErrors); + ADDNUMBER(dict, kSCNetworkConnectionErrorsOut, &stats->s.run.outErrors); + + /* add the PPP dictionary to the statistics dictionary */ + CFDictionaryAddValue(statsdict, kSCEntNetPPP, dict); + CFRelease(dict); + + /* done */ + CFAllocatorDeallocate(NULL, stats); + return statsdict; + + fail: + + if (stats) + CFAllocatorDeallocate(NULL, stats); + if (dict) + CFRelease(dict); + if (statsdict) + CFRelease(statsdict); + _SCErrorSet(error); + return NULL; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +SCNetworkConnectionStatus +SCNetworkConnectionGetStatus (SCNetworkConnectionRef connection) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + struct ppp_status *stats = 0; + SCNetworkConnectionStatus status; + + if (!isA_SCNetworkConnection(connection)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + if (PPPStatus(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &stats)) + return kSCNetworkConnectionDisconnected; // XXX + + status = __SCNetworkConnectionConvertStatus(stats->status); + + CFAllocatorDeallocate(NULL, stats); + return status; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ +CFDictionaryRef +SCNetworkConnectionCopyExtendedStatus (SCNetworkConnectionRef connection) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + CFPropertyListRef status = 0; + void *data = 0; + u_int32_t datalen; + + if (!isA_SCNetworkConnection(connection)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + if (PPPExtendedStatus(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &data, &datalen)) + goto fail; + + if (!data + || !(status = PPPUnserialize(data, datalen)) + || !isA_CFDictionary(status)) + goto fail; + + CFAllocatorDeallocate(NULL, data); + return status; + + fail: + + _SCErrorSet(kSCStatusFailed); + if (status) + CFRelease(status); + if (data) + CFAllocatorDeallocate(NULL, data); + return NULL; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +Boolean +SCNetworkConnectionStart (SCNetworkConnectionRef connection, + CFDictionaryRef userOptions, + Boolean linger) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + CFDataRef dataref = 0; + void *data = 0; + u_int32_t datalen = 0; + + if (!isA_SCNetworkConnection(connection)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + if (userOptions && !(dataref = PPPSerialize(userOptions, &data, &datalen))) + goto fail; + + if (PPPConnect(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, data, datalen, linger)) + goto fail; + + if (dataref) + CFRelease(dataref); + + /* connection is now started */ + return TRUE; + + fail: + + if (dataref) + CFRelease(dataref); + _SCErrorSet(kSCStatusFailed); // XXX + return FALSE; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +Boolean +SCNetworkConnectionStop (SCNetworkConnectionRef connection, + Boolean forceDisconnect) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + + if (!isA_SCNetworkConnection(connection)) { + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + + if (PPPDisconnect(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, forceDisconnect)) { + _SCErrorSet(kSCStatusFailed); + return FALSE; + } + + /* connection is now disconnecting */ + return TRUE; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +Boolean +SCNetworkConnectionSuspend (SCNetworkConnectionRef connection) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + + if (!isA_SCNetworkConnection(connection)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + if (PPPSuspend(connectionPrivate->controlRef, connectionPrivate->serviceID, 0)) { + _SCErrorSet(kSCStatusFailed); + return FALSE; + } + + /* connection is now suspended */ + return TRUE; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +Boolean +SCNetworkConnectionResume (SCNetworkConnectionRef connection) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + + if (!isA_SCNetworkConnection(connection)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + if (PPPResume(connectionPrivate->controlRef, connectionPrivate->serviceID, 0)) { + _SCErrorSet(kSCStatusFailed); + return FALSE; + } + + /* connection is now resume */ + return TRUE; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +CFDictionaryRef +SCNetworkConnectionCopyUserOptions (SCNetworkConnectionRef connection) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + void *data = 0; + u_int32_t datalen; + CFPropertyListRef userOptions = 0; + + if (!isA_SCNetworkConnection(connection)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + if (PPPGetConnectData(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &data, &datalen)) + goto fail; + + // no data were used, return an empty dictionary + if (data == 0) { + CFDictionaryRef dict; + + dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (dict == 0) + _SCErrorSet(kSCStatusFailed); // XXX + return dict; + } + + userOptions = PPPUnserialize(data, datalen); + if (!isA_CFDictionary(userOptions)) + goto fail; + + CFAllocatorDeallocate(NULL, data); + return userOptions; + + fail: + + _SCErrorSet(kSCStatusFailed); + if (userOptions) + CFRelease(userOptions); + if (data) + CFAllocatorDeallocate(NULL, data); + return NULL; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +static Boolean +__isScheduled(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList) +{ + CFIndex i; + CFIndex n = CFArrayGetCount(rlList); + + for (i = 0; i < n; i += 3) { + if (obj && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { + continue; + } + if (runLoop && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) { + continue; + } + if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) { + continue; + } + return TRUE; + } + + return FALSE; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ +static void +__schedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList) +{ + CFArrayAppendValue(rlList, obj); + CFArrayAppendValue(rlList, runLoop); + CFArrayAppendValue(rlList, runLoopMode); + + return; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ +static Boolean +__unschedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList, Boolean all) +{ + CFIndex i = 0; + Boolean found = FALSE; + CFIndex n = CFArrayGetCount(rlList); + + while (i < n) { + if (obj && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { + i += 3; + continue; + } + if (runLoop && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) { + i += 3; + continue; + } + if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) { + i += 3; + continue; + } + + found = TRUE; + + CFArrayRemoveValueAtIndex(rlList, i + 2); + CFArrayRemoveValueAtIndex(rlList, i + 1); + CFArrayRemoveValueAtIndex(rlList, i); + + if (!all) { + return found; + } + + n -= 3; + } + + return found; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +static void +__SCNetworkConnectionCallBack(CFSocketRef inref, + CFSocketCallBackType type, + CFDataRef address, + const void *data, + void *info) +{ + void *context_info; + void (*context_release)(const void *); + SCNetworkConnectionRef connection = (SCNetworkConnectionRef)info; + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + SCNetworkConnectionCallBack rlsFunction; + SCNetworkConnectionStatus status; + int pppstatus; + int err; + + err = PPPReadEvent(connectionPrivate->eventRef, &pppstatus); + if (err) + return; + + rlsFunction = connectionPrivate->rlsFunction; + if (connectionPrivate->rlsContext.retain && connectionPrivate->rlsContext.info) { + context_info = (void *)connectionPrivate->rlsContext.retain(connectionPrivate->rlsContext.info); + context_release = connectionPrivate->rlsContext.release; + } + else { + context_info = connectionPrivate->rlsContext.info; + context_release = NULL; + } + + status = __SCNetworkConnectionConvertStatus(pppstatus); + + (*rlsFunction)(connection, status, context_info); + if (context_release && context_info) { + context_release(context_info); + } +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +Boolean +SCNetworkConnectionScheduleWithRunLoop(SCNetworkConnectionRef connection, + CFRunLoopRef runLoop, + CFStringRef runLoopMode) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + //CFSocketRef ref; + + if (!isA_SCNetworkConnection(connection) || runLoop == NULL || runLoopMode == NULL) { + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + + if (connectionPrivate->rlsFunction == 0) { + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + + if (connectionPrivate->rlList + && __isScheduled(NULL, runLoop, runLoopMode, connectionPrivate->rlList)) { + /* already scheduled */ + _SCErrorSet(kSCStatusFailed); + return FALSE; + } + + if (connectionPrivate->eventRef == -1) { + CFSocketContext context = { 0, (void*)connection, CFRetain, CFRelease, CFCopyDescription }; + + if (PPPInit(&connectionPrivate->eventRef)) { + _SCErrorSet(kSCStatusFailed); + return FALSE; + } + + PPPEnableEvents(connectionPrivate->eventRef, connectionPrivate->serviceID, 0, 1); + + connectionPrivate->eventRefCF = CFSocketCreateWithNative(NULL, connectionPrivate->eventRef, + kCFSocketReadCallBack, __SCNetworkConnectionCallBack, &context); + connectionPrivate->rls = CFSocketCreateRunLoopSource(NULL, connectionPrivate->eventRefCF, 0); + connectionPrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + //CFRelease(ref); + } + + CFRunLoopAddSource(runLoop, connectionPrivate->rls, runLoopMode); + __schedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList); + + return TRUE; +} + +/* ------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- */ + +Boolean +SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef connection, + CFRunLoopRef runLoop, + CFStringRef runLoopMode) +{ + SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection; + + if (!isA_SCNetworkConnection(connection) || runLoop == NULL || runLoopMode == NULL) { + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + + if (connectionPrivate->rlList == NULL + || !__unschedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList, FALSE)) { + /* if not currently scheduled */ + _SCErrorSet(kSCStatusFailed); + return FALSE; + } + + CFRunLoopRemoveSource(runLoop, connectionPrivate->rls, runLoopMode); + + if (CFArrayGetCount(connectionPrivate->rlList) == 0) { + CFRelease(connectionPrivate->rls); + connectionPrivate->rls = NULL; + CFRelease(connectionPrivate->rlList); + connectionPrivate->rlList = NULL; + //PPPDispose(connectionPrivate->eventRef); + CFSocketInvalidate(connectionPrivate->eventRefCF); + CFRelease(connectionPrivate->eventRefCF); + connectionPrivate->eventRefCF = 0; + connectionPrivate->eventRef = -1; + } + + return TRUE; +} + + +//************************* USER LEVEL DIAL API ********************************** + + +#define k_NetworkConnect_Pref_File CFSTR("com.apple.networkConnect") +#define k_InterentConnect_Pref_File CFSTR("com.apple.internetconnect") + +#define k_Dial_Default_Key CFSTR("ConnectByDefault") // needs to go into SC +#define k_Last_Service_Id_Key CFSTR("ServiceID") +#define k_Unique_Id_Key CFSTR("UniqueIdentifier") + + +/* Private Prototypes */ +static Boolean SCNetworkConnectionPrivateCopyDefaultServiceIDForDial (SCDynamicStoreRef session, CFStringRef *serviceID); +static Boolean SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore (SCDynamicStoreRef session, CFStringRef *serviceID); +static Boolean SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptionsArray, CFDictionaryRef *userOptions); +static Boolean SCNetworkConnectionPrivateIsPPPService (SCDynamicStoreRef session, CFStringRef serviceID); +static void addPasswordFromKeychain(CFDictionaryRef *userOptions); +static CFArrayRef copyKeychainEnumerator(CFStringRef uniqueIdentifier); + +Boolean +SCNetworkConnectionCopyUserPreferences (CFDictionaryRef selectionOptions, + CFStringRef *serviceID, + CFDictionaryRef *userOptions) +{ + SCDynamicStoreRef session = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkConnection"), NULL, NULL); + Boolean success = FALSE; + + // NOTE: we are currently ignoring selectionOptions + + if (session != NULL) { + // (1) Figure out which service ID we care about, allocate it into passed "serviceID" + success = SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(session, serviceID); + + if (success && (*serviceID != NULL)) { + // (2) Get the list of user data for this service ID + CFPropertyListRef userServices = CFPreferencesCopyValue(*serviceID, + k_NetworkConnect_Pref_File, + kCFPreferencesCurrentUser, + kCFPreferencesCurrentHost); + + // (3) We are expecting an array if the user has defined records for this service ID or NULL if the user hasn't + if (userServices != NULL) { + if (isA_CFArray(userServices)) { + // (4) Get the default set of user options for this service + success = SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray( + (CFArrayRef)userServices, + userOptions); + if(success && userOptions != NULL) + { + addPasswordFromKeychain(userOptions); + } + } else { + fprintf(stderr, "Error, userServices are not of type CFArray!\n"); + } + + CFRelease(userServices); // this is OK because SCNetworkConnectionPrivateISExpectedCFType() checks for NULL + } + } + + CFRelease(session); + } else { + fprintf(stderr, "Error, SCNetworkConnectionCopyUserPreferences, SCDynamicStoreCreate() returned NULL!\n"); + } + + return success; +} + +//******************************************************************************************* +// SCNetworkConnectionPrivateCopyDefaultServiceIDForDial +// ---------------------------------------------------- +// Try to find the service id to connect +// (1) Start by looking at the last service used in Internet Connect +// (2) If Internet Connect has not been used, find the PPP service with the highest ordering +//******************************************************************************************** +static Boolean +SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session, CFStringRef *serviceID) +{ + Boolean foundService = FALSE; + CFPropertyListRef lastServiceSelectedInIC = NULL; + + // NULL out the pointer + *serviceID = NULL; + + // read out the last service from the Internet Connect preference file + lastServiceSelectedInIC = CFPreferencesCopyValue(k_Last_Service_Id_Key, + k_InterentConnect_Pref_File, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + + // we found the service the user last had open in IC + if (lastServiceSelectedInIC != NULL) { + // make sure its a PPP service + if (SCNetworkConnectionPrivateIsPPPService(session, lastServiceSelectedInIC)) { + // make sure the service that we found is valid + CFDictionaryRef dict; + CFStringRef key; + + key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + lastServiceSelectedInIC, + kSCEntNetInterface); + dict = SCDynamicStoreCopyValue(session, key); + CFRelease(key); + if (dict) { + *serviceID = CFRetain(lastServiceSelectedInIC); + foundService = TRUE; + CFRelease(dict); + } + } + CFRelease(lastServiceSelectedInIC); + } + + if (!foundService) { + foundService = SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(session, serviceID); + } + + return foundService; +} + +//******************************************************************************** +// SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore +// ------------------------------------------------------- +// Find the highest ordered PPP service in the dynamic store +//******************************************************************************** +static Boolean +SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef session, CFStringRef *serviceID) +{ + Boolean success = FALSE; + CFStringRef key = NULL; + CFDictionaryRef dict = NULL; + CFArrayRef serviceIDs = NULL; + + *serviceID = NULL; + + do { + CFIndex count; + CFIndex i; + + key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainSetup, kSCEntNetIPv4); + if (key == NULL) { + fprintf(stderr, "Error, Setup Key == NULL!\n"); + break; + } + + dict = SCDynamicStoreCopyValue(session, key); + if (dict == NULL) { + fprintf(stderr, "Error, Dictionary for setup key == NULL!\n"); + break; + } + + serviceIDs = CFDictionaryGetValue(dict, kSCPropNetServiceOrder); // array of service id's + if (isA_CFArray(serviceIDs) == NULL) { + if (serviceIDs == NULL) + fprintf(stderr, "Error, Array of service IDs == NULL!\n"); + else + fprintf(stderr, "Error, serviceIds are not of type CFArray!\n"); + break; + } + + count = CFArrayGetCount(serviceIDs); + for (i = 0; i < count; i++) { + CFStringRef service = CFArrayGetValueAtIndex(serviceIDs, i); + + if (SCNetworkConnectionPrivateIsPPPService(session, service)) { + *serviceID = CFRetain(service); + success = TRUE; + break; + } + } + } while (FALSE); + + if (key != NULL) + CFRelease(key); + + if (dict != NULL) + CFRelease(dict); + + return success; +} + +//******************************************************************************** +// SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray +// --------------------------------------------------------- +// Copy over user preferences for a particular service if they exist +//******************************************************************************** +static Boolean +SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptionsArray, CFDictionaryRef *userOptions) +{ + CFIndex count = CFArrayGetCount(userOptionsArray); + int i; + + *userOptions = NULL; + + for (i = 0; i < count; i++) { + // (1) Find the dictionary + CFPropertyListRef propertyList = CFArrayGetValueAtIndex(userOptionsArray, i); + + if (isA_CFDictionary(propertyList) != NULL) { + // See if there's a value for dial on demand + CFPropertyListRef value = CFDictionaryGetValue((CFDictionaryRef)propertyList, + k_Dial_Default_Key); + if (isA_CFBoolean(value) != NULL) { + if (CFBooleanGetValue(value)) { + // we found the default user options + *userOptions = CFDictionaryCreateCopy(NULL, + (CFDictionaryRef)propertyList); + break; + } + } + } + } + + return TRUE; +} + +//******************************************************************************** +// SCNetworkConnectionPrivateIsPPPService +// -------------------------------------- +// Check and see if the service is a PPP service +//******************************************************************************** +static Boolean +SCNetworkConnectionPrivateIsPPPService(SCDynamicStoreRef session, CFStringRef serviceID) +{ + CFStringRef entityKey; + Boolean isPPPService = FALSE; + Boolean isModemOrPPPoE = FALSE; + + entityKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + serviceID, + kSCEntNetInterface); + if (entityKey != NULL) { + CFDictionaryRef serviceDict; + + serviceDict = SCDynamicStoreCopyValue(session, entityKey); + if (serviceDict != NULL) { + if (isA_CFDictionary(serviceDict)) { + CFStringRef type; + CFStringRef subtype; + + type = CFDictionaryGetValue(serviceDict, kSCPropNetInterfaceType); + if (isA_CFString(type)) { + isPPPService = CFEqual(type, kSCValNetInterfaceTypePPP); + } + + subtype = CFDictionaryGetValue(serviceDict, kSCPropNetInterfaceSubType); + if (isA_CFString(subtype)) { + isModemOrPPPoE = (CFEqual(subtype, kSCValNetInterfaceSubTypePPPSerial) || + CFEqual(subtype, kSCValNetInterfaceSubTypePPPoE)); + } + } + CFRelease(serviceDict); + } + CFRelease(entityKey); + } + + return (isPPPService && isModemOrPPPoE); +} + +//******************************************************************************** +// addPasswordFromKeychain +// -------------------------------------- +// Get the password out of the keychain and add it to the PPP dictionary +//******************************************************************************** +static void +addPasswordFromKeychain(CFDictionaryRef *userOptions) +{ + CFArrayRef enumerator; + CFIndex n; + CFDictionaryRef oldDict; + CFPropertyListRef uniqueID = NULL; + + oldDict = *userOptions; + if(oldDict == NULL) { + return; // if no userOptions + } + + uniqueID = CFDictionaryGetValue(oldDict, k_Unique_Id_Key); + if(!isA_CFString(uniqueID)) { + return; // if no unique ID + } + + enumerator = copyKeychainEnumerator(uniqueID); + if(enumerator == NULL) { + return; // if no keychain enumerator + } + + + n = CFArrayGetCount(enumerator); + if (n > 0) { + void *data = NULL; + UInt32 dataLen = 0; + SecKeychainItemRef itemRef; + OSStatus result; + + itemRef = (SecKeychainItemRef)CFArrayGetValueAtIndex(enumerator, 0); + result = SecKeychainItemCopyContent(itemRef, // itemRef + NULL, // itemClass + NULL, // attrList + &dataLen, // length + (void *)&data); // outData + if(result == noErr && data != NULL && dataLen > 0) { + CFStringRef pass; + + pass = CFStringCreateWithBytes(NULL, data, dataLen, kCFStringEncodingUTF8, TRUE); + if (pass) { + CFMutableDictionaryRef newDict; + CFMutableDictionaryRef newPPP; + CFDictionaryRef pppDict; + + newDict = CFDictionaryCreateMutableCopy(NULL, 0, oldDict); + pppDict = CFDictionaryGetValue(newDict, kSCEntNetPPP); + if (isA_CFDictionary(pppDict)) { + newPPP = CFDictionaryCreateMutableCopy(NULL, 0, pppDict); + } else { + newPPP = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + + // set the PPP password + CFDictionarySetValue(newPPP, kSCPropNetPPPAuthPassword, pass); + CFRelease(pass); + + // update the PPP entity + CFDictionarySetValue(newDict, kSCEntNetPPP, newPPP); + CFRelease(newPPP); + + // update the userOptions dictionary + CFRelease(oldDict); + *userOptions = CFDictionaryCreateCopy(NULL, newDict); + CFRelease(newDict); + } + } + } + + CFRelease(enumerator); + return; +} + +//******************************************************************************** +// copyKeychainEnumerator +// -------------------------------------- +// Gather Keychain Enumerator +//******************************************************************************** +static CFArrayRef +copyKeychainEnumerator(CFStringRef uniqueIdentifier) +{ + char *buf = NULL; + CFMutableArrayRef itemArray = NULL; + OSStatus result; + SecKeychainSearchRef search = NULL; + + buf = _SC_cfstring_to_cstring(uniqueIdentifier, NULL, 0, kCFStringEncodingUTF8); + if (buf != NULL) { + // search for unique identifier in "svce" attribute + SecKeychainAttribute attributes[] = {{ kSecServiceItemAttr, + CFStringGetLength(uniqueIdentifier), + (void *)buf + }}; + + SecKeychainAttributeList attrList = { sizeof(attributes) / sizeof(*attributes), + attributes }; + + result = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attrList, &search); + if (result == noErr) { + itemArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + while (result == noErr) { + SecKeychainItemRef itemFound = NULL; + + result = SecKeychainSearchCopyNext(search, &itemFound); + if (result != noErr) { + break; + } + + if (itemFound) { + CFArrayAppendValue(itemArray, itemFound); + CFRelease(itemFound); + } + } + } + } + + if (search) CFRelease(search); + if (buf) CFAllocatorDeallocate(NULL, buf); + + return itemArray; +} diff --git a/SystemConfiguration.fproj/SCNetworkConnection.h b/SystemConfiguration.fproj/SCNetworkConnection.h new file mode 100644 index 0000000..53357bc --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkConnection.h @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCNETWORKCONNECTION_H +#define _SCNETWORKCONNECTION_H + +#include +#include +#include +#include +#include +#include + + +/*! + @header SCNetworkConnection + The SCNetworkConnectionXXX() APIs allow an application to + control connection oriented services defined in the system. + + This is a set of control APIs only. Using these APIs, an + application will be able to control existing services. + To create, change, or remove services, SCPreferences APIs + must be used. + + Note: Currently only PPP services can be controlled. + */ + + +/*! + @typedef SCNetworkConnectionRef + @discussion This is the handle to manage a connection oriented service. + */ +typedef const struct __SCNetworkConnection * SCNetworkConnectionRef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @typedef SCNetworkConnectionContext + */ +typedef struct { + CFIndex version; + void * info; + const void *(*retain)(const void *info); + void (*release)(const void *info); + CFStringRef (*copyDescription)(const void *info); +} SCNetworkConnectionContext AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + + +/*! + @enum SCNetworkConnectionStatus + @discussion Status of the network connection. + This status is intended to be generic and high level. + An extended status, specific to the type of network + connection is also available for applications that + need additonal information. + + @constant kSCNetworkConnectionInvalid + The network connection refers to an invalid service. + + @constant kSCNetworkConnectionDisconnected + The network connection is disconnected. + + @constant kSCNetworkConnectionConnecting + The network connection is connecting. + + @constant kSCNetworkConnectionConnected + The network connection is connected. + + @constant kSCNetworkConnectionDisconnecting + The network connection is disconnecting. + */ +enum { + kSCNetworkConnectionInvalid = -1, + kSCNetworkConnectionDisconnected = 0, + kSCNetworkConnectionConnecting = 1, + kSCNetworkConnectionConnected = 2, + kSCNetworkConnectionDisconnecting = 3 +}; +typedef int32_t SCNetworkConnectionStatus AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @enum SCNetworkConnectionPPPStatus + @discussion PPP specific status of the network connection. + This status is PPP specific and returned as part of the extended information + for a PPP service. + Note: additional status might be returned in the future, and the application should + be prepared to receive an unknown value. + + @constant kSCNetworkConnectionPPPDisconnected + PPP is disconnected. + + @constant kSCNetworkConnectionPPPInitializing + PPP is initializing. + + @constant kSCNetworkConnectionPPPConnectingLink + PPP is connecting the lower connection layer (for example, the modem is dialing out). + + @constant kSCNetworkConnectionPPPDialOnTraffic + PPP is waiting for networking traffic to automatically establish the connection. + + @constant kSCNetworkConnectionPPPNegotiatingLink + PPP lower layer is connected and PPP is negotiating the link layer (LCP protocol). + + @constant kSCNetworkConnectionPPPAuthenticating + PPP is authenticating to the server (PAP, CHAP, MS-CHAP or EAP protocols). + + @constant kSCNetworkConnectionPPPWaitingForCallBack + PPP is waiting for server to call back. + + @constant kSCNetworkConnectionPPPNegotiatingNetwork + PPP is now authenticated and negotiating the networking layer (IPCP or IPv6CP protocols) + + @constant kSCNetworkConnectionPPPConnected + PPP is now fully connected for at least one of the networking layer. + Additional networking protocol might still be negotiating. + + @constant kSCNetworkConnectionPPPTerminating + PPP networking and link protocols are terminating. + + @constant kSCNetworkConnectionPPPDisconnectingLink + PPP is disconnecting the lower level (for example, the modem is hanging up). + + @constant kSCNetworkConnectionPPPHoldingLinkOff + PPP is disconnected and maintaining the link temporarily off. + + @constant kSCNetworkConnectionPPPSuspended + PPP is suspended as a result of the suspend command (for example, when a V92 Modem is On Hold). + + @constant kSCNetworkConnectionPPPWaitingForRedial + PPP has found a busy server and is waiting for redial. + */ +enum { + kSCNetworkConnectionPPPDisconnected = 0, + kSCNetworkConnectionPPPInitializing = 1, + kSCNetworkConnectionPPPConnectingLink = 2, + kSCNetworkConnectionPPPDialOnTraffic = 3, + kSCNetworkConnectionPPPNegotiatingLink = 4, + kSCNetworkConnectionPPPAuthenticating = 5, + kSCNetworkConnectionPPPWaitingForCallBack = 6, + kSCNetworkConnectionPPPNegotiatingNetwork = 7, + kSCNetworkConnectionPPPConnected = 8, + kSCNetworkConnectionPPPTerminating = 9, + kSCNetworkConnectionPPPDisconnectingLink = 10, + kSCNetworkConnectionPPPHoldingLinkOff = 11, + kSCNetworkConnectionPPPSuspended = 12, + kSCNetworkConnectionPPPWaitingForRedial = 13 +}; +typedef int32_t SCNetworkConnectionPPPStatus AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @typedef SCNetworkConnectionCallBack + @discussion Type of the callback function used when a + status event is delivered. + @param status The connection status. + @param connection The connection reference. + @param info .... + */ +typedef void (*SCNetworkConnectionCallBack) ( + SCNetworkConnectionRef connection, + SCNetworkConnectionStatus status, + void *info + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + + +/* + Keys for the statistics dictionary +*/ + +#define kSCNetworkConnectionBytesIn CFSTR("BytesIn") /* CFNumber */ +#define kSCNetworkConnectionBytesOut CFSTR("BytesOut") /* CFNumber */ +#define kSCNetworkConnectionPacketsIn CFSTR("PacketsIn") /* CFNumber */ +#define kSCNetworkConnectionPacketsOut CFSTR("PacketsOut") /* CFNumber */ +#define kSCNetworkConnectionErrorsIn CFSTR("ErrorsIn") /* CFNumber */ +#define kSCNetworkConnectionErrorsOut CFSTR("ErrorsOut") /* CFNumber */ + + +__BEGIN_DECLS + +/*! + @function SCDynamicStoreGetTypeID + Returns the type identifier of all SCNetworkConnection instances. + */ +CF_EXPORT +CFTypeID SCNetworkConnectionGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionCopyUserPreferences + @discussion Provides the default serviceID and a userOptions dictionary for the connection. + Applications can use the serviceID and userOptions returned to open a connection on the fly. + @param selectionOptions Currently unimplemented. Pass NULL for this version. + @param serviceID Reference to the default serviceID for starting connections, + this value will be returned by the function. + @param userOptions Reference to default userOptions for starting connections, + this will be returned by the function. + @result TRUE if there is a valid service to dial. + FALSE if function was unable to retrieve a service to dial. + */ +Boolean SCNetworkConnectionCopyUserPreferences ( + CFDictionaryRef selectionOptions, + CFStringRef *serviceID, + CFDictionaryRef *userOptions + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionCreateWithServiceID + @discussion Creates a new connection reference to use for getting the status, + for connecting or for disconnecting the associated service. + @param allocator The CFAllocator which should be used to allocate + memory for the connection structure. + 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 serviceID A string that defines the service identifier + of the connection. Service identifiers uniquely identify + services in the system configuration database. + @param callout The function to be called when the status + of the connection changes. + If this parameter is NULL, the application will not receive + change of status notifications and will need to poll for updates. + @param context The SCNetworkConnectionContext associated with the callout. + @result A reference to the new SCNetworkConnection. + */ +SCNetworkConnectionRef +SCNetworkConnectionCreateWithServiceID ( + CFAllocatorRef allocator, + CFStringRef serviceID, + SCNetworkConnectionCallBack callout, + SCNetworkConnectionContext *context + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionCopyService + @discussion Returns the service ID associated with the SCNetworkConnection. + @param connection The SCNetworkConnection to obtained status from. + Returns the service ID associated with the SCNetworkConnection. + */ +CFStringRef +SCNetworkConnectionCopyServiceID ( + SCNetworkConnectionRef connection + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionGetStatus + @discussion Returns the status of the SCNetworkConnection. + A status is one of the following values : + kSCNetworkConnectionInvalid + kSCNetworkConnectionDisconnected + kSCNetworkConnectionConnecting + kSCNetworkConnectionDisconnecting + kSCNetworkConnectionConnected + + @param connection The SCNetworkConnection to obtain status from. + @result The status value. +*/ +SCNetworkConnectionStatus +SCNetworkConnectionGetStatus ( + SCNetworkConnectionRef connection + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionCopyExtendedStatus + @discussion Returns the extended status of the connection. + An extended status dictionary contains specific dictionaries + describing the status for each subcomponent of the service. + + For example, a status dictionary will contain the following dictionaries: + + IPv4: + IPaddress: IP address used. + + PPP: + Status: PPP specific status of type SCNetworkConnectionPPPStatus. + LastCause: Available when status is Disconnected. + Contains the last error of disconnection. + ConnectTime: time when the connection happened + MaxTime: maximum time for this connection + + Modem: + ConnectionSpeed: Speed of the modem connection in bits/s + + Other dictionaries could be present for PPPoE, PPTP and L2TP. + + The status dictionary can be extended as needed in the future + to contain additional information. + + @param connection The SCNetworkConnection to obtain status from. + @result The status dictionary. + If NULL is returned, the error can be retrieved with SCError(). + */ +CFDictionaryRef +SCNetworkConnectionCopyExtendedStatus ( + SCNetworkConnectionRef connection + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionCopyStatistics + @discussion Returns the statistics of the SCNetworkConnection. + A statistic dictionary contains specific dictionaries + with statistics for each subcomponents of the service. + + For example, a statistic dictionary will contain the following dictionaries: + + PPP: {Bytes,Packets,Errors}{In,Out}: + Statistics at the Network level. + Contains the number of bytes, packets, and errors on the PPP interface. + For example, BytesIn contains the number of bytes going up + into the network stack, for any networking protocol, + without the PPP headers and trailers. + + The statistic dictionary can be extended as needed in the future + to contain additional information. + + @param connection The SCNetworkConnection to obtained statistics from. + @result The statistics dictionary. + If NULL is returned, the error can be retrieved with SCError(). + */ +CFDictionaryRef +SCNetworkConnectionCopyStatistics ( + SCNetworkConnectionRef connection + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionStart + @discussion Start the connection for the SCNetworkConnection. + The connection process is asynchronous and the function will + return immediately. The connection status can be obtain by polling or + by callback. + The connection is done with the default settings from the administrator. + Some of the settings can be overridden for the duration of + the connection. They are given in an option dictionary. + The options dictionary is in the format of a Network Service + as described in SystemConfiguration. + + Note: Starting and stopping of connections is implicitely arbitrated. + Calling Start on a connection already started will indicate + that the application has interest in the connection and it shouldn't + be stopped by anyone else. + + @param connection The SCNetworkConnection to start. + @param userOptions The options dictionary to start the connection with. + If userOptions is NULL, the default settings will be used. + If userOptions are specified, they must be in the SystemConfiguration format. + The options will override the default settings defined for the service. + + For security reasons, not all the options can be overridden, the appropriate merging + of all the settings will be done before the connection is established, + and inappropriate options will be ignored. + + @param linger This parameter indicates whether or not the connection can stay around + when the application no longer has interest in it. + Typical application should pass FALSE, and the Stop function will + automatically be called when the reference is released or if the application quits. + If the application passes TRUE, the application can release the reference + or exit and the Stop function will not be called. + + @result TRUE if the connection was correctly started. The actual connection is not established yet, + and the connection status needs to be periodically checked. + FALSE if the connection request didn't start. Error must be taken + from SCError(). + */ +Boolean +SCNetworkConnectionStart ( + SCNetworkConnectionRef connection, + CFDictionaryRef userOptions, + Boolean linger + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionStop + @discussion Stop the connection for the SCNetworkConnection. + The disconnection process is asynchronous and the function will + return immediately. The connection status can be obtain by polling or + by callback. + This function performs an arbitrated stop of the connection. + If several applications have marked their interest in the connection, + by calling SCNetworkConnectionStart, the call will succeed but the the actual + connection will be maintained until the last interested application calls stop. + + In certain cases, you might want to stop the connection anyway, and + SCNetworkConnectionStop with forceDisconnect argument can be used. + + @param connection The SCNetworkConnection to stop. + @result TRUE if the disconnection request succeeded. + FALSE if the disconnection request failed. Error must be taken from SCError(). + */ +Boolean +SCNetworkConnectionStop ( + SCNetworkConnectionRef connection, + Boolean forceDisconnect + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionCopyCurrentOptions + @discussion Copy the user options used to start the connection. + This is a mechanism for a client to retrieve the user options + previously passed to the SCNetworkConnectionStart function. + @param connection The SCNetworkConnection to obtain options from. + @result The service dictionary containing the connection options. + The dictionary can be empty if no user options were used. + If NULL is returned, the error can be retrieved with SCError(). + */ +CFDictionaryRef +SCNetworkConnectionCopyUserOptions ( + SCNetworkConnectionRef connection + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionScheduleWithRunLoop + @discussion Schedule a connection with the Run Loop. + @param connection The SCNetworkConnection to schedule. + @param runLoop The runloop to schedule with. + @param runLoopMode The runloop mode. + @result TRUE if success. + FALSE if failed. The error can be retrieved with SCError(). + */ +Boolean +SCNetworkConnectionScheduleWithRunLoop ( + SCNetworkConnectionRef connection, + CFRunLoopRef runLoop, + CFStringRef runLoopMode + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkConnectionUnscheduleFromRunLoop + @discussion Unschedule a connection from the Run Loop. + @param connection The SCNetworkConnection to unschedule. + @param runLoop The runloop to unschedule from. + @param runLoopMode The runloop mode. + @result TRUE if success. + FALSE if failed. The error can be retrieved with SCError(). + */ +Boolean +SCNetworkConnectionUnscheduleFromRunLoop ( + SCNetworkConnectionRef connection, + CFRunLoopRef runLoop, + CFStringRef runLoopMode + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + +__END_DECLS + +#endif /* _SCNETWORKCONNECTION_H */ diff --git a/SystemConfiguration.fproj/SCNetworkReachability.c b/SystemConfiguration.fproj/SCNetworkReachability.c new file mode 100644 index 0000000..e5a1e51 --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkReachability.c @@ -0,0 +1,2580 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Modification History + * + * January 19, 2003 Allan Nathanson + * - add advanced reachability APIs + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define KERNEL_PRIVATE +#include +#undef KERNEL_PRIVATE + +#ifndef s6_addr16 +#define s6_addr16 __u6_addr.__u6_addr16 +#endif + +#include "ppp.h" + + +#define kSCNetworkFlagsFirstResolvePending (1<<31) + + +#define N_QUICK 32 + + +typedef enum { + reachabilityTypeAddress, + reachabilityTypeAddressPair, + reachabilityTypeName +} addressType; + + +static CFStringRef __SCNetworkReachabilityCopyDescription (CFTypeRef cf); +static void __SCNetworkReachabilityDeallocate (CFTypeRef cf); + + +typedef struct { + + /* base CFType information */ + CFRuntimeBase cfBase; + + /* lock */ + pthread_mutex_t lock; + + /* address type */ + addressType type; + + /* target host name */ + const char *name; + CFArrayRef resolvedAddress; /* CFArray[CFData] */ + int resolvedAddressError; + + /* local & remote addresses */ + struct sockaddr *localAddress; + struct sockaddr *remoteAddress; + + /* current reachability flags */ + SCNetworkConnectionFlags flags; + uint16_t if_index; + + /* run loop source, callout, context, rl scheduling info */ + CFRunLoopSourceRef rls; + SCNetworkReachabilityCallBack rlsFunction; + SCNetworkReachabilityContext rlsContext; + CFMutableArrayRef rlList; + + /* async DNS query info */ + CFMachPortRef dnsPort; + CFRunLoopSourceRef dnsRLS; + +} SCNetworkReachabilityPrivate, *SCNetworkReachabilityPrivateRef; + + +static CFTypeID __kSCNetworkReachabilityTypeID = _kCFRuntimeNotATypeID; + + +static const CFRuntimeClass __SCNetworkReachabilityClass = { + 0, // version + "SCNetworkReachability", // className + NULL, // init + NULL, // copy + __SCNetworkReachabilityDeallocate, // dealloc + NULL, // equal + NULL, // hash + NULL, // copyFormattingDesc + __SCNetworkReachabilityCopyDescription // copyDebugDesc +}; + + +static pthread_once_t initialized = PTHREAD_ONCE_INIT; +static Boolean needDNS = TRUE; + + +/* host "something has changed" notifications */ +static pthread_mutex_t hn_lock = PTHREAD_MUTEX_INITIALIZER; +static SCDynamicStoreRef hn_store = NULL; +static CFRunLoopSourceRef hn_storeRLS = NULL; +static CFMutableArrayRef hn_rlList = NULL; +static CFMutableSetRef hn_targets = NULL; + + +static __inline__ CFTypeRef +isA_SCNetworkReachability(CFTypeRef obj) +{ + return (isA_CFType(obj, SCNetworkReachabilityGetTypeID())); +} + + +static void +sockaddr_to_string(const struct sockaddr *address, char *buf, size_t bufLen) +{ + bzero(buf, bufLen); + switch (address->sa_family) { + case AF_INET : + (void)inet_ntop(((struct sockaddr_in *)address)->sin_family, + &((struct sockaddr_in *)address)->sin_addr, + buf, + bufLen); + break; + case AF_INET6 : { + (void)inet_ntop(((struct sockaddr_in6 *)address)->sin6_family, + &((struct sockaddr_in6 *)address)->sin6_addr, + buf, + bufLen); + if (((struct sockaddr_in6 *)address)->sin6_scope_id != 0) { + int n; + + n = strlen(buf); + if ((n+IF_NAMESIZE+1) <= (int)bufLen) { + buf[n++] = '%'; + if_indextoname(((struct sockaddr_in6 *)address)->sin6_scope_id, &buf[n]); + } + } + break; + } + case AF_LINK : + if (((struct sockaddr_dl *)address)->sdl_len < bufLen) { + bufLen = ((struct sockaddr_dl *)address)->sdl_len; + } else { + bufLen = bufLen - 1; + } + + bcopy(((struct sockaddr_dl *)address)->sdl_data, buf, bufLen); + break; + default : + snprintf(buf, bufLen, "unexpected address family %d", address->sa_family); + break; + } + + return; +} + + +#ifndef CHECK_IPV6_REACHABILITY +static char * +__netdb_error(int error) +{ + char *msg; + + switch(error) { + case NETDB_INTERNAL : + msg = strerror(errno); + break; + case HOST_NOT_FOUND : + msg = "Host not found."; + 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; + } + + return msg; +} +#endif /* CHECK_IPV6_REACHABILITY */ + + +static void +__signalRunLoop(CFTypeRef obj, CFRunLoopSourceRef rls, CFArrayRef rlList) +{ + CFRunLoopRef rl = NULL; + CFRunLoopRef rl1 = NULL; + CFIndex i; + CFIndex n = CFArrayGetCount(rlList); + + if (n == 0) { + return; + } + + /* get first runLoop for this object */ + for (i = 0; i < n; i += 3) { + if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { + continue; + } + + rl1 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1); + break; + } + + if (!rl1) { + /* if not scheduled */ + return; + } + + /* check if we have another runLoop for this object */ + rl = rl1; + for (i = i+3; i < n; i += 3) { + CFRunLoopRef rl2; + + if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { + continue; + } + + rl2 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1); + if (!CFEqual(rl1, rl2)) { + /* we've got more than one runLoop */ + rl = NULL; + break; + } + } + + if (rl) { + /* if we only have one runLoop */ + CFRunLoopWakeUp(rl); + return; + } + + /* more than one different runLoop, so we must pick one */ + for (i = 0; i < n; i+=3) { + CFStringRef rlMode; + + if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { + continue; + } + + rl = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1); + rlMode = CFRunLoopCopyCurrentMode(rl); + if (rlMode && CFRunLoopIsWaiting(rl) && CFRunLoopContainsSource(rl, rls, rlMode)) { + /* we've found a runLoop that's "ready" */ + CFRelease(rlMode); + CFRunLoopWakeUp(rl); + return; + } + if (rlMode) CFRelease(rlMode); + } + + /* didn't choose one above, so choose first */ + CFRunLoopWakeUp(rl1); + return; +} + + +static int +updatePPPStatus(SCDynamicStoreRef *storeP, + const struct sockaddr *sa, + const char *if_name, + SCNetworkConnectionFlags *flags) +{ + CFDictionaryRef dict = NULL; + CFStringRef entity; + CFIndex i; + const void * keys_q[N_QUICK]; + const void ** keys = keys_q; + CFIndex n; + CFStringRef ppp_if; + int sc_status = kSCStatusReachabilityUnknown; + SCDynamicStoreRef store = (storeP) ? *storeP : NULL; + const void * values_q[N_QUICK]; + const void ** values = values_q; + + switch (sa->sa_family) { + case AF_INET : + entity = kSCEntNetIPv4; + break; + case AF_INET6 : + entity = kSCEntNetIPv6; + break; + default : + goto done; + } + + if (!store) { + store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkReachability"), NULL, NULL); + if (!store) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + goto done; + } + } + + /* + * grab a snapshot of the PPP configuration from the dynamic store + */ + { + CFStringRef pattern; + CFMutableArrayRef patterns; + + patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainState, + kSCCompAnyRegex, + entity); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + kSCCompAnyRegex, + kSCEntNetPPP); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainState, + kSCCompAnyRegex, + kSCEntNetPPP); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + dict = SCDynamicStoreCopyMultiple(store, NULL, patterns); + CFRelease(patterns); + } + if (!dict) { + /* if we could not access the dynamic store */ + goto done; + } + + sc_status = kSCStatusOK; + + /* + * look for the service which matches the provided interface + */ + n = CFDictionaryGetCount(dict); + if (n <= 0) { + goto done; + } + + ppp_if = CFStringCreateWithCStringNoCopy(NULL, + if_name, + kCFStringEncodingASCII, + kCFAllocatorNull); + + if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { + keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); + values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); + } + CFDictionaryGetKeysAndValues(dict, keys, values); + + for (i=0; i < n; i++) { + CFArrayRef components; + CFStringRef key; + CFNumberRef num; + CFDictionaryRef p_setup; + CFDictionaryRef p_state; + int32_t ppp_status; + CFStringRef service = NULL; + CFStringRef s_key = (CFStringRef) keys[i]; + CFDictionaryRef s_dict = (CFDictionaryRef)values[i]; + CFStringRef s_if; + + if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) { + continue; + } + + if (!CFStringHasSuffix(s_key, entity)) { + continue; // if not an IPv4 or IPv6 entity + } + + s_if = CFDictionaryGetValue(s_dict, kSCPropInterfaceName); + if (!isA_CFString(s_if)) { + continue; // if no interface + } + + if (!CFEqual(ppp_if, s_if)) { + continue; // if not this interface + } + + /* + * extract service ID, get PPP "state" entity (for status), and get + * the "setup" entity (for dial-on-traffic flag) + */ + components = CFStringCreateArrayBySeparatingStrings(NULL, s_key, CFSTR("/")); + if (CFArrayGetCount(components) != 5) { + continue; + } + service = CFArrayGetValueAtIndex(components, 3); + key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainState, + service, + kSCEntNetPPP); + p_state = CFDictionaryGetValue(dict, key); + CFRelease(key); + key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + service, + kSCEntNetPPP); + p_setup = CFDictionaryGetValue(dict, key); + CFRelease(key); + CFRelease(components); + + // get PPP status + if (!isA_CFDictionary(p_state)) { + continue; + } + num = CFDictionaryGetValue(p_state, kSCPropNetPPPStatus); + if (!isA_CFNumber(num)) { + continue; + } + + if (!CFNumberGetValue(num, kCFNumberSInt32Type, &ppp_status)) { + continue; + } + switch (ppp_status) { + case PPP_RUNNING : + /* if we're really UP and RUNNING */ + break; + case PPP_ONHOLD : + /* if we're effectively UP and RUNNING */ + break; + case PPP_IDLE : + case PPP_STATERESERVED : + /* if we're not connected at all */ + SCLog(_sc_debug, LOG_INFO, CFSTR(" PPP link idle, dial-on-traffic to connect")); + *flags |= kSCNetworkFlagsConnectionRequired; + break; + default : + /* if we're in the process of [dis]connecting */ + SCLog(_sc_debug, LOG_INFO, CFSTR(" PPP link, connection in progress")); + *flags |= kSCNetworkFlagsConnectionRequired; + break; + } + + // check PPP dial-on-traffic status + if (isA_CFDictionary(p_setup)) { + num = CFDictionaryGetValue(p_setup, kSCPropNetPPPDialOnDemand); + if (isA_CFNumber(num)) { + int32_t ppp_demand; + + if (CFNumberGetValue(num, kCFNumberSInt32Type, &ppp_demand)) { + if (ppp_demand) { + *flags |= kSCNetworkFlagsConnectionAutomatic; + if (ppp_status == PPP_IDLE) { + *flags |= kSCNetworkFlagsInterventionRequired; + } + } + } + } + } + + break; + } + + CFRelease(ppp_if); + if (keys != keys_q) { + CFAllocatorDeallocate(NULL, keys); + CFAllocatorDeallocate(NULL, values); + } + + done : + + if (dict) CFRelease(dict); + if (storeP) *storeP = store; + return sc_status; +} + + +static int +updatePPPAvailable(SCDynamicStoreRef *storeP, + const struct sockaddr *sa, + SCNetworkConnectionFlags *flags) +{ + CFDictionaryRef dict = NULL; + CFStringRef entity; + CFIndex i; + const void * keys_q[N_QUICK]; + const void ** keys = keys_q; + CFIndex n; + int sc_status = kSCStatusReachabilityUnknown; + SCDynamicStoreRef store = (storeP) ? *storeP : NULL; + const void * values_q[N_QUICK]; + const void ** values = values_q; + + switch (sa->sa_family) { + case AF_INET : + entity = kSCEntNetIPv4; + break; + case AF_INET6 : + entity = kSCEntNetIPv6; + break; + default : + goto done; + } + + if (!store) { + store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkReachability"), NULL, NULL); + if (!store) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + goto done; + } + } + + /* + * grab a snapshot of the PPP configuration from the dynamic store + */ + { + CFStringRef pattern; + CFMutableArrayRef patterns; + + patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + kSCCompAnyRegex, + entity); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + kSCCompAnyRegex, + kSCEntNetPPP); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + dict = SCDynamicStoreCopyMultiple(store, NULL, patterns); + CFRelease(patterns); + } + if (!dict) { + /* if we could not access the dynamic store */ + goto done; + } + + sc_status = kSCStatusOK; + + /* + * look for an available service which will provide connectivity + * for the requested address family. + */ + n = CFDictionaryGetCount(dict); + if (n <= 0) { + goto done; + } + + if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { + keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); + values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); + } + CFDictionaryGetKeysAndValues(dict, keys, values); + + for (i = 0; i < n; i++) { + CFArrayRef components; + Boolean found = FALSE; + CFStringRef p_key; + CFDictionaryRef p_dict; + CFStringRef service; + CFStringRef s_key = (CFStringRef) keys[i]; + CFDictionaryRef s_dict = (CFDictionaryRef)values[i]; + + if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) { + continue; + } + + if (!CFStringHasSuffix(s_key, entity)) { + continue; // if not an IPv4 or IPv6 entity + } + + // extract service ID + components = CFStringCreateArrayBySeparatingStrings(NULL, s_key, CFSTR("/")); + if (CFArrayGetCount(components) != 5) { + continue; + } + service = CFArrayGetValueAtIndex(components, 3); + + // check for PPP entity + p_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainSetup, + service, + kSCEntNetPPP); + p_dict = CFDictionaryGetValue(dict, p_key); + CFRelease(p_key); + + if (isA_CFDictionary(p_dict)) { + CFNumberRef num; + + /* + * we have a PPP service for this address family + */ + found = TRUE; + + *flags |= kSCNetworkFlagsReachable; + *flags |= kSCNetworkFlagsTransientConnection; + *flags |= kSCNetworkFlagsConnectionRequired; + + /* + * get PPP dial-on-traffic status + */ + num = CFDictionaryGetValue(p_dict, kSCPropNetPPPDialOnDemand); + if (isA_CFNumber(num)) { + int32_t ppp_demand; + + if (CFNumberGetValue(num, kCFNumberSInt32Type, &ppp_demand)) { + if (ppp_demand) { + *flags |= kSCNetworkFlagsConnectionAutomatic; + } + } + } + + if (_sc_debug) { + SCLog(TRUE, LOG_INFO, CFSTR(" status = isReachable (after connect)")); + SCLog(TRUE, LOG_INFO, CFSTR(" service = %@"), service); + } + + } + + CFRelease(components); + + if (found) { + break; + } + } + + if (keys != keys_q) { + CFAllocatorDeallocate(NULL, keys); + CFAllocatorDeallocate(NULL, values); + } + + done : + + if (dict) CFRelease(dict); + if (storeP) *storeP = store; + return sc_status; +} + + +#define ROUNDUP(a, size) \ + (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) + +#define NEXT_SA(ap) (ap) = (struct sockaddr *) \ + ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ + sizeof(u_long)) :\ + sizeof(u_long))) + +static void +get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) +{ + int i; + + for (i = 0; i < RTAX_MAX; i++) { + if (addrs & (1 << i)) { + rti_info[i] = sa; + NEXT_SA(sa); + } else + rti_info[i] = NULL; + } +} + + +#define BUFLEN (sizeof(struct rt_msghdr) + 512) /* 8 * sizeof(struct sockaddr_in6) = 192 */ + +static Boolean +checkAddress(SCDynamicStoreRef *storeP, + const struct sockaddr *address, + SCNetworkConnectionFlags *flags, + uint16_t *if_index) +{ + char buf[BUFLEN]; + struct ifreq ifr; + char if_name[IFNAMSIZ+1]; + int isock; + int n; + pid_t pid = getpid(); + int rsock; + struct sockaddr *rti_info[RTAX_MAX]; + struct rt_msghdr *rtm; + struct sockaddr *sa; + int sc_status = kSCStatusReachabilityUnknown; + struct sockaddr_dl *sdl; + int seq = (int)pthread_self(); + SCDynamicStoreRef store = (storeP) ? *storeP : NULL; + char *statusMessage = NULL; +#ifndef RTM_GET_SILENT +#warning Note: Using RTM_GET (and not RTM_GET_SILENT) + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + int sosize = 48 * 1024; +#endif + + if (!address || !flags) { + sc_status = kSCStatusInvalidArgument; + goto done; + } + + switch (address->sa_family) { + case AF_INET : + case AF_INET6 : + if (_sc_debug) { + sockaddr_to_string(address, buf, sizeof(buf)); + SCLog(TRUE, LOG_INFO, CFSTR("checkAddress(%s)"), buf); + } + break; + default : + /* + * if no code for this address family (yet) + */ + SCLog(_sc_verbose, LOG_ERR, + CFSTR("checkAddress(): unexpected address family %d"), + address->sa_family); + sc_status = kSCStatusInvalidArgument; + goto done; + } + + *flags = 0; + if (if_index) { + *if_index = 0; + } + + if ((address->sa_family == AF_INET) && (((struct sockaddr_in *)address)->sin_addr.s_addr == 0)) { + /* special case: check for available paths off the system */ + goto checkAvailable; + } + + bzero(&buf, sizeof(buf)); + + rtm = (struct rt_msghdr *)&buf; + rtm->rtm_msglen = sizeof(struct rt_msghdr); + rtm->rtm_version = RTM_VERSION; +#ifdef RTM_GET_SILENT + rtm->rtm_type = RTM_GET_SILENT; +#else + rtm->rtm_type = RTM_GET; +#endif + rtm->rtm_flags = RTF_STATIC|RTF_UP|RTF_HOST|RTF_GATEWAY; + rtm->rtm_addrs = RTA_DST|RTA_IFP; /* Both destination and device */ + rtm->rtm_pid = pid; + rtm->rtm_seq = seq; + + switch (address->sa_family) { + case AF_INET6: { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)address; + if ((IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || + IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) && + (sin6->sin6_scope_id != 0)) { + sin6->sin6_addr.s6_addr16[1] = htons(sin6->sin6_scope_id); + sin6->sin6_scope_id = 0; + } + break; + } + } + + sa = (struct sockaddr *) (rtm + 1); + bcopy(address, sa, address->sa_len); + n = ROUNDUP(sa->sa_len, sizeof(u_long)); + rtm->rtm_msglen += n; + + sdl = (struct sockaddr_dl *) ((void *)sa + n); + sdl->sdl_family = AF_LINK; + sdl->sdl_len = sizeof (struct sockaddr_dl); + n = ROUNDUP(sdl->sdl_len, sizeof(u_long)); + rtm->rtm_msglen += n; + +#ifndef RTM_GET_SILENT + pthread_mutex_lock(&lock); +#endif + rsock = socket(PF_ROUTE, SOCK_RAW, 0); + if (rsock == -1) { +#ifndef RTM_GET_SILENT + pthread_mutex_unlock(&lock); +#endif + SCLog(TRUE, LOG_ERR, CFSTR("socket(PF_ROUTE) failed: %s"), strerror(errno)); + sc_status = kSCStatusFailed; + goto done; + } + +#ifndef RTM_GET_SILENT + if (setsockopt(rsock, SOL_SOCKET, SO_RCVBUF, &sosize, sizeof(sosize)) == -1) { + (void)close(rsock); + pthread_mutex_unlock(&lock); + SCLog(TRUE, LOG_ERR, CFSTR("setsockopt(SO_RCVBUF) failed: %s"), strerror(errno)); + sc_status = kSCStatusFailed; + goto done; + } +#endif + + if (write(rsock, &buf, rtm->rtm_msglen) == -1) { + int err = errno; + + (void)close(rsock); +#ifndef RTM_GET_SILENT + pthread_mutex_unlock(&lock); +#endif + if (err != ESRCH) { + SCLog(TRUE, LOG_ERR, CFSTR("write() failed: %s"), strerror(err)); + goto done; + } + goto checkAvailable; + } + + /* + * Type, seq, pid identify our response. + * Routing sockets are broadcasters on input. + */ + do { + int n; + + n = read(rsock, (void *)&buf, sizeof(buf)); + if (n == -1) { + int err = errno; + + if (err != EINTR) { + (void)close(rsock); + SCLog(TRUE, LOG_ERR, CFSTR("read() failed: %s"), strerror(err)); +#ifndef RTM_GET_SILENT + pthread_mutex_unlock(&lock); +#endif + goto done; + } + } + } while (rtm->rtm_type != RTM_GET || + rtm->rtm_seq != seq || + rtm->rtm_pid != pid); + + (void)close(rsock); +#ifndef RTM_GET_SILENT + pthread_mutex_unlock(&lock); +#endif + + get_rtaddrs(rtm->rtm_addrs, sa, rti_info); + +#ifdef DEBUG +{ + int i; + char buf[200]; + + SCLog(_sc_debug, LOG_DEBUG, CFSTR("rtm_flags = 0x%8.8x"), rtm->rtm_flags); + + for (i = 0; i < RTAX_MAX; i++) { + if (rti_info[i] != NULL) { + sockaddr_to_string(rti_info[i], buf, sizeof(buf)); + SCLog(_sc_debug, LOG_DEBUG, CFSTR("%d: %s"), i, buf); + } + } +} +#endif /* DEBUG */ + + if ((rti_info[RTAX_IFP] == NULL) || + (rti_info[RTAX_IFP]->sa_family != AF_LINK)) { + /* no interface info */ + goto done; // ??? + } + + sdl = (struct sockaddr_dl *) rti_info[RTAX_IFP]; + if ((sdl->sdl_nlen == 0) || (sdl->sdl_nlen > IFNAMSIZ)) { + /* no interface name */ + goto done; // ??? + } + + /* get the interface flags */ + + bzero(&ifr, sizeof(ifr)); + bcopy(sdl->sdl_data, ifr.ifr_name, sdl->sdl_len); + + isock = socket(AF_INET, SOCK_DGRAM, 0); + if (isock < 0) { + SCLog(TRUE, LOG_NOTICE, CFSTR("socket() failed: %s"), strerror(errno)); + goto done; + } + + if (ioctl(isock, SIOCGIFFLAGS, (char *)&ifr) < 0) { + SCLog(TRUE, LOG_NOTICE, CFSTR("ioctl() failed: %s"), strerror(errno)); + (void)close(isock); + goto done; + } + (void)close(isock); + + if (!(ifr.ifr_flags & IFF_UP)) { + goto checkAvailable; + } + + statusMessage = "isReachable"; + *flags |= kSCNetworkFlagsReachable; + + if (rtm->rtm_flags & RTF_LOCAL) { + statusMessage = "isReachable (is a local address)"; + *flags |= kSCNetworkFlagsIsLocalAddress; + } else if (ifr.ifr_flags & IFF_LOOPBACK) { + statusMessage = "isReachable (is loopback network)"; + *flags |= kSCNetworkFlagsIsLocalAddress; + } else if (rti_info[RTAX_IFA]) { + void *addr1 = (void *)address; + void *addr2 = (void *)rti_info[RTAX_IFA]; + size_t len = address->sa_len; + + if ((address->sa_family != rti_info[RTAX_IFA]->sa_family) && + (address->sa_len != rti_info[RTAX_IFA]->sa_len)) { + SCLog(TRUE, LOG_NOTICE, + CFSTR("address family/length mismatch: %d/%d != %d/%d"), + address->sa_family, + address->sa_len, + rti_info[RTAX_IFA]->sa_family, + rti_info[RTAX_IFA]->sa_len); + goto done; + } + + switch (address->sa_family) { + case AF_INET : + addr1 = &((struct sockaddr_in *)address)->sin_addr; + addr2 = &((struct sockaddr_in *)rti_info[RTAX_IFA])->sin_addr; + len = sizeof(struct in_addr); + break; + case AF_INET6 : + addr1 = &((struct sockaddr_in6 *)address)->sin6_addr; + addr2 = &((struct sockaddr_in6 *)rti_info[RTAX_IFA])->sin6_addr; + len = sizeof(struct in6_addr); + break; + default : + break; + } + + if (memcmp(addr1, addr2, len) == 0) { + statusMessage = "isReachable (is interface address)"; + *flags |= kSCNetworkFlagsIsLocalAddress; + } + } + + if (rti_info[RTAX_GATEWAY] && (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)) { + *flags |= kSCNetworkFlagsIsDirect; + } + + bzero(&if_name, sizeof(if_name)); + bcopy(sdl->sdl_data, + if_name, + (sdl->sdl_len <= IFNAMSIZ) ? sdl->sdl_len : IFNAMSIZ); + + if (if_index) { + *if_index = sdl->sdl_index; + } + + if (_sc_debug) { + SCLog(TRUE, LOG_INFO, CFSTR(" status = %s"), statusMessage); + SCLog(TRUE, LOG_INFO, CFSTR(" device = %s (%hu)"), if_name, sdl->sdl_index); + SCLog(TRUE, LOG_INFO, CFSTR(" ifr_flags = 0x%04hx"), ifr.ifr_flags); + SCLog(TRUE, LOG_INFO, CFSTR(" rtm_flags = 0x%08x"), rtm->rtm_flags); + } + + sc_status = kSCStatusOK; + + if (ifr.ifr_flags & IFF_POINTOPOINT) { + /* + * We have an interface which "claims" to be a valid path + * off of the system. + */ + *flags |= kSCNetworkFlagsTransientConnection; + + /* + * Check if this is a dial-on-demand PPP link that isn't + * connected yet. + */ + sc_status = updatePPPStatus(&store, address, if_name, flags); + } + + goto done; + + checkAvailable : + + sc_status = updatePPPAvailable(&store, address, flags); + + done : + + if (*flags == 0) { + SCLog(_sc_debug, LOG_INFO, CFSTR(" cannot be reached")); + } + + if (storeP) *storeP = store; + if (sc_status != kSCStatusOK) { + _SCErrorSet(sc_status); + return FALSE; + } + + return TRUE; +} + + +static Boolean +checkAddressZero(SCDynamicStoreRef *storeP, + SCNetworkConnectionFlags *flags, + uint16_t *if_index) +{ + Boolean ok; + struct sockaddr_in sin; + + bzero(&sin, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = 0; + + ok = checkAddress(storeP, (struct sockaddr *)&sin, flags, if_index); + + return ok; +} + + +static Boolean +isAddressZero(struct sockaddr *sa, SCNetworkConnectionFlags *flags) +{ + /* + * Check if 0.0.0.0 + */ + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + + if (sin->sin_addr.s_addr == 0) { + SCLog(_sc_debug, LOG_INFO, CFSTR("isAddressZero(0.0.0.0)")); + SCLog(_sc_debug, LOG_INFO, CFSTR(" status = isReachable (this host)")); + *flags |= kSCNetworkFlagsReachable; + *flags |= kSCNetworkFlagsIsLocalAddress; + return TRUE; + } + } + + return FALSE; +} + + +static CFStringRef +__SCNetworkReachabilityCopyDescription(CFTypeRef cf) +{ + CFAllocatorRef allocator = CFGetAllocator(cf); + CFMutableStringRef result; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)cf; + + result = CFStringCreateMutable(allocator, 0); + CFStringAppendFormat(result, NULL, CFSTR(" { "), cf, allocator); + switch (targetPrivate->type) { + case reachabilityTypeAddress : + case reachabilityTypeAddressPair : { + char buf[64]; + + if (targetPrivate->localAddress) { + sockaddr_to_string(targetPrivate->localAddress, buf, sizeof(buf)); + CFStringAppendFormat(result, NULL, CFSTR("local address=%s"), + buf); + } + + if (targetPrivate->remoteAddress) { + sockaddr_to_string(targetPrivate->remoteAddress, buf, sizeof(buf)); + CFStringAppendFormat(result, NULL, CFSTR("%s%saddress=%s"), + targetPrivate->localAddress ? ", " : "", + (targetPrivate->type == reachabilityTypeAddressPair) ? "remote " : "", + buf); + } + break; + } + case reachabilityTypeName : { + CFStringAppendFormat(result, NULL, CFSTR("name=%s"), targetPrivate->name); + if (targetPrivate->resolvedAddress || (targetPrivate->resolvedAddressError != NETDB_SUCCESS)) { + if (targetPrivate->resolvedAddress) { + if (isA_CFArray(targetPrivate->resolvedAddress)) { + CFIndex i; + CFIndex n = CFArrayGetCount(targetPrivate->resolvedAddress); + + CFStringAppendFormat(result, NULL, CFSTR(" (")); + for (i = 0; i < n; i++) { + CFDataRef address; + char buf[64]; + struct sockaddr *sa; + + address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddress, i); + sa = (struct sockaddr *)CFDataGetBytePtr(address); + sockaddr_to_string(sa, buf, sizeof(buf)); + CFStringAppendFormat(result, NULL, CFSTR("%s%s"), + i > 0 ? ", " : "", + buf); + } + CFStringAppendFormat(result, NULL, CFSTR(")")); + } else { + CFStringAppendFormat(result, NULL, CFSTR(" (no addresses)")); + } + } else { +#ifdef CHECK_IPV6_REACHABILITY + CFStringAppendFormat(result, NULL, CFSTR(" (%s)"), + gai_strerror(targetPrivate->resolvedAddressError)); +#else /* CHECK_IPV6_REACHABILITY */ + CFStringAppendFormat(result, NULL, CFSTR(" (%s)"), + __netdb_error(targetPrivate->resolvedAddressError)); +#endif /* CHECK_IPV6_REACHABILITY */ + } + } else if (targetPrivate->dnsPort) { + CFStringAppendFormat(result, NULL, CFSTR(" (DNS query active)")); + } + break; + } + } + if (targetPrivate->rls) { + CFStringAppendFormat(result, + NULL, + CFSTR(", flags=%8.8x, if_index=%hu"), + targetPrivate->flags, + targetPrivate->if_index); + } + CFStringAppendFormat(result, NULL, CFSTR(" }")); + + return result; +} + + +static void +__SCNetworkReachabilityDeallocate(CFTypeRef cf) +{ + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)cf; + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkReachabilityDeallocate:")); + + /* release resources */ + + pthread_mutex_destroy(&targetPrivate->lock); + + if (targetPrivate->name) + CFAllocatorDeallocate(NULL, (void *)targetPrivate->name); + + if (targetPrivate->resolvedAddress) + CFRelease(targetPrivate->resolvedAddress); + + if (targetPrivate->localAddress) + CFAllocatorDeallocate(NULL, (void *)targetPrivate->localAddress); + + if (targetPrivate->remoteAddress) + CFAllocatorDeallocate(NULL, (void *)targetPrivate->remoteAddress); + + if (targetPrivate->rlsContext.release) { + targetPrivate->rlsContext.release(targetPrivate->rlsContext.info); + } + + return; +} + + +static void +__SCNetworkReachabilityInitialize(void) +{ + __kSCNetworkReachabilityTypeID = _CFRuntimeRegisterClass(&__SCNetworkReachabilityClass); + return; +} + + +static SCNetworkReachabilityPrivateRef +__SCNetworkReachabilityCreatePrivate(CFAllocatorRef allocator) +{ + SCNetworkReachabilityPrivateRef targetPrivate; + uint32_t size; + + /* initialize runtime */ + pthread_once(&initialized, __SCNetworkReachabilityInitialize); + + SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkReachabilityCreatePrivate:")); + + /* allocate target */ + size = sizeof(SCNetworkReachabilityPrivate) - sizeof(CFRuntimeBase); + targetPrivate = (SCNetworkReachabilityPrivateRef)_CFRuntimeCreateInstance(allocator, + __kSCNetworkReachabilityTypeID, + size, + NULL); + if (!targetPrivate) { + return NULL; + } + + pthread_mutex_init(&targetPrivate->lock, NULL); + + targetPrivate->name = NULL; + + targetPrivate->resolvedAddress = NULL; + targetPrivate->resolvedAddressError = NETDB_SUCCESS; + + targetPrivate->localAddress = NULL; + targetPrivate->remoteAddress = NULL; + + targetPrivate->flags = 0; + targetPrivate->if_index = 0; + + targetPrivate->rls = NULL; + targetPrivate->rlsFunction = NULL; + targetPrivate->rlsContext.info = NULL; + targetPrivate->rlsContext.retain = NULL; + targetPrivate->rlsContext.release = NULL; + targetPrivate->rlsContext.copyDescription = NULL; + targetPrivate->rlList = NULL; + + targetPrivate->dnsPort = NULL; + targetPrivate->dnsRLS = NULL; + + return targetPrivate; +} + + +SCNetworkReachabilityRef +SCNetworkReachabilityCreateWithAddress(CFAllocatorRef allocator, + const struct sockaddr *address) +{ + SCNetworkReachabilityPrivateRef targetPrivate; + + if (!address || + (address->sa_len == 0) || + (address->sa_len > sizeof(struct sockaddr_storage))) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator); + if (!targetPrivate) { + return NULL; + } + + targetPrivate->type = reachabilityTypeAddress; + targetPrivate->remoteAddress = CFAllocatorAllocate(NULL, address->sa_len, 0); + bcopy(address, targetPrivate->remoteAddress, address->sa_len); + + return (SCNetworkReachabilityRef)targetPrivate; +} + + +SCNetworkReachabilityRef +SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef allocator, + const struct sockaddr *localAddress, + const struct sockaddr *remoteAddress) +{ + SCNetworkReachabilityPrivateRef targetPrivate; + + if ((localAddress == NULL) && (remoteAddress == NULL)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + if (localAddress) { + if ((localAddress->sa_len == 0) || + (localAddress->sa_len > sizeof(struct sockaddr_storage))) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + } + + if (remoteAddress) { + if ((remoteAddress->sa_len == 0) || + (remoteAddress->sa_len > sizeof(struct sockaddr_storage))) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + } + + targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator); + if (!targetPrivate) { + return NULL; + } + + targetPrivate->type = reachabilityTypeAddressPair; + + if (localAddress) { + targetPrivate->localAddress = CFAllocatorAllocate(NULL, localAddress->sa_len, 0); + bcopy(localAddress, targetPrivate->localAddress, localAddress->sa_len); + } + + if (remoteAddress) { + targetPrivate->remoteAddress = CFAllocatorAllocate(NULL, remoteAddress->sa_len, 0); + bcopy(remoteAddress, targetPrivate->remoteAddress, remoteAddress->sa_len); + } + + return (SCNetworkReachabilityRef)targetPrivate; +} + + +SCNetworkReachabilityRef +SCNetworkReachabilityCreateWithName(CFAllocatorRef allocator, + const char *nodename) +{ + SCNetworkReachabilityPrivateRef targetPrivate; + + if (!nodename) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator); + if (!targetPrivate) { + return NULL; + } + + targetPrivate->type = reachabilityTypeName; + + targetPrivate->flags |= kSCNetworkFlagsFirstResolvePending; + + targetPrivate->name = CFAllocatorAllocate(NULL, strlen(nodename) + 1, 0); + strcpy((char *)targetPrivate->name, nodename); + + return (SCNetworkReachabilityRef)targetPrivate; +} + + +CFTypeID +SCNetworkReachabilityGetTypeID(void) +{ + pthread_once(&initialized, __SCNetworkReachabilityInitialize); /* initialize runtime */ + return __kSCNetworkReachabilityTypeID; +} + + +CFArrayRef +SCNetworkReachabilityCopyResolvedAddress(SCNetworkReachabilityRef target, + int *error_num) +{ + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + if (!isA_SCNetworkReachability(target)) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + if (targetPrivate->type != reachabilityTypeName) { + _SCErrorSet(kSCStatusInvalidArgument); + return NULL; + } + + if (error_num) { + *error_num = targetPrivate->resolvedAddressError; + } + + if (targetPrivate->resolvedAddress || (targetPrivate->resolvedAddressError != NETDB_SUCCESS)) { + if (targetPrivate->resolvedAddress) { + return CFRetain(targetPrivate->resolvedAddress); + } else { + /* if status is known but no resolved addresses to return */ + _SCErrorSet(kSCStatusOK); + return NULL; + } + } + + _SCErrorSet(kSCStatusReachabilityUnknown); + return NULL; +} + + +static void +__SCNetworkReachabilitySetResolvedAddress(SCNetworkReachabilityRef target, + CFArrayRef addresses, + int error_num) +{ + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + if (targetPrivate->resolvedAddress) { + CFRelease(targetPrivate->resolvedAddress); + } + targetPrivate->resolvedAddress = addresses ? CFRetain(addresses) : NULL; + targetPrivate->resolvedAddressError = error_num; + return; +} + + +#ifdef CHECK_IPV6_REACHABILITY +static void +__SCNetworkReachabilityCallbackSetResolvedAddress(int32_t status, struct addrinfo *res, void *context) +{ + Boolean ok; + struct addrinfo *resP; + SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)context; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + ok = (status == 0) && (res != NULL); + + SCLog(_sc_debug, LOG_DEBUG, + CFSTR("process async DNS complete%s"), + ok ? "" : ", host not found"); + + if (ok) { + CFMutableArrayRef addresses; + + addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + for (resP = res; resP; resP = resP->ai_next) { + CFDataRef newAddress; + + newAddress = CFDataCreate(NULL, (void *)resP->ai_addr, resP->ai_addr->sa_len); + CFArrayAppendValue(addresses, newAddress); + CFRelease(newAddress); + } + + /* save the resolved address[es] */ + __SCNetworkReachabilitySetResolvedAddress(target, addresses, NETDB_SUCCESS); + CFRelease(addresses); + } else { + SCLog(_sc_debug, LOG_INFO, CFSTR("getaddrinfo() failed: %s"), gai_strerror(status)); + + /* save the error associated with the attempt to resolve the name */ + __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, status); + } + + if (res) freeaddrinfo(res); + + if (targetPrivate->rls) { + SCLog(_sc_debug, LOG_INFO, CFSTR("DNS request completed")); + CFRunLoopSourceSignal(targetPrivate->rls); + __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList); + } + + return; +} +#else /* CHECK_IPV6_REACHABILITY */ +static void +__SCNetworkReachabilityCallbackSetResolvedAddress(struct hostent *h, int error, void *context) +{ + SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)context; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + SCLog(_sc_debug, LOG_DEBUG, + CFSTR("process async DNS complete%s"), + (h == NULL) ? ", host not found" : ""); + + if (h && h->h_length) { + CFMutableArrayRef addresses; + union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_storage ss; + } addr; + char **ha = h->h_addr_list; + + addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + bzero(&addr, sizeof(addr)); + + while (*ha) { + CFDataRef newAddress; + + switch (h->h_length) { + case sizeof(struct in_addr) : + addr.sin.sin_family = AF_INET; + addr.sin.sin_len = sizeof(struct sockaddr_in); + bcopy(*ha, &addr.sin.sin_addr, h->h_length); + break; + case sizeof(struct in6_addr) : + addr.sin6.sin6_family = AF_INET6; + addr.sin6.sin6_len = sizeof(struct sockaddr_in6); + bcopy(*ha, &addr.sin6.sin6_addr, h->h_length); + break; + } + + newAddress = CFDataCreate(NULL, (void *)&addr, addr.sa.sa_len); + CFArrayAppendValue(addresses, newAddress); + CFRelease(newAddress); + + ha++; + } + + /* save the resolved address[es] */ + __SCNetworkReachabilitySetResolvedAddress(target, addresses, NETDB_SUCCESS); + CFRelease(addresses); + } else { + SCLog(_sc_debug, LOG_INFO, CFSTR("getipnodebyname() failed: %s"), __netdb_error(error)); + + /* save the error associated with the attempt to resolve the name */ + __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, error); + } + + if (h) freehostent(h); + + if (targetPrivate->rls) { + SCLog(_sc_debug, LOG_INFO, CFSTR("DNS request completed")); + CFRunLoopSourceSignal(targetPrivate->rls); + __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList); + } + + return; +} +#endif /* CHECK_IPV6_REACHABILITY */ + + +/* + * rankReachability() + * Not reachable == 0 + * Connection Required == 1 + * Reachable == 2 + */ +static int +rankReachability(SCNetworkConnectionFlags flags) +{ + int rank = 0; + + if (flags & kSCNetworkFlagsReachable) rank = 2; + if (flags & kSCNetworkFlagsConnectionRequired) rank = 1; + return rank; +} + + +#ifdef CHECK_IPV6_REACHABILITY +static void +getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info) +{ + SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)info; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + pthread_mutex_lock(&targetPrivate->lock); + + getaddrinfo_async_handle_reply(msg); + + if (port == targetPrivate->dnsPort) { + CFRelease(targetPrivate->dnsRLS); + targetPrivate->dnsRLS = NULL; + CFRelease(targetPrivate->dnsPort); + targetPrivate->dnsPort = NULL; + } + + pthread_mutex_unlock(&targetPrivate->lock); + + return; +} +#else /* CHECK_IPV6_REACHABILITY */ +static void +getipnodebyname_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info) +{ + SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)info; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + pthread_mutex_lock(&targetPrivate->lock); + + getipnodebyname_async_handleReply(msg); + + if (port == targetPrivate->dnsPort) { + CFRelease(targetPrivate->dnsRLS); + targetPrivate->dnsRLS = NULL; + CFRelease(targetPrivate->dnsPort); + targetPrivate->dnsPort = NULL; + } + + pthread_mutex_unlock(&targetPrivate->lock); + + return; +} +#endif /* CHECK_IPV6_REACHABILITY */ + + +static Boolean +checkResolverReachability(SCDynamicStoreRef *storeP, + SCNetworkConnectionFlags *flags, + Boolean *haveDNS) +{ + int i; + Boolean ok = TRUE; + + /* + * 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; + *haveDNS = FALSE; + + if (needDNS) { + if (hn_store) { + /* if we are actively watching at least one host */ + needDNS = FALSE; + } + res_init(); + } + + for (i = 0; i < _res.nscount; i++) { + 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(storeP, (struct sockaddr *)&_res.nsaddr_list[i], &ns_flags, NULL); + if (!ok) { + /* not today */ + break; + } + if (rankReachability(ns_flags) < rankReachability(*flags)) { + /* return the worst case result */ + *flags = ns_flags; + } + } + + if (!*haveDNS) { + /* if no DNS server addresses */ + *flags = 0; + } + + return ok; +} + + +static Boolean +startAsyncDNSQuery(SCNetworkReachabilityRef target) { + CFMachPortContext context = { 0, (void *)target, CFRetain, CFRelease, CFCopyDescription }; + int error; +#ifdef CHECK_IPV6_REACHABILITY + struct addrinfo hints; +#endif /* CHECK_IPV6_REACHABILITY */ + CFIndex i; + CFIndex n; + mach_port_t port; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + +#ifdef CHECK_IPV6_REACHABILITY + bzero(&hints, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG; + + error = getaddrinfo_async_start(&port, + targetPrivate->name, + NULL, + &hints, + __SCNetworkReachabilityCallbackSetResolvedAddress, + (void *)target); + if (error != 0) { + /* save the error associated with the attempt to resolve the name */ + __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, error); + return FALSE; + } + + targetPrivate->dnsPort = CFMachPortCreateWithPort(NULL, + port, + getaddrinfo_async_handleCFReply, + &context, + NULL); +#else /* CHECK_IPV6_REACHABILITY */ + port = getipnodebyname_async_start(targetPrivate->name, + AF_INET, + 0, + &error, + __SCNetworkReachabilityCallbackSetResolvedAddress, + (void *)target); + if (port == MACH_PORT_NULL) { + /* save the error associated with the attempt to resolve the name */ + __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, error); + return FALSE; + } + + targetPrivate->dnsPort = CFMachPortCreateWithPort(NULL, + port, + getipnodebyname_async_handleCFReply, + &context, + NULL); +#endif /* CHECK_IPV6_REACHABILITY */ + + targetPrivate->dnsRLS = CFMachPortCreateRunLoopSource(NULL, targetPrivate->dnsPort, 0); + + n = CFArrayGetCount(targetPrivate->rlList); + for (i = 0; i < n; i += 3) { + CFRunLoopRef rl = (CFRunLoopRef)CFArrayGetValueAtIndex(targetPrivate->rlList, i+1); + CFStringRef rlMode = (CFStringRef) CFArrayGetValueAtIndex(targetPrivate->rlList, i+2); + + CFRunLoopAddSource(rl, targetPrivate->dnsRLS, rlMode); + } + + return TRUE; +} + + +static Boolean +__SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, + SCNetworkReachabilityRef target, + SCNetworkConnectionFlags *flags, + uint16_t *if_index, + Boolean async) +{ + CFMutableArrayRef addresses = NULL; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + SCNetworkConnectionFlags my_flags = 0; + uint16_t my_index = 0; + Boolean ok = TRUE; + + *flags = 0; + if (if_index) { + *if_index = 0; + } + + if (!isA_SCNetworkReachability(target)) { + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + + switch (targetPrivate->type) { + case reachabilityTypeAddress : + case reachabilityTypeAddressPair : { + /* + * Check "local" address + */ + if (targetPrivate->localAddress) { + /* + * Check if 0.0.0.0 + */ + if (isAddressZero(targetPrivate->localAddress, &my_flags)) { + goto checkRemote; + } + + /* + * Check "local" address + */ + ok = checkAddress(storeP, targetPrivate->localAddress, &my_flags, &my_index); + if (!ok) { + goto error; /* not today */ + } + + if (!(my_flags & kSCNetworkFlagsIsLocalAddress)) { + goto error; /* not reachable, non-"local" address */ + } + } + + checkRemote : + + /* + * Check "remote" address + */ + if (targetPrivate->remoteAddress) { + /* + * in cases where we have "local" and "remote" addresses + * we need to re-initialize the to-be-returned flags. + */ + my_flags = 0; + my_index = 0; + + /* + * Check if 0.0.0.0 + */ + if (isAddressZero(targetPrivate->remoteAddress, &my_flags)) { + break; + } + + /* + * Check "remote" address + */ + ok = checkAddress(storeP, targetPrivate->remoteAddress, &my_flags, &my_index); + if (!ok) { + goto error; /* not today */ + } + } + + break; + + } + + case reachabilityTypeName : { + int error; +#ifndef CHECK_IPV6_REACHABILITY + struct hostent *h; +#endif /* CHECK_IPV6_REACHABILITY */ + Boolean haveDNS = FALSE; +#ifdef CHECK_IPV6_REACHABILITY + struct addrinfo hints; +#endif /* CHECK_IPV6_REACHABILITY */ + SCNetworkConnectionFlags ns_flags; +#ifdef CHECK_IPV6_REACHABILITY + struct addrinfo *res; +#endif /* CHECK_IPV6_REACHABILITY */ + + addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error); + if (addresses || (error != NETDB_SUCCESS)) { + /* if resolved or an error had been detected */ + goto checkResolvedAddress; + } + + /* check the reachability of the DNS servers */ + ok = checkResolverReachability(storeP, &ns_flags, &haveDNS);\ + if (!ok) { + /* if we could not get DNS server info */ + goto error; + } + + if (rankReachability(ns_flags) < 2) { + /* + * if DNS servers are not (or are no longer) reachable, set + * flags based on the availability of configured (but not + * active) services. + */ + if (!checkAddressZero(storeP, &my_flags, &my_index)) { + goto error; + } + + if (async && targetPrivate->rls) { + /* + * return HOST_NOT_FOUND, set flags appropriately, + * and schedule notification. + */ +#ifdef CHECK_IPV6_REACHABILITY + __SCNetworkReachabilityCallbackSetResolvedAddress(EAI_NODATA, + NULL, + (void *)target); +#else /* CHECK_IPV6_REACHABILITY */ + __SCNetworkReachabilityCallbackSetResolvedAddress(NULL, + HOST_NOT_FOUND, + (void *)target); +#endif /* CHECK_IPV6_REACHABILITY */ + + my_flags |= (targetPrivate->flags & kSCNetworkFlagsFirstResolvePending); + + SCLog(_sc_debug, LOG_INFO, CFSTR("no DNS servers are reachable")); + CFRunLoopSourceSignal(targetPrivate->rls); + __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList); + } + break; + } + + if (async) { + /* for async requests we return the last known status */ + my_flags = targetPrivate->flags; + my_index = targetPrivate->if_index; + + if (targetPrivate->dnsPort) { + /* if request already in progress */ + break; + } + + SCLog(_sc_debug, LOG_INFO, CFSTR("start DNS query for \"%s\""), targetPrivate->name); + + /* + * initiate an async DNS query + */ + if (!startAsyncDNSQuery(target)) { + /* if we could not initiate the request, process error */ + goto checkResolvedAddress; + } + + /* if request initiated */ + break; + } + + SCLog(_sc_debug, LOG_INFO, CFSTR("check DNS for \"%s\""), targetPrivate->name); + + /* + * OK, all of the DNS name servers are available. Let's + * resolve the nodename into an address. + */ +#ifdef CHECK_IPV6_REACHABILITY + bzero(&hints, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG; + + error = getaddrinfo(targetPrivate->name, NULL, &hints, &res); + __SCNetworkReachabilityCallbackSetResolvedAddress(error, res, (void *)target); +#else /* CHECK_IPV6_REACHABILITY */ + h = getipnodebyname(targetPrivate->name, AF_INET, 0, &error); + __SCNetworkReachabilityCallbackSetResolvedAddress(h, error, (void *)target); +#endif /* CHECK_IPV6_REACHABILITY */ + + addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error); + + checkResolvedAddress : + + /* + * We first assume that the requested host is NOT available. + * Then, check each address for accessibility and return the + * best status available. + */ + my_flags = 0; + my_index = 0; + + if (isA_CFArray(addresses)) { + CFIndex i; + CFIndex n = CFArrayGetCount(addresses); + + for (i = 0; i < n; i++) { + SCNetworkConnectionFlags ns_flags = 0; + uint16_t ns_if_index = 0; + struct sockaddr *sa; + + sa = (struct sockaddr *)CFDataGetBytePtr(CFArrayGetValueAtIndex(addresses, i)); + ok = checkAddress(storeP, sa, &ns_flags, &ns_if_index); + if (!ok) { + goto error; /* not today */ + } + + if (rankReachability(ns_flags) > rankReachability(my_flags)) { + /* return the best case result */ + my_flags = ns_flags; + my_index = ns_if_index; + if (rankReachability(my_flags) == 2) { + /* we're in luck */ + break; + } + } + } + } else { + if ((error == HOST_NOT_FOUND) && !haveDNS) { + /* + * No DNS servers are defined. Set flags based on + * the availability of configured (but not active) + * services. + */ + ok = checkAddressZero(storeP, &my_flags, &my_index); + if (!ok) { + goto error; /* not today */ + } + + if ((my_flags & kSCNetworkFlagsReachable) && + (my_flags & kSCNetworkFlagsConnectionRequired)) { + /* + * Since we might pick up a set of DNS servers when this connection + * is established, don't reply with a "HOST NOT FOUND" error just yet. + */ + break; + } + + /* Host not found, not reachable! */ + my_flags = 0; + my_index = 0; + } + } + + break; + } + } + + *flags = my_flags; + if (if_index) { + *if_index = my_index; + } + + error : + + if (addresses) CFRelease(addresses); + return ok; +} + + +Boolean +SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef target, + SCNetworkConnectionFlags *flags) +{ + Boolean ok; + SCDynamicStoreRef store = NULL; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + if (!isA_SCNetworkReachability(target)) { + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + + if (targetPrivate->rlList) { + /* if being watched, return current (OK, last known) status */ + *flags = targetPrivate->flags & ~kSCNetworkFlagsFirstResolvePending; + return TRUE; + } + + ok = __SCNetworkReachabilityGetFlags(&store, target, flags, NULL, FALSE); + *flags &= ~kSCNetworkFlagsFirstResolvePending; + if (store) CFRelease(store); + return ok; +} + + +static void +__SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef store) +{ + CFStringRef key; + CFMutableArrayRef keys; + CFStringRef pattern; + CFMutableArrayRef patterns; + + keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + /* + * Setup:/Network/Global/IPv4 (for the ServiceOrder) + */ + key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, + kSCDynamicStoreDomainSetup, + kSCEntNetIPv4); + CFArrayAppendValue(keys, key); + CFRelease(key); + + /* + * State:/Network/Global/DNS + */ + key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, + kSCDynamicStoreDomainState, + kSCEntNetDNS); + CFArrayAppendValue(keys, key); + CFRelease(key); + + /* + * State:/Network/Global/IPv4 + */ + key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, + kSCDynamicStoreDomainState, + kSCEntNetIPv4); + CFArrayAppendValue(keys, key); + CFRelease(key); + + /* 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); + + /* State: per-interface IPv6 info */ + pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, + kSCDynamicStoreDomainState, + kSCCompAnyRegex, + kSCEntNetIPv6); + CFArrayAppendValue(patterns, pattern); + CFRelease(pattern); + + (void)SCDynamicStoreSetNotificationKeys(store, keys, patterns); + CFRelease(keys); + CFRelease(patterns); + + return; +} + + +static void +__SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef store, + CFArrayRef changedKeys, + void *info) +{ + Boolean dnsChanged = FALSE; + CFIndex i; + CFStringRef key; + CFIndex nTargets; + const void * targets_q[N_QUICK]; + const void ** targets = targets_q; + + pthread_mutex_lock(&hn_lock); + + nTargets = CFSetGetCount(hn_targets); + if (nTargets == 0) { + /* if no addresses being monitored */ + goto done; + } + + if (CFArrayGetCount(changedKeys) == 0) { + /* if no changes */ + goto done; + } + + SCLog(_sc_debug, LOG_INFO, CFSTR("process configuration change")); + + key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, + kSCDynamicStoreDomainState, + kSCEntNetDNS); + if (CFArrayContainsValue(changedKeys, + CFRangeMake(0, CFArrayGetCount(changedKeys)), + key)) { + dnsChanged = TRUE; /* the DNS server(s) have changed */ + needDNS = TRUE; /* ... and we need to res_init() on the next query */ + } + CFRelease(key); + + if (!dnsChanged) { + /* + * if the DNS configuration didn't change we still need to + * check that the DNS servers are accessible. + */ + Boolean haveDNS = FALSE; + SCNetworkConnectionFlags ns_flags; + Boolean ok; + + /* check the reachability of the DNS servers */ + ok = checkResolverReachability(&store, &ns_flags, &haveDNS);\ + if (!ok || (rankReachability(ns_flags) < 2)) { + /* if DNS servers are not reachable */ + dnsChanged = TRUE; + } + } + + SCLog(_sc_debug && dnsChanged, LOG_INFO, CFSTR(" DNS changed")); + + if (nTargets > (CFIndex)(sizeof(targets_q) / sizeof(CFTypeRef))) + targets = CFAllocatorAllocate(NULL, nTargets * sizeof(CFTypeRef), 0); + CFSetGetValues(hn_targets, targets); + for (i = 0; i < nTargets; i++) { + SCNetworkReachabilityRef target = targets[i]; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + pthread_mutex_lock(&targetPrivate->lock); + + if (dnsChanged) { + if (targetPrivate->dnsPort) { + /* cancel the outstanding DNS query */ +#ifdef CHECK_IPV6_REACHABILITY + lu_async_call_cancel(CFMachPortGetPort(targetPrivate->dnsPort)); +#else /* CHECK_IPV6_REACHABILITY */ + getipnodebyname_async_cancel(CFMachPortGetPort(targetPrivate->dnsPort)); +#endif /* CHECK_IPV6_REACHABILITY */ + CFRelease(targetPrivate->dnsRLS); + targetPrivate->dnsRLS = NULL; + CFRelease(targetPrivate->dnsPort); + targetPrivate->dnsPort = NULL; + } + + /* schedule request to resolve the name again */ + __SCNetworkReachabilitySetResolvedAddress(target, NULL, NETDB_SUCCESS); + } + + CFRunLoopSourceSignal(targetPrivate->rls); + __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList); + + pthread_mutex_unlock(&targetPrivate->lock); + } + if (targets != targets_q) CFAllocatorDeallocate(NULL, targets); + + done : + + pthread_mutex_unlock(&hn_lock); + return; +} + + +static Boolean +__isScheduled(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList) +{ + CFIndex i; + CFIndex n = CFArrayGetCount(rlList); + + for (i = 0; i < n; i += 3) { + if (obj && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { + continue; + } + if (runLoop && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) { + continue; + } + if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) { + continue; + } + return TRUE; + } + + return FALSE; +} + + +static void +__schedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList) +{ + CFArrayAppendValue(rlList, obj); + CFArrayAppendValue(rlList, runLoop); + CFArrayAppendValue(rlList, runLoopMode); + + return; +} + + +static Boolean +__unschedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList, Boolean all) +{ + CFIndex i = 0; + Boolean found = FALSE; + CFIndex n = CFArrayGetCount(rlList); + + while (i < n) { + if (obj && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) { + i += 3; + continue; + } + if (runLoop && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) { + i += 3; + continue; + } + if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) { + i += 3; + continue; + } + + found = TRUE; + + CFArrayRemoveValueAtIndex(rlList, i + 2); + CFArrayRemoveValueAtIndex(rlList, i + 1); + CFArrayRemoveValueAtIndex(rlList, i); + + if (!all) { + return found; + } + + n -= 3; + } + + return found; +} + + +static void +rlsPerform(void *info) +{ + void *context_info; + void (*context_release)(const void *); + SCNetworkConnectionFlags flags; + uint16_t if_index; + Boolean ok; + SCNetworkReachabilityCallBack rlsFunction; + SCDynamicStoreRef store = NULL; + SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)info; + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + SCLog(_sc_debug, LOG_DEBUG, CFSTR("process reachability change")); + + pthread_mutex_lock(&targetPrivate->lock); + + /* update reachability, notify if status changed */ + ok = __SCNetworkReachabilityGetFlags(&store, target, &flags, &if_index, TRUE); + if (store) CFRelease(store); + if (!ok) { + /* if reachability status not available */ + flags = 0; + if_index = 0; + } + + if ((targetPrivate->flags == flags) && (targetPrivate->if_index == if_index)) { + /* if reachability flags and interface have not changed */ + pthread_mutex_unlock(&targetPrivate->lock); + SCLog(_sc_debug, LOG_DEBUG, CFSTR("flags/interface match")); + return; + } + + /* update flags / interface */ + targetPrivate->flags = flags; + targetPrivate->if_index = if_index; + + /* callout */ + rlsFunction = targetPrivate->rlsFunction; + if (NULL != targetPrivate->rlsContext.retain) { + context_info = (void *)targetPrivate->rlsContext.retain(targetPrivate->rlsContext.info); + context_release = targetPrivate->rlsContext.release; + } else { + context_info = targetPrivate->rlsContext.info; + context_release = NULL; + } + + pthread_mutex_unlock(&targetPrivate->lock); + + if (rlsFunction) { + SCLog(_sc_debug, LOG_DEBUG, CFSTR("flags/interface have changed")); + (*rlsFunction)(target, flags, context_info); + } + + if (context_release) { + context_release(context_info); + } + + return; +} + + +Boolean +SCNetworkReachabilitySetCallback(SCNetworkReachabilityRef target, + SCNetworkReachabilityCallBack callout, + SCNetworkReachabilityContext *context) +{ + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + + pthread_mutex_lock(&targetPrivate->lock); + + if (targetPrivate->rlsContext.release) { + /* let go of the current context */ + targetPrivate->rlsContext.release(targetPrivate->rlsContext.info); + } + + targetPrivate->rlsFunction = callout; + targetPrivate->rlsContext.info = NULL; + targetPrivate->rlsContext.retain = NULL; + targetPrivate->rlsContext.release = NULL; + targetPrivate->rlsContext.copyDescription = NULL; + if (context) { + bcopy(context, &targetPrivate->rlsContext, sizeof(SCNetworkReachabilityContext)); + if (context->retain) { + targetPrivate->rlsContext.info = (void *)context->retain(context->info); + } + } + + pthread_mutex_unlock(&targetPrivate->lock); + + return TRUE; +} + + +Boolean +SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode) +{ + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + Boolean init = FALSE; + Boolean ok = FALSE; + + if (!isA_SCNetworkReachability(target) || runLoop == NULL || runLoopMode == NULL) { + _SCErrorSet(kSCStatusInvalidArgument); + return FALSE; + } + + /* schedule the SCNetworkReachability run loop source */ + + pthread_mutex_lock(&hn_lock); + pthread_mutex_lock(&targetPrivate->lock); + + if (!hn_store) { + /* + * if we are not monitoring any hosts + */ + hn_store = SCDynamicStoreCreate(NULL, + CFSTR("SCNetworkReachability"), + __SCNetworkReachabilityReachabilityHandleChanges, + NULL); + if (!hn_store) { + SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed")); + goto done; + } + + __SCNetworkReachabilityReachabilitySetNotifications(hn_store); + + hn_storeRLS = SCDynamicStoreCreateRunLoopSource(NULL, hn_store, 0); + hn_rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + hn_targets = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); + } + + if (!targetPrivate->rls) { + CFRunLoopSourceContext context = { 0 // version + , (void *)target // info + , CFRetain // retain + , CFRelease // release + , CFCopyDescription // copyDescription + , CFEqual // equal + , CFHash // hash + , NULL // schedule + , NULL // cancel + , rlsPerform // perform + }; + + targetPrivate->rls = CFRunLoopSourceCreate(NULL, 0, &context); + targetPrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + init = TRUE; + } + + if (!__isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) { + /* + * if we do not already have host notifications scheduled with + * this runLoop / runLoopMode + */ + CFRunLoopAddSource(runLoop, targetPrivate->rls, runLoopMode); + + if (targetPrivate->dnsRLS) { + /* if we have an active async DNS query too */ + CFRunLoopAddSource(runLoop, targetPrivate->dnsRLS, runLoopMode); + } + } + + __schedule(target, runLoop, runLoopMode, targetPrivate->rlList); + + /* schedule the SCNetworkReachability run loop source */ + + if (!__isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) { + /* + * if we do not already have SC notifications scheduled with + * this runLoop / runLoopMode + */ + CFRunLoopAddSource(runLoop, hn_storeRLS, runLoopMode); + } + + __schedule(target, runLoop, runLoopMode, hn_rlList); + CFSetAddValue(hn_targets, target); + + if (init) { + SCNetworkConnectionFlags flags; + uint16_t if_index; + SCDynamicStoreRef store = NULL; + + /* + * if we have yet to schedule SC notifications for this address + * - initialize current reachability status + */ + if (__SCNetworkReachabilityGetFlags(&store, target, &flags, &if_index, TRUE)) { + /* + * if reachability status available + * - set flags + * - schedule notification to report status via callback + */ + targetPrivate->flags = flags; + targetPrivate->if_index = if_index; + CFRunLoopSourceSignal(targetPrivate->rls); + __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList); + } else { + /* if reachability status not available, async lookup started */ + targetPrivate->flags = 0; + targetPrivate->if_index = 0; + } + if (store) CFRelease(store); + } + + ok = TRUE; + + done : + + pthread_mutex_unlock(&targetPrivate->lock); + pthread_mutex_unlock(&hn_lock); + return ok; +} + + +Boolean +SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode) +{ + SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target; + CFIndex n; + Boolean ok = FALSE; + + if (!isA_SCNetworkReachability(target) || runLoop == NULL || runLoopMode == NULL) { + _SCErrorSet(kSCStatusInvalidArgument); + goto done; + } + + pthread_mutex_lock(&hn_lock); + pthread_mutex_lock(&targetPrivate->lock); + + if (!targetPrivate->rls) { + /* if not currently scheduled */ + goto done; + } + + if (!__unschedule(NULL, runLoop, runLoopMode, targetPrivate->rlList, FALSE)) { + /* if not currently scheduled */ + goto done; + } + + n = CFArrayGetCount(targetPrivate->rlList); + if (n == 0 || !__isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) { + /* + * if this host is no longer scheduled for this runLoop / runLoopMode + */ + CFRunLoopRemoveSource(runLoop, targetPrivate->rls, runLoopMode); + + if (targetPrivate->dnsRLS) { + /* if we have an active async DNS query too */ + CFRunLoopRemoveSource(runLoop, targetPrivate->dnsRLS, runLoopMode); + } + + if (n == 0) { + /* + * if this host is no longer scheduled + */ + CFRelease(targetPrivate->rls); /* cleanup SCNetworkReachability resources */ + targetPrivate->rls = NULL; + CFRelease(targetPrivate->rlList); + targetPrivate->rlList = NULL; + CFSetRemoveValue(hn_targets, target); /* cleanup notification resources */ + + if (targetPrivate->dnsPort) { + /* if we have an active async DNS query too */ +#ifdef CHECK_IPV6_REACHABILITY + lu_async_call_cancel(CFMachPortGetPort(targetPrivate->dnsPort)); +#else /* CHECK_IPV6_REACHABILITY */ + getipnodebyname_async_cancel(CFMachPortGetPort(targetPrivate->dnsPort)); +#endif /* CHECK_IPV6_REACHABILITY */ + CFRelease(targetPrivate->dnsRLS); + targetPrivate->dnsRLS = NULL; + CFRelease(targetPrivate->dnsPort); + targetPrivate->dnsPort = NULL; + } + } + } + + (void)__unschedule(target, runLoop, runLoopMode, hn_rlList, FALSE); + + n = CFArrayGetCount(hn_rlList); + if (n == 0 || !__isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) { + /* + * if we no longer have any addresses scheduled for + * this runLoop / runLoopMode + */ + CFRunLoopRemoveSource(runLoop, hn_storeRLS, runLoopMode); + + if (n == 0) { + /* + * if we are no longer monitoring any addresses + */ + CFRelease(hn_targets); + CFRelease(hn_rlList); + CFRelease(hn_storeRLS); + CFRelease(hn_store); + hn_store = NULL; + + /* + * until we start monitoring again, ensure that + * all subsequent reachability-by-name checks + * call res_init() + */ + needDNS = TRUE; + } + } + + ok = TRUE; + + done : + + pthread_mutex_unlock(&targetPrivate->lock); + pthread_mutex_unlock(&hn_lock); + return ok; +} diff --git a/SystemConfiguration.fproj/SCNetworkReachability.h b/SystemConfiguration.fproj/SCNetworkReachability.h new file mode 100644 index 0000000..7ad9962 --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkReachability.h @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SCNETWORKREACHABILITY_H +#define _SCNETWORKREACHABILITY_H + +#include +#include +#include +#include +#include +#include + +/*! + @header SCNetworkReachability + The SCNetworkReachabilityXXX() APIs allow an application to determine the status + of a system's current network configuration and the reachability + of a target host. In addition, the reachability can be monitored + with a notification being provided when/if the status has changed. + + The term "reachable" reflects whether a data packet, sent by + an application into the network stack, can be sent to the + the target host/address. Please note that there is no + guarantee that the data packet will actually be received by + the host. + */ + +/*! + @typedef SCNetworkReachabilityRef + @discussion This is the handle to a network address/name. + */ +typedef const struct __SCNetworkReachability * SCNetworkReachabilityRef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @typedef SCNetworkReachabilityContext + */ +typedef struct { + CFIndex version; + void * info; + const void *(*retain)(const void *info); + void (*release)(const void *info); + CFStringRef (*copyDescription)(const void *info); +} SCNetworkReachabilityContext AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + +/*! + @typedef SCNetworkReachabilityCallBack + @discussion Type of the callback function used when the + reachability of a network address/name changes. + @param target The SCNetworkReachability reference being monitored for changes. + @param flags The new SCNetworkConnectionFlags representing the + reachability status of the network address/name. + @param info .... + */ +typedef void (*SCNetworkReachabilityCallBack) ( + SCNetworkReachabilityRef target, + SCNetworkConnectionFlags flags, + void *info + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + +__BEGIN_DECLS + +/*! + @function SCNetworkReachabilityCreateWithAddress + @discussion Creates a reference to the specified network + address. This reference can later be used to monitor + the reachability of the target host. + @param address The address of the desired host. + @result A reference to the new immutable SCNetworkReachabilityRef. + + You must release the returned value. + */ +SCNetworkReachabilityRef +SCNetworkReachabilityCreateWithAddress ( + CFAllocatorRef allocator, + const struct sockaddr *address + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + +/*! + @function SCNetworkReachabilityCreateWithAddressPair + @discussion Creates a reference to the specified network + address. This reference can later be used to monitor + the reachability of the target host. + @param localAddress The local address associated with a network + connection. If NULL, only the remote address is of interest. + @param remoteAddress The remote address associated with a network + connection. If NULL, only the local address is of interest. + @result A reference to the new immutable SCNetworkReachabilityRef. + + You must release the returned value. + */ +SCNetworkReachabilityRef +SCNetworkReachabilityCreateWithAddressPair ( + CFAllocatorRef allocator, + const struct sockaddr *localAddress, + const struct sockaddr *remoteAddress + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + +/*! + @function SCNetworkReachabilityCreateWithName + @discussion Creates a reference to the specified network host/node + name. This reference can later be used to monitor the + reachability of the target host. + @param nodename The node name of the desired host. This name would + be the same as that passed to gethostbyname() or getaddrinfo(). + @result A reference to the new immutable SCNetworkReachabilityRef. + + You must release the returned value. + */ +SCNetworkReachabilityRef +SCNetworkReachabilityCreateWithName ( + CFAllocatorRef allocator, + const char *nodename + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + +/*! + @function SCNetworkReachabilityGetTypeID + Returns the type identifier of all SCNetworkReachability instances. + */ +CFTypeID +SCNetworkReachabilityGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + + +/*! + @function SCNetworkReachabilityGetFlags + @discussion Determines if the given target is reachable using the + current network configuration. + @param target The network reference associated with the address/name + to be checked for reachability. + @param flags A pointer to memory that will be filled with the + SCNetworkConnectionFlags detailing the reachability + of the specified target. + @result TRUE if the network connection flags are valid; FALSE if the + status could not be determined. + */ +Boolean +SCNetworkReachabilityGetFlags ( + SCNetworkReachabilityRef target, + SCNetworkConnectionFlags *flags + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + +/*! + @function SCNetworkReachabilitySetCallback + @discussion Assigns a client to a target, which receives callbacks + when the reachability of the target changes. + @param target The network reference associated with the address/name + to be checked for reachability. + @param callout The function to be called when the reachability of + target changes. If NULL, the current client for the target + is removed. + @param context The SCNetworkReachabilityContext associated with + the callout. + @result TRUE if the notification client was successfully set. + */ +Boolean +SCNetworkReachabilitySetCallback ( + SCNetworkReachabilityRef target, + SCNetworkReachabilityCallBack callout, + SCNetworkReachabilityContext *context + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + +/*! + @function SCNetworkReachabilityScheduleWithRunLoop + @discussion Schedule the given target from the given run loop and mode. + @param target The address/name which is set up for asynchronous mode. Must be non-NULL. + @param runLoop A reference to a runloop on which the target should be scheduled. Must be non-NULL. + @param runLoopMode The mode on which to schedule the target. Must be non-NULL. + */ +Boolean +SCNetworkReachabilityScheduleWithRunLoop ( + SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + +/*! + @function SCNetworkReachabilityUnscheduleFromRunLoop + @discussion Unschedule the given target from the given run loop and mode. + @param target The address/name which is set up for asynchronous mode. Must be non-NULL. + @param runLoop A reference to a runloop on which the target should be scheduled. Must be non-NULL. + @param runLoopMode The mode on which to schedule the target. Must be non-NULL. + */ +Boolean +SCNetworkReachabilityUnscheduleFromRunLoop ( + SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode + ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; + +__END_DECLS + +#endif /* _SCNETWORKREACHABILITY_H */ diff --git a/SystemConfiguration.fproj/SCP.c b/SystemConfiguration.fproj/SCP.c index 9252a15..40f2eda 100644 --- a/SystemConfiguration.fproj/SCP.c +++ b/SystemConfiguration.fproj/SCP.c @@ -1,22 +1,25 @@ /* - * Copyright(c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -61,10 +64,10 @@ __private_extern__ char * __SCPreferencesPath(CFAllocatorRef allocator, CFStringRef prefsID, Boolean perUser, - CFStringRef user) + CFStringRef user, + Boolean useNewPrefs) { CFStringRef path = NULL; - int pathLen; char *pathStr; if (perUser) { @@ -73,7 +76,7 @@ __SCPreferencesPath(CFAllocatorRef allocator, return NULL; } else if (CFStringHasPrefix(prefsID, CFSTR("/"))) { /* if absolute path */ - path = CFRetain(prefsID); + path = CFStringCreateCopy(allocator, prefsID); } else { /* * relative (to the user's preferences) path @@ -91,25 +94,12 @@ __SCPreferencesPath(CFAllocatorRef allocator, /* if could not get console user */ return NULL; } - (void) CFStringGetBytes(u, - CFRangeMake(0, CFStringGetLength(u)), - kCFStringEncodingMacRoman, - 0, - FALSE, - login, - MAXLOGNAME, - NULL); + + (void)_SC_cfstring_to_cstring(u, login, sizeof(login), kCFStringEncodingASCII); CFRelease(u); } else { /* use specified user */ - (void) CFStringGetBytes(user, - CFRangeMake(0, CFStringGetLength(user)), - kCFStringEncodingMacRoman, - 0, - FALSE, - login, - MAXLOGNAME, - NULL); + (void)_SC_cfstring_to_cstring(user, login, sizeof(login), kCFStringEncodingASCII); } /* get password entry for user */ @@ -133,33 +123,37 @@ __SCPreferencesPath(CFAllocatorRef allocator, path = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@"), - PREFS_DEFAULT_DIR, - PREFS_DEFAULT_CONFIG); + useNewPrefs ? PREFS_DEFAULT_DIR : PREFS_DEFAULT_DIR_OLD, + useNewPrefs ? PREFS_DEFAULT_CONFIG : PREFS_DEFAULT_CONFIG_OLD); } else if (CFStringHasPrefix(prefsID, CFSTR("/"))) { /* if absolute path */ - path = CFRetain(prefsID); + path = CFStringCreateCopy(allocator, prefsID); } else { /* relative path */ path = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@/%@"), - PREFS_DEFAULT_DIR, + useNewPrefs ? PREFS_DEFAULT_DIR : PREFS_DEFAULT_DIR_OLD, prefsID); + if (useNewPrefs && CFStringHasSuffix(path, CFSTR(".xml"))) { + CFMutableStringRef newPath; + + newPath = CFStringCreateMutableCopy(allocator, 0, path); + CFStringReplace(newPath, + CFRangeMake(CFStringGetLength(newPath)-4, 4), + CFSTR(".plist")); + CFRelease(path); + path = newPath; + } } } /* * convert CFStringRef path to C-string path */ - pathLen = CFStringGetLength(path) + 1; - pathStr = CFAllocatorAllocate(allocator, pathLen, 0); - if (!CFStringGetCString(path, - pathStr, - pathLen, - kCFStringEncodingMacRoman)) { + pathStr = _SC_cfstring_to_cstring(path, NULL, 0, kCFStringEncodingASCII); + if (pathStr == NULL) { SCLog(_sc_verbose, LOG_DEBUG, CFSTR("could not convert path to C string")); - CFAllocatorDeallocate(allocator, pathStr); - pathStr = NULL; } CFRelease(path); @@ -190,7 +184,7 @@ _SCPNotificationKey(CFAllocatorRef allocator, char *pathStr; char *typeStr; - pathStr = __SCPreferencesPath(allocator, prefsID, perUser, user); + pathStr = __SCPreferencesPath(allocator, prefsID, perUser, user, TRUE); if (pathStr == NULL) { return NULL; } @@ -217,7 +211,7 @@ _SCPNotificationKey(CFAllocatorRef allocator, typeStr, pathStr); - CFAllocatorDeallocate(allocator, pathStr); + CFAllocatorDeallocate(NULL, pathStr); return key; } @@ -225,17 +219,17 @@ _SCPNotificationKey(CFAllocatorRef allocator, CFStringRef SCDynamicStoreKeyCreatePreferences(CFAllocatorRef allocator, CFStringRef prefsID, - int keyType) + SCPreferencesKeyType keyType) { return _SCPNotificationKey(allocator, prefsID, FALSE, NULL, keyType); } CFStringRef -SCDynamicStoreKeyCreateUserPreferences(CFAllocatorRef allocator, - CFStringRef prefsID, - CFStringRef user, - int keyType) +SCDynamicStoreKeyCreateUserPreferences(CFAllocatorRef allocator, + CFStringRef prefsID, + CFStringRef user, + SCPreferencesKeyType keyType) { return _SCPNotificationKey(allocator, prefsID, TRUE, user, keyType); } diff --git a/SystemConfiguration.fproj/SCP.h b/SystemConfiguration.fproj/SCP.h deleted file mode 100644 index ab6957a..0000000 --- a/SystemConfiguration.fproj/SCP.h +++ /dev/null @@ -1,37 +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 _SCP_H -#define _SCP_H - -#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 70bc7a7..43de7f2 100644 --- a/SystemConfiguration.fproj/SCPAdd.c +++ b/SystemConfiguration.fproj/SCPAdd.c @@ -1,22 +1,25 @@ /* - * Copyright(c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -39,9 +42,11 @@ SCPreferencesAddValue(SCPreferencesRef session, CFStringRef key, CFPropertyListR { SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesAddValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesAddValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value); + } sessionPrivate->accessed = TRUE; diff --git a/SystemConfiguration.fproj/SCPApply.c b/SystemConfiguration.fproj/SCPApply.c index c0b9695..65c9acd 100644 --- a/SystemConfiguration.fproj/SCPApply.c +++ b/SystemConfiguration.fproj/SCPApply.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCPCommit.c b/SystemConfiguration.fproj/SCPCommit.c index fe6f435..18f00f3 100644 --- a/SystemConfiguration.fproj/SCPCommit.c +++ b/SystemConfiguration.fproj/SCPCommit.c @@ -1,22 +1,25 @@ /* - * Copyright(c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -38,6 +41,29 @@ #include #include +static ssize_t +writen(int d, const void *buf, size_t nbytes) +{ + size_t left = nbytes; + const void *p = buf; + + while (left > 0) { + ssize_t n; + + n = write(d, p, left); + if (n >= 0) { + left -= n; + p += n; + } else { + if (errno != EINTR) { + return -1; + } + } + } + return nbytes; +} + + Boolean SCPreferencesCommitChanges(SCPreferencesRef session) { @@ -62,11 +88,12 @@ SCPreferencesCommitChanges(SCPreferencesRef session) * if necessary, apply changes */ if (sessionPrivate->changed) { - struct stat statBuf; - int pathLen; - char *newPath; int fd; CFDataRef newPrefs; + char * path; + int pathLen; + struct stat statBuf; + char * thePath; if (stat(sessionPrivate->path, &statBuf) == -1) { if (errno == ENOENT) { @@ -81,24 +108,25 @@ SCPreferencesCommitChanges(SCPreferencesRef session) } /* create the (new) preferences file */ - pathLen = strlen(sessionPrivate->path) + sizeof("-new"); - newPath = CFAllocatorAllocate(NULL, pathLen, 0); - snprintf(newPath, pathLen, "%s-new", sessionPrivate->path); + path = sessionPrivate->newPath ? sessionPrivate->newPath : sessionPrivate->path; + pathLen = strlen(path) + sizeof("-new"); + thePath = CFAllocatorAllocate(NULL, pathLen, 0); + snprintf(thePath, pathLen, "%s-new", path); /* open the (new) preferences file */ reopen : - fd = open(newPath, O_WRONLY|O_CREAT, statBuf.st_mode); + fd = open(thePath, O_WRONLY|O_CREAT, statBuf.st_mode); if (fd == -1) { if ((errno == ENOENT) && ((sessionPrivate->prefsID == NULL) || !CFStringHasPrefix(sessionPrivate->prefsID, CFSTR("/")))) { char *ch; - ch = strrchr(newPath, '/'); + ch = strrchr(thePath, '/'); if (ch != NULL) { int status; *ch = '\0'; - status = mkdir(newPath, 0755); + status = mkdir(thePath, 0755); *ch = '/'; if (status == 0) { goto reopen; @@ -106,37 +134,55 @@ SCPreferencesCommitChanges(SCPreferencesRef session) } } SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPCommit open() failed: %s"), strerror(errno)); - CFAllocatorDeallocate(NULL, newPath); + CFAllocatorDeallocate(NULL, thePath); goto error; } /* preserve permissions */ (void) fchown(fd, statBuf.st_uid, statBuf.st_gid); + (void) fchmod(fd, statBuf.st_mode); /* write the new preferences */ newPrefs = CFPropertyListCreateXMLData(NULL, sessionPrivate->prefs); if (!newPrefs) { _SCErrorSet(kSCStatusFailed); SCLog(_sc_verbose, LOG_ERR, CFSTR(" CFPropertyListCreateXMLData() failed")); - CFAllocatorDeallocate(NULL, newPath); + CFAllocatorDeallocate(NULL, thePath); + (void) close(fd); + goto error; + } + if (writen(fd, (void *)CFDataGetBytePtr(newPrefs), CFDataGetLength(newPrefs)) == -1) { + _SCErrorSet(errno); + SCLog(_sc_verbose, LOG_ERR, CFSTR("write() failed: %s"), strerror(errno)); + (void) unlink(thePath); + CFAllocatorDeallocate(NULL, thePath); (void) close(fd); + CFRelease(newPrefs); goto error; } - (void) write(fd, CFDataGetBytePtr(newPrefs), CFDataGetLength(newPrefs)); (void) close(fd); CFRelease(newPrefs); /* rename new->old */ - if (rename(newPath, sessionPrivate->path) == -1) { + if (rename(thePath, path) == -1) { _SCErrorSet(errno); SCLog(_sc_verbose, LOG_ERR, CFSTR("rename() failed: %s"), strerror(errno)); - CFAllocatorDeallocate(NULL, newPath); + CFAllocatorDeallocate(NULL, thePath); goto error; } - CFAllocatorDeallocate(NULL, newPath); + CFAllocatorDeallocate(NULL, thePath); + + if (sessionPrivate->newPath) { + /* prefs file saved in "new" directory */ + (void) unlink(sessionPrivate->path); + (void) symlink(sessionPrivate->newPath, sessionPrivate->path); + CFAllocatorDeallocate(NULL, sessionPrivate->path); + sessionPrivate->path = path; + sessionPrivate->newPath = NULL; + } /* update signature */ - if (stat(sessionPrivate->path, &statBuf) == -1) { + if (stat(path, &statBuf) == -1) { _SCErrorSet(errno); SCLog(_sc_verbose, LOG_ERR, CFSTR("stat() failed: %s"), strerror(errno)); goto error; diff --git a/SystemConfiguration.fproj/SCPGet.c b/SystemConfiguration.fproj/SCPGet.c index 50f7cd4..bdbfc41 100644 --- a/SystemConfiguration.fproj/SCPGet.c +++ b/SystemConfiguration.fproj/SCPGet.c @@ -1,22 +1,25 @@ /* - * Copyright(c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -44,8 +47,10 @@ SCPreferencesGetValue(SCPreferencesRef session, CFStringRef key) SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; CFPropertyListRef value; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesGetValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesGetValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + } sessionPrivate->accessed = TRUE; value = CFDictionaryGetValue(sessionPrivate->prefs, key); diff --git a/SystemConfiguration.fproj/SCPList.c b/SystemConfiguration.fproj/SCPList.c index e0306d9..031c33e 100644 --- a/SystemConfiguration.fproj/SCPList.c +++ b/SystemConfiguration.fproj/SCPList.c @@ -1,22 +1,25 @@ /* - * Copyright(c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -41,7 +44,7 @@ SCPreferencesCopyKeyList(SCPreferencesRef session) CFArrayRef keys; SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; CFIndex prefsCnt; - const void **prefsKeys; + const void ** prefsKeys; SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesCopyKeyList:")); diff --git a/SystemConfiguration.fproj/SCPLock.c b/SystemConfiguration.fproj/SCPLock.c index c96d016..d69c81e 100644 --- a/SystemConfiguration.fproj/SCPLock.c +++ b/SystemConfiguration.fproj/SCPLock.c @@ -2,21 +2,24 @@ * Copyright(c) 2000-2002 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -41,6 +44,7 @@ Boolean SCPreferencesLock(SCPreferencesRef session, Boolean wait) { + CFAllocatorRef allocator = CFGetAllocator(session); CFArrayRef changes; CFDataRef currentSignature = NULL; Boolean haveLock = FALSE; @@ -68,7 +72,7 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait) if (sessionPrivate->session == NULL) { /* open a session */ - sessionPrivate->session = SCDynamicStoreCreate(NULL, + sessionPrivate->session = SCDynamicStoreCreate(allocator, CFSTR("SCPreferencesLock"), NULL, NULL); @@ -80,7 +84,7 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait) if (sessionPrivate->sessionKeyLock == NULL) { /* create the session "lock" key */ - sessionPrivate->sessionKeyLock = _SCPNotificationKey(NULL, + sessionPrivate->sessionKeyLock = _SCPNotificationKey(allocator, sessionPrivate->prefsID, sessionPrivate->perUser, sessionPrivate->user, @@ -94,7 +98,7 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait) goto error; } - value = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); + value = CFDateCreate(allocator, CFAbsoluteTimeGetCurrent()); while (TRUE) { CFArrayRef changedKeys; @@ -183,7 +187,7 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait) SCPreferencesRef newPrefs; SCPreferencesPrivateRef newPrivate; - newPrefs = __SCPreferencesCreate(NULL, + newPrefs = __SCPreferencesCreate(allocator, sessionPrivate->name, sessionPrivate->prefsID, sessionPrivate->perUser, diff --git a/SystemConfiguration.fproj/SCPOpen.c b/SystemConfiguration.fproj/SCPOpen.c index b24a006..a748210 100644 --- a/SystemConfiguration.fproj/SCPOpen.c +++ b/SystemConfiguration.fproj/SCPOpen.c @@ -1,22 +1,25 @@ /* - * Copyright(c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -31,8 +34,8 @@ */ #include -#include #include +#include #include "SCPreferencesInternal.h" #include @@ -65,6 +68,7 @@ __SCPreferencesDeallocate(CFTypeRef cf) if (sessionPrivate->prefsID) CFRelease(sessionPrivate->prefsID); if (sessionPrivate->user) CFRelease(sessionPrivate->user); if (sessionPrivate->path) CFAllocatorDeallocate(NULL, sessionPrivate->path); + if (sessionPrivate->newPath) CFAllocatorDeallocate(NULL, sessionPrivate->newPath); if (sessionPrivate->signature) CFRelease(sessionPrivate->signature); if (sessionPrivate->session) CFRelease(sessionPrivate->session); if (sessionPrivate->sessionKeyLock) CFRelease(sessionPrivate->sessionKeyLock); @@ -76,7 +80,7 @@ __SCPreferencesDeallocate(CFTypeRef cf) } -static CFTypeID __kSCPreferencesTypeID = _kCFRuntimeNotATypeID; +static CFTypeID __kSCPreferencesTypeID = _kCFRuntimeNotATypeID; static const CFRuntimeClass __SCPreferencesClass = { @@ -94,7 +98,6 @@ static const CFRuntimeClass __SCPreferencesClass = { static pthread_once_t initialized = PTHREAD_ONCE_INIT; - static void __SCPreferencesInitialize(void) { __kSCPreferencesTypeID = _CFRuntimeRegisterClass(&__SCPreferencesClass); @@ -102,42 +105,43 @@ __SCPreferencesInitialize(void) { } -SCPreferencesRef +static SCPreferencesPrivateRef __SCPreferencesCreatePrivate(CFAllocatorRef allocator) { - SCPreferencesPrivateRef prefs; - UInt32 size; + SCPreferencesPrivateRef prefsPrivate; + uint32_t size; /* initialize runtime */ pthread_once(&initialized, __SCPreferencesInitialize); /* allocate session */ size = sizeof(SCPreferencesPrivate) - sizeof(CFRuntimeBase); - prefs = (SCPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator, + prefsPrivate = (SCPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator, __kSCPreferencesTypeID, size, NULL); - if (!prefs) { + if (!prefsPrivate) { 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; + prefsPrivate->name = NULL; + prefsPrivate->prefsID = NULL; + prefsPrivate->perUser = FALSE; + prefsPrivate->user = NULL; + prefsPrivate->path = NULL; + prefsPrivate->newPath = NULL; // new prefs path + prefsPrivate->signature = NULL; + prefsPrivate->session = NULL; + prefsPrivate->sessionKeyLock = NULL; + prefsPrivate->sessionKeyCommit = NULL; + prefsPrivate->sessionKeyApply = NULL; + prefsPrivate->prefs = NULL; + prefsPrivate->accessed = FALSE; + prefsPrivate->changed = FALSE; + prefsPrivate->locked = FALSE; + prefsPrivate->isRoot = (geteuid() == 0); + + return prefsPrivate; } @@ -149,7 +153,6 @@ __SCPreferencesCreate(CFAllocatorRef allocator, CFStringRef user) { int fd = -1; - SCPreferencesRef prefs; SCPreferencesPrivateRef prefsPrivate; int sc_status = kSCStatusOK; struct stat statBuf; @@ -159,16 +162,21 @@ __SCPreferencesCreate(CFAllocatorRef allocator, /* * allocate and initialize a new session */ - prefs = __SCPreferencesCreatePrivate(allocator); - if (!prefs) { + prefsPrivate = __SCPreferencesCreatePrivate(allocator); + if (!prefsPrivate) { return NULL; } - prefsPrivate = (SCPreferencesPrivateRef)prefs; + + retry : /* * convert prefsID to path */ - prefsPrivate->path = __SCPreferencesPath(NULL, prefsID, perUser, user); + prefsPrivate->path = __SCPreferencesPath(allocator, + prefsID, + perUser, + user, + (prefsPrivate->newPath == NULL)); if (prefsPrivate->path == NULL) { sc_status = kSCStatusFailed; goto error; @@ -181,7 +189,31 @@ __SCPreferencesCreate(CFAllocatorRef allocator, if (fd == -1) { switch (errno) { case ENOENT : - /* no prefs file, start fresh */ + /* no prefs file */ + if (!perUser && + ((prefsID == NULL) || !CFStringHasPrefix(prefsID, CFSTR("/")))) { + /* if default preference ID or relative path */ + if (prefsPrivate->newPath == NULL) { + /* + * we've looked in the "new" prefs directory + * without success. Save the "new" path and + * look in the "old" prefs directory. + */ + prefsPrivate->newPath = prefsPrivate->path; + goto retry; + } else { + /* + * we've looked in both the "new" and "old" + * prefs directories without success. USe + * the "new" path. + */ + CFAllocatorDeallocate(NULL, prefsPrivate->path); + prefsPrivate->path = prefsPrivate->newPath; + prefsPrivate->newPath = NULL; + } + } + + /* start fresh */ bzero(&statBuf, sizeof(statBuf)); goto create_1; case EACCES : @@ -214,7 +246,7 @@ __SCPreferencesCreate(CFAllocatorRef allocator, /* * extract property list */ - xmlData = CFDataCreateMutable(NULL, statBuf.st_size); + xmlData = CFDataCreateMutable(allocator, statBuf.st_size); CFDataSetLength(xmlData, statBuf.st_size); if (read(fd, (void *)CFDataGetBytePtr(xmlData), statBuf.st_size) != statBuf.st_size) { /* corrupt prefs file, start fresh */ @@ -227,7 +259,7 @@ __SCPreferencesCreate(CFAllocatorRef allocator, /* * load preferences */ - dict = CFPropertyListCreateFromXMLData(NULL, + dict = CFPropertyListCreateFromXMLData(allocator, xmlData, kCFPropertyListImmutable, &xmlError); @@ -253,7 +285,7 @@ __SCPreferencesCreate(CFAllocatorRef allocator, goto create_2; } - prefsPrivate->prefs = CFDictionaryCreateMutableCopy(NULL, 0, dict); + prefsPrivate->prefs = CFDictionaryCreateMutableCopy(allocator, 0, dict); CFRelease(dict); } @@ -269,7 +301,7 @@ __SCPreferencesCreate(CFAllocatorRef allocator, * new file, create empty preferences */ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen(): creating new dictionary.")); - prefsPrivate->prefs = CFDictionaryCreateMutable(NULL, + prefsPrivate->prefs = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -279,22 +311,16 @@ __SCPreferencesCreate(CFAllocatorRef allocator, /* * all OK */ - prefsPrivate->name = CFRetain(name); - if (prefsID) { - prefsPrivate->prefsID = CFRetain(prefsID); - } + prefsPrivate->name = CFStringCreateCopy(allocator, name); + if (prefsID) prefsPrivate->prefsID = CFStringCreateCopy(allocator, prefsID); prefsPrivate->perUser = perUser; - if (user) { - prefsPrivate->user = CFRetain(user); - } - return prefs; + if (user) prefsPrivate->user = CFStringCreateCopy(allocator, user); + return (SCPreferencesRef)prefsPrivate; error : - if (fd != -1) { - (void) close(fd); - } - CFRelease(prefs); + if (fd != -1) (void) close(fd); + CFRelease(prefsPrivate); _SCErrorSet(sc_status); return NULL; } @@ -305,9 +331,11 @@ SCPreferencesCreate(CFAllocatorRef allocator, CFStringRef name, CFStringRef prefsID) { - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesCreate:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" name = %@"), name); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" prefsID = %@"), prefsID); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesCreate:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" name = %@"), name); + SCLog(TRUE, LOG_DEBUG, CFSTR(" prefsID = %@"), prefsID); + } return __SCPreferencesCreate(allocator, name, prefsID, FALSE, NULL); } @@ -319,10 +347,12 @@ SCUserPreferencesCreate(CFAllocatorRef allocator, CFStringRef prefsID, CFStringRef user) { - 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); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCUserPreferencesCreate:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" name = %@"), name); + SCLog(TRUE, LOG_DEBUG, CFSTR(" prefsID = %@"), prefsID); + SCLog(TRUE, LOG_DEBUG, CFSTR(" user = %@"), user); + } return __SCPreferencesCreate(allocator, name, prefsID, TRUE, user); } @@ -330,5 +360,6 @@ SCUserPreferencesCreate(CFAllocatorRef allocator, CFTypeID SCPreferencesGetTypeID(void) { + pthread_once(&initialized, __SCPreferencesInitialize); /* initialize runtime */ return __kSCPreferencesTypeID; } diff --git a/SystemConfiguration.fproj/SCPPath.c b/SystemConfiguration.fproj/SCPPath.c index 40b351f..fc27f6b 100644 --- a/SystemConfiguration.fproj/SCPPath.c +++ b/SystemConfiguration.fproj/SCPPath.c @@ -1,22 +1,25 @@ /* - * Copyright(c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -56,7 +59,7 @@ normalizePath(CFStringRef path) /* remove empty path components */ nElements = CFArrayGetCount(elements); - for (i=nElements; i>0; i--) { + for (i = nElements; i > 0; i--) { CFStringRef pathElement; pathElement = CFArrayGetValueAtIndex(elements, i-1); @@ -97,7 +100,7 @@ getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity) restart : nElements = CFArrayGetCount(elements); - for (i=0; iaccessed = TRUE; @@ -186,7 +189,7 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity) nElements = CFArrayGetCount(elements); nodes = CFArrayCreateMutable(NULL, nElements-1, &kCFTypeArrayCallBacks); - for (i=0; iaccessed = TRUE; @@ -253,7 +256,7 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity) if (entity) { newEntity = CFRetain(entity); } - for (i=nElements-1; i>=0; i--) { + for (i = nElements - 1; i >= 0; i--) { element = CFArrayGetValueAtIndex(elements, i); if (i == 0) { if (newEntity) { @@ -299,8 +302,10 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef session, CFUUIDRef uuid; CFDictionaryRef entity; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathCreateUniqueChild:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" prefix = %@"), prefix); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathCreateUniqueChild:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" prefix = %@"), prefix); + } if (getPath(session, prefix, &entity)) { // if prefix path exists @@ -344,8 +349,10 @@ SCPreferencesPathGetValue(SCPreferencesRef session, CFDictionaryRef entity; CFStringRef entityLink; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathGetValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" path = %@"), path); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathGetValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %@"), path); + } if (!getPath(session, path, &entity)) { return NULL; @@ -372,8 +379,10 @@ SCPreferencesPathGetLink(SCPreferencesRef session, CFDictionaryRef entity; CFStringRef entityLink; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathGetLink:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" path = %@"), path); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathGetLink:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %@"), path); + } if (!getPath(session, path, &entity)) { return NULL; @@ -397,9 +406,11 @@ SCPreferencesPathSetValue(SCPreferencesRef session, { Boolean ok; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathSetValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" path = %@"), path); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathSetValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %@"), path); + SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value); + } if (!value) { _SCErrorSet(kSCStatusInvalidArgument); @@ -420,9 +431,11 @@ SCPreferencesPathSetLink(SCPreferencesRef session, CFDictionaryRef entity; Boolean ok; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathSetLink:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" path = %@"), path); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" link = %@"), link); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathSetLink:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %@"), path); + SCLog(TRUE, LOG_DEBUG, CFSTR(" link = %@"), link); + } if (!link) { _SCErrorSet(kSCStatusInvalidArgument); @@ -454,8 +467,10 @@ SCPreferencesPathRemoveValue(SCPreferencesRef session, Boolean ok = FALSE; CFDictionaryRef value; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesPathRemoveValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" path = %@"), path); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathRemoveValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %@"), path); + } if (!getPath(session, path, &value)) { // if no such path diff --git a/SystemConfiguration.fproj/SCPPath.h b/SystemConfiguration.fproj/SCPPath.h deleted file mode 100644 index 8febc65..0000000 --- a/SystemConfiguration.fproj/SCPPath.h +++ /dev/null @@ -1,37 +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 _SCPPATH_H -#define _SCPPATH_H - -#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 8532004..ab52648 100644 --- a/SystemConfiguration.fproj/SCPRemove.c +++ b/SystemConfiguration.fproj/SCPRemove.c @@ -1,22 +1,25 @@ /* - * Copyright(c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -39,8 +42,10 @@ SCPreferencesRemoveValue(SCPreferencesRef session, CFStringRef key) { SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesRemoveValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesRemoveValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + } sessionPrivate->accessed = TRUE; diff --git a/SystemConfiguration.fproj/SCPSet.c b/SystemConfiguration.fproj/SCPSet.c index 28d5df5..2b1357e 100644 --- a/SystemConfiguration.fproj/SCPSet.c +++ b/SystemConfiguration.fproj/SCPSet.c @@ -1,22 +1,25 @@ /* - * Copyright(c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -39,9 +42,11 @@ SCPreferencesSetValue(SCPreferencesRef session, CFStringRef key, CFPropertyListR { SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesSetValue:")); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); + if (_sc_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesSetValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value); + } CFDictionarySetValue(sessionPrivate->prefs, key, value); sessionPrivate->accessed = TRUE; diff --git a/SystemConfiguration.fproj/SCPUnlock.c b/SystemConfiguration.fproj/SCPUnlock.c index 112a459..5a2ab73 100644 --- a/SystemConfiguration.fproj/SCPUnlock.c +++ b/SystemConfiguration.fproj/SCPUnlock.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCPreferences.h b/SystemConfiguration.fproj/SCPreferences.h index 854ed87..5db981e 100644 --- a/SystemConfiguration.fproj/SCPreferences.h +++ b/SystemConfiguration.fproj/SCPreferences.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -44,9 +47,6 @@ 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. */ @@ -104,8 +104,6 @@ SCPreferencesCreate ( 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 ( @@ -121,11 +119,13 @@ SCPreferencesLock ( 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. + + Note: This routine commits changes to persistent storage. + Call SCPreferencesApplyChanges() to apply the changes + to the running system. @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 ( diff --git a/SystemConfiguration.fproj/SCPreferencesInternal.h b/SystemConfiguration.fproj/SCPreferencesInternal.h index 82e3aa3..488e5d7 100644 --- a/SystemConfiguration.fproj/SCPreferencesInternal.h +++ b/SystemConfiguration.fproj/SCPreferencesInternal.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -32,10 +35,13 @@ #include -#define PREFS_DEFAULT_DIR CFSTR("/var/db/SystemConfiguration") -#define PREFS_DEFAULT_CONFIG CFSTR("preferences.xml") +#define PREFS_DEFAULT_DIR CFSTR("/Library/Preferences/SystemConfiguration") +#define PREFS_DEFAULT_CONFIG CFSTR("preferences.plist") -#define PREFS_DEFAULT_USER_DIR CFSTR("Library/Preferences") +#define PREFS_DEFAULT_DIR_OLD CFSTR("/var/db/SystemConfiguration") +#define PREFS_DEFAULT_CONFIG_OLD CFSTR("preferences.xml") + +#define PREFS_DEFAULT_USER_DIR CFSTR("Library/Preferences") /* Define the per-preference-handle structure */ @@ -56,6 +62,7 @@ typedef struct { /* configuration file path */ char *path; + char *newPath; /* configuration file signature */ CFDataRef signature; @@ -105,7 +112,8 @@ char * __SCPreferencesPath (CFAllocatorRef allocator, CFStringRef prefsID, Boolean perUser, - CFStringRef user); + CFStringRef user, + Boolean useNewPrefs); CFStringRef _SCPNotificationKey (CFAllocatorRef allocator, diff --git a/SystemConfiguration.fproj/SCPreferencesPath.h b/SystemConfiguration.fproj/SCPreferencesPath.h index 21ed419..98cd637 100644 --- a/SystemConfiguration.fproj/SCPreferencesPath.h +++ b/SystemConfiguration.fproj/SCPreferencesPath.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -69,9 +72,6 @@ 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. */ diff --git a/SystemConfiguration.fproj/SCPreferencesPrivate.h b/SystemConfiguration.fproj/SCPreferencesPrivate.h index 5ee8c21..076e1af 100644 --- a/SystemConfiguration.fproj/SCPreferencesPrivate.h +++ b/SystemConfiguration.fproj/SCPreferencesPrivate.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -38,12 +41,12 @@ @constant kSCPreferencesKeyApply Key used when new preferences are to be applied to the active system configuration. */ -typedef enum { +enum { kSCPreferencesKeyLock = 1, kSCPreferencesKeyCommit = 2, - kSCPreferencesKeyApply = 3, -} SCPreferencesKeyType; - + kSCPreferencesKeyApply = 3 +}; +typedef int32_t SCPreferencesKeyType; __BEGIN_DECLS @@ -60,21 +63,27 @@ __BEGIN_DECLS @result A notification string for the specified preference identifier. */ CFStringRef -SCDynamicStoreKeyCreatePreferences (CFAllocatorRef allocator, - CFStringRef prefsID, - int keyType); +SCDynamicStoreKeyCreatePreferences ( + CFAllocatorRef allocator, + CFStringRef prefsID, + SCPreferencesKeyType keyType + ); SCPreferencesRef -SCUserPreferencesCreate (CFAllocatorRef allocator, - CFStringRef name, - CFStringRef prefsID, - CFStringRef user); +SCUserPreferencesCreate ( + CFAllocatorRef allocator, + CFStringRef name, + CFStringRef prefsID, + CFStringRef user + ); CFStringRef -SCDynamicStoreKeyCreateUserPreferences (CFAllocatorRef allocator, - CFStringRef prefsID, - CFStringRef user, - int keyType); +SCDynamicStoreKeyCreateUserPreferences ( + CFAllocatorRef allocator, + CFStringRef prefsID, + CFStringRef user, + SCPreferencesKeyType keyType + ); __END_DECLS diff --git a/SystemConfiguration.fproj/SCPreferencesSetSpecific.h b/SystemConfiguration.fproj/SCPreferencesSetSpecific.h index dc22ff2..c4f4fed 100644 --- a/SystemConfiguration.fproj/SCPreferencesSetSpecific.h +++ b/SystemConfiguration.fproj/SCPreferencesSetSpecific.h @@ -2,21 +2,24 @@ * Copyright (c) 2000-2002 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SCPrivate.h b/SystemConfiguration.fproj/SCPrivate.h index e74d535..c63ca59 100644 --- a/SystemConfiguration.fproj/SCPrivate.h +++ b/SystemConfiguration.fproj/SCPrivate.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -28,6 +31,7 @@ #include #include +#include #include #include @@ -66,15 +70,117 @@ Boolean _SCSerialize (CFPropertyListRef obj, @function _SCUnserialize @discussion Unserialize a stream of bytes passed from/to configd into a CFPropertyList object. - @param obj A pointer to memory that will be filled with the CFPropertyList - associated with the stream of bytes. + @param obj A pointer to memory that will be filled with the CFPropertyList + associated with the stream of bytes. + @param xml CFDataRef with the serialized data @param data A pointer to the serialized data @param dataLen A pointer to the length of the serialized data + + Specify either "xml" or "data/dataLen". */ Boolean _SCUnserialize (CFPropertyListRef *obj, + CFDataRef xml, + void *dataRef, + CFIndex dataLen); + +/* + @function _SCSerializeString + @discussion Serialize a CFString object for passing + to/from configd. + @param str CFString key to serialize + @param data A pointer to a CFDataRef, NULL if storage should be + vm_allocated. + @param data A pointer to the newly allocated/serialized data + @param dataLen A pointer to the length in bytes of the newly + allocated/serialized data + */ +Boolean _SCSerializeString (CFStringRef str, + CFDataRef *data, + void **dataRef, + CFIndex *dataLen); + +/* + @function _SCUnserializeString + @discussion Unserialize a stream of bytes passed from/to configd + into a CFString object. + @param str A pointer to memory that will be filled with the CFPropertyList + associated with the stream of bytes. + @param utf8 CFDataRef with the serialized data + @param data A pointer to the serialized data + @param dataLen A pointer to the length of the serialized data + + Specify either "utf8" or "data/dataLen". + */ +Boolean _SCUnserializeString (CFStringRef *str, + CFDataRef utf8, void *dataRef, CFIndex dataLen); +/* + @function _SCSerializeData + @discussion Serialize a CFData object for passing + to/from configd. + @param data CFData key to serialize + @param data A pointer to the newly allocated/serialized data + @param dataLen A pointer to the length in bytes of the newly + allocated/serialized data + */ +Boolean _SCSerializeData (CFDataRef data, + void **dataRef, + CFIndex *dataLen); + +/* + @function _SCUnserializeData + @discussion Unserialize a stream of bytes passed from/to configd + into a CFData object. + @param data A pointer to memory that will be filled with the CFPropertyList + associated with the stream of bytes. + @param data A pointer to the serialized data + @param dataLen A pointer to the length of the serialized data + */ +Boolean _SCUnserializeData (CFDataRef *data, + void *dataRef, + CFIndex dataLen); + +/* + @function _SCSerializeMultiple + @discussion Convert a CFDictionary containing a set of CFPropertlyList + values into a CFDictionary containing a set of serialized CFData + values. + @param dict The CFDictionary with CFPropertyList values. + @result The serialized CFDictionary with CFData values + */ +CFDictionaryRef _SCSerializeMultiple (CFDictionaryRef dict); + +/* + @function _SCUnserializeMultiple + @discussion Convert a CFDictionary containing a set of CFData + values into a CFDictionary containing a set of serialized + CFPropertlyList values. + @param dict The CFDictionary with CFData values. + @result The serialized CFDictionary with CFPropertyList values + */ +CFDictionaryRef _SCUnserializeMultiple (CFDictionaryRef dict); + +/* + @function _SC_cfstring_to_cstring + @discussion Extracts a C-string from a CFString. + @param cfstr The CFString to extract the data from. + @param buf A user provided buffer of the specefied length. If NULL, + a new buffer will be allocated to contain the C-string. It + is the responsiblity of the caller to free an allocated + buffer. + @param bufLen The size of the user provided buffer. + @param encoding The string encoding + @result If the extraction (conversion) is successful then a pointer + to the user provided (or allocated) buffer is returned, NULL + if the string could not be extracted. + */ +char * _SC_cfstring_to_cstring (CFStringRef cfstr, + char *buf, + int bufLen, + CFStringEncoding encoding); + /* @function SCLog @discussion Conditionally issue a log message. @@ -95,7 +201,7 @@ void SCLog (Boolean condition, @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 + @result The message will be written to the specified stream stream. */ void SCPrint (Boolean condition, @@ -103,6 +209,20 @@ void SCPrint (Boolean condition, CFStringRef formatString, ...); +/* + @function SCTrace + @discussion Conditionally issue a debug message with a time stamp. + @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 message will be written to the specified stream + stream. + */ +void SCTrace (Boolean condition, + FILE *stream, + CFStringRef formatString, + ...); + __END_DECLS #endif /* _SCPRIVATE_H */ diff --git a/SystemConfiguration.fproj/SCProxies.c b/SystemConfiguration.fproj/SCProxies.c index 2574512..5606ddc 100644 --- a/SystemConfiguration.fproj/SCProxies.c +++ b/SystemConfiguration.fproj/SCProxies.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -50,7 +53,7 @@ SCDynamicStoreCopyProxies(SCDynamicStoreRef store) if (!store) { store = SCDynamicStoreCreate(NULL, - CFSTR("SCDynamicStoreCopyConsoleUser"), + CFSTR("SCDynamicStoreCopyProxies"), NULL, NULL); if (!store) { diff --git a/SystemConfiguration.fproj/SCValidation.h b/SystemConfiguration.fproj/SCValidation.h index 272cdc5..254c0a4 100644 --- a/SystemConfiguration.fproj/SCValidation.h +++ b/SystemConfiguration.fproj/SCValidation.h @@ -2,21 +2,24 @@ * Copyright (c) 2001-2002 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/SystemConfiguration.fproj/SystemConfiguration.h b/SystemConfiguration.fproj/SystemConfiguration.h index 3467ba6..5278005 100644 --- a/SystemConfiguration.fproj/SystemConfiguration.h +++ b/SystemConfiguration.fproj/SystemConfiguration.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -104,7 +107,7 @@ enum { /* * SCNetwork status codes */ - kSCStatusReachabilityUnknown = 4001, /* Network reachability cannot be determined */ + kSCStatusReachabilityUnknown = 4001 /* Network reachability cannot be determined */ }; @@ -120,8 +123,10 @@ enum { /* store and preference scheme definitions */ #include -/* "network reachability" APIs */ +/* network reachability / connection APIs */ #include +#include +#include __BEGIN_DECLS diff --git a/SystemConfiguration.fproj/config.defs b/SystemConfiguration.fproj/config.defs index af98b56..943de07 100644 --- a/SystemConfiguration.fproj/config.defs +++ b/SystemConfiguration.fproj/config.defs @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -39,13 +42,13 @@ serverprefix _; import "config_types.h"; /* - * serialized XML data (client->server) + * serialized XML or UTF8 data (client->server) */ type xmlData = ^ array [] of MACH_MSG_TYPE_BYTE ctype : xmlData_t; /* - * serialized XML data (server->client) + * serialized XML or UTF8 data (server->client) */ type xmlDataOut = ^ array [] of MACH_MSG_TYPE_BYTE ctype : xmlDataOut_t; @@ -177,7 +180,11 @@ routine notifyviasignal ( server : mach_port_t; routine notifycancel ( server : mach_port_t; out status : int); - skip; /* reserved for future use */ +routine notifyset ( server : mach_port_t; + keys : xmlData; + patterns : xmlData; + out status : int); + skip; /* reserved for future use */ skip; /* reserved for future use */ skip; /* reserved for future use */ diff --git a/SystemConfiguration.fproj/config_types.h b/SystemConfiguration.fproj/config_types.h index 2351837..4508412 100644 --- a/SystemConfiguration.fproj/config_types.h +++ b/SystemConfiguration.fproj/config_types.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -34,7 +37,7 @@ /* * Mach server port name */ -#define SCD_SERVER "System Configuration Server" +#define SCD_SERVER "com.apple.SystemConfiguration.configd" /* * Input arguments: serialized key's, list delimiters, ... diff --git a/SystemConfiguration.fproj/dy_framework.c b/SystemConfiguration.fproj/dy_framework.c index d772f97..a104dec 100644 --- a/SystemConfiguration.fproj/dy_framework.c +++ b/SystemConfiguration.fproj/dy_framework.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -32,7 +35,6 @@ #include #include #include -#include #include "dy_framework.h" @@ -176,3 +178,57 @@ _IOServiceMatching(const char *name) } return dyfunc ? dyfunc(name) : NULL; } + +static void * +__loadSecurity(void) { + static const void *image = NULL; + if (NULL == image) { + const char *framework = "/System/Library/Frameworks/Security.framework/Security"; + struct stat statbuf; + const char *suffix = getenv("DYLD_IMAGE_SUFFIX"); + char path[MAXPATHLEN]; + + strcpy(path, framework); + if (suffix) strcat(path, suffix); + if (0 <= stat(path, &statbuf)) { + image = NSAddImage(path, NSADDIMAGE_OPTION_NONE); + } else { + image = NSAddImage(framework, NSADDIMAGE_OPTION_NONE); + } + } + return (void *)image; +} + + +__private_extern__ OSStatus +_SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass *itemClass, SecKeychainAttributeList *attrList, UInt32 *length, void **outData) +{ + static OSStatus (*dyfunc)(SecKeychainItemRef, SecItemClass *, SecKeychainAttributeList *, UInt32 *, void **) = NULL; + if (!dyfunc) { + void *image = __loadSecurity(); + if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_SecKeychainItemCopyContent", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND)); + } + return dyfunc ? dyfunc(itemRef, itemClass, attrList, length, outData) : -1; +} + +__private_extern__ OSStatus +_SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef *itemRef) +{ + static OSStatus (*dyfunc)(SecKeychainSearchRef, SecKeychainItemRef *) = NULL; + if (!dyfunc) { + void *image = __loadSecurity(); + if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_SecKeychainSearchCopyNext", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND)); + } + return dyfunc ? dyfunc(searchRef, itemRef) : -1; +} + +__private_extern__ OSStatus +_SecKeychainSearchCreateFromAttributes(CFTypeRef keychainOrArray, SecItemClass itemClass, const SecKeychainAttributeList *attrList, SecKeychainSearchRef *searchRef) +{ + static OSStatus (*dyfunc)(CFTypeRef, SecItemClass, const SecKeychainAttributeList *, SecKeychainSearchRef *) = NULL; + if (!dyfunc) { + void *image = __loadSecurity(); + if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_SecKeychainSearchCreateFromAttributes", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND)); + } + return dyfunc ? dyfunc(keychainOrArray, itemClass, attrList, searchRef) : -1; +} diff --git a/SystemConfiguration.fproj/dy_framework.h b/SystemConfiguration.fproj/dy_framework.h index c53da68..bcc656c 100644 --- a/SystemConfiguration.fproj/dy_framework.h +++ b/SystemConfiguration.fproj/dy_framework.h @@ -2,21 +2,24 @@ * Copyright (c) 2002 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -28,6 +31,7 @@ #include #include #include +#include __BEGIN_DECLS @@ -106,6 +110,32 @@ _IOServiceMatching ( ); #define IOServiceMatching _IOServiceMatching +OSStatus +_SecKeychainItemCopyContent ( + SecKeychainItemRef itemRef, + SecItemClass *itemClass, + SecKeychainAttributeList *attrList, + UInt32 *length, + void **outData + ); +#define SecKeychainItemCopyContent _SecKeychainItemCopyContent + +OSStatus +_SecKeychainSearchCopyNext ( + SecKeychainSearchRef searchRef, + SecKeychainItemRef *itemRef + ); +#define SecKeychainSearchCopyNext _SecKeychainSearchCopyNext + +OSStatus +_SecKeychainSearchCreateFromAttributes ( + CFTypeRef keychainOrArray, + SecItemClass itemClass, + const SecKeychainAttributeList *attrList, + SecKeychainSearchRef *searchRef + ); +#define SecKeychainSearchCreateFromAttributes _SecKeychainSearchCreateFromAttributes + __END_DECLS #endif /* _DY_FRAMEWORK_H */ diff --git a/SystemConfiguration.fproj/genSCPreferences.c b/SystemConfiguration.fproj/genSCPreferences.c index c4e845c..c6573ab 100644 --- a/SystemConfiguration.fproj/genSCPreferences.c +++ b/SystemConfiguration.fproj/genSCPreferences.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -30,7 +33,13 @@ /* * Modification History * - * June 1, 2001 Allan Nathanson + * 16 July 2003 Allan Nathanson (ajn@apple.com) + * - changes to facilitate cross-compilation to earlier releases + * + * 5 May 2003 Allan Nathanson (ajn@apple.com) + * - switch back to "extern const CFStringRef ..." + * + * 1 June 2001 Allan Nathanson * - public API conversion * * 27 Apr 2001 Allan Nathanson (ajn@apple.com) @@ -47,25 +56,28 @@ char copyright_string[] = "/*\n" -" * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.\n" +" * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.\n" " *\n" -" * @APPLE_LICENSE_HEADER_START@\n" -" * \n" -" * The contents of this file constitute Original Code as defined in and\n" -" * are subject to the Apple Public Source License Version 1.1 (the\n" -" * \"License\"). You may not use this file except in compliance with the\n" -" * License. Please obtain a copy of the License at\n" -" * http://www.apple.com/publicsource and read it before using this file.\n" -" * \n" -" * This Original Code and all software distributed under the License are\n" -" * distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY KIND, EITHER\n" -" * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,\n" -" * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,\n" -" * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the\n" -" * License for the specific language governing rights and limitations\n" -" * under the License.\n" -" * \n" -" * @APPLE_LICENSE_HEADER_END@\n" +" * @APPLE_LICENSE_HEADER_START@ +" * +" * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. +" * +" * This file contains Original Code and/or Modifications of Original Code +" * as defined in and that are subject to the Apple Public Source License +" * Version 2.0 (the 'License'). You may not use this file except in +" * compliance with the License. Please obtain a copy of the License at +" * http://www.opensource.apple.com/apsl/ and read it before using this +" * file. +" * +" * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. +" * Please see the License for the specific language governing rights and +" * limitations under the License. +" * +" * @APPLE_LICENSE_HEADER_END@ " */\n"; @@ -78,6 +90,8 @@ typedef enum { END } controlType; +#define SC_SCHEMA_DECLARATION "SC_SCHEMA_DECLARATION" + #define KEY_PREFIX "kSC" #define COMP "Comp" @@ -106,8 +120,10 @@ typedef enum { #define CFNUMBER_BOOL "CFNumber (0 or 1)" #define CFSTRING "CFString" +#define ACSPENABLED "ACSPEnabled" // Apple Client Server Protocol #define ACTIVE "Active" #define ADDRESSES "Addresses" +#define AFTER "After" #define AIRPORT "AirPort" #define ALERT "Alert" #define ALLOWNETCREATION "AllowNetCreation" @@ -116,6 +132,7 @@ typedef enum { #define APPLETALK "AppleTalk" #define AUTH "Auth" #define AUTOMATIC "Automatic" +#define BEFORE "Before" #define BINDINGMETHODS "BindingMethods" #define BOOTP "BOOTP" #define BROADCAST "Broadcast" @@ -152,11 +169,13 @@ typedef enum { #define DISCONNECTONIDLETIMER "DisconnectOnIdleTimer" #define DISCONNECTONLOGOUT "DisconnectOnLogout" #define DISCONNECTONSLEEP "DisconnectOnSleep" +#define DISCONNECTTIME "DisconnectTime" #define DISPLAYTERMINALWINDOW "DisplayTerminalWindow" #define DNS "DNS" #define DOMAIN "Domain" #define DOMAINNAME "DomainName" #define DOMAINSEPARATOR "DomainSeparator" +#define EAP "EAP" #define ECHOENABLED "EchoEnabled" #define ECHOFAILURE "EchoFailure" #define ECHOINTERVAL "EchoInterval" @@ -167,6 +186,8 @@ typedef enum { #define ETHERNET "Ethernet" #define EXCEPTIONSLIST "ExceptionsList" #define FILE "File" +#define FIREWIRE "FireWire" +#define FLAGS "Flags" #define FTPENABLE "FTPEnable" #define FTPPASSIVE "FTPPassive" #define FTPPORT "FTPPort" @@ -193,10 +214,14 @@ typedef enum { #define INTERFACE "Interface" #define INTERFACENAME "InterfaceName" #define INTERFACES "Interfaces" +#define IP "IP" #define IPCP "IPCP" #define IPV4 "IPv4" #define IPV6 "IPv6" +#define IPSEC "IPSec" #define JOINMODE "JoinMode" +#define KEYCHAIN "Keychain" +#define L2TP "L2TP" #define LASTCAUSE "LastCause" #define LASTUPDATED "LastUpdated" #define LCP "LCP" @@ -210,6 +235,8 @@ typedef enum { #define OPTIONS "Options" #define MODEM "Modem" #define MRU "MRU" +#define MSCHAP1 "MSCHAP1" +#define MSCHAP2 "MSCHAP2" #define MTU "MTU" #define NAME "Name" #define NETINFO "NetInfo" @@ -234,9 +261,11 @@ typedef enum { #define PPTP "PPTP" #define PREFERRED "Preferred" #define PREFERREDNETWORK "PreferredNetwork" +#define PREFIXLENGTH "PrefixLength" #define PREFS "Prefs" #define PRIMARYINTERFACE "PrimaryInterface" #define PRIMARYSERVICE "PrimaryService" +#define PROMPT "Prompt" #define PROTOCOL "Protocol" #define PROXIES "Proxies" #define PULSEDIAL "PulseDial" @@ -245,11 +274,14 @@ typedef enum { #define REDIALCOUNT "RedialCount" #define REDIALENABLED "RedialEnabled" #define REDIALINTERVAL "RedialInterval" +#define RELAY "Relay" #define REMINDER "Reminder" #define REMINDERTIME "ReminderTime" #define REMOTEADDRESS "RemoteAddress" +#define RETRYCONNECTTIME "RetryConnectTime" #define ROOTSEPARATOR "RootSeparator" #define ROUTER "Router" +#define ROUTERADVERTISEMENT "RouterAdvertisement" #define RTSPENABLE "RTSPEnable" #define RTSPPORT "RTSPPort" #define RTSPPROXY "RTSPProxy" @@ -266,6 +298,7 @@ typedef enum { #define SESSIONTIMER "SessionTimer" #define SETS "Sets" #define SETUP "Setup" +#define SHAREDSECRET "SharedSecret" #define SOCKSENABLE "SOCKSEnable" #define SOCKSPORT "SOCKSPort" #define SOCKSPROXY "SOCKSProxy" @@ -274,6 +307,7 @@ typedef enum { #define SPEED "Speed" #define STATE "State" #define STATUS "Status" +#define STF "6to4" #define STRONGEST "Strongest" #define SUBNETMASKS "SubnetMasks" #define SUBTYPE "SubType" @@ -281,6 +315,7 @@ typedef enum { #define SYSTEM "System" #define TERMINALSCRIPT "TerminalScript" #define TRANSMITACCM "TransmitACCM" +#define TRANSPORT "Transport" #define TYPE "Type" #define UID "UID" #define USERDEFINEDNAME "UserDefinedName" @@ -291,10 +326,10 @@ typedef enum { struct { int control; - unsigned char * prefix; - unsigned char * key; - unsigned char * value; - unsigned char * type; + const char * prefix; + const char * key; + const char * value; + const char * type; } names[] = { { COMMENT, "/*\n * Reserved Keys\n */", NULL, NULL }, { REGULAR, RESV, LINK, "__LINK__", CFSTRING }, @@ -335,16 +370,21 @@ struct { { DEFINE , NETENT, DHCP, NULL, CFDICTIONARY }, { REGULAR, NETENT, DNS, NULL, CFDICTIONARY }, { REGULAR, NETENT, ETHERNET, NULL, CFDICTIONARY }, + { DEFINE , NETENT, FIREWIRE, NULL, CFDICTIONARY }, { REGULAR, NETENT, INTERFACE, NULL, CFDICTIONARY }, { REGULAR, NETENT, IPV4, NULL, CFDICTIONARY }, { REGULAR, NETENT, IPV6, NULL, CFDICTIONARY }, + { DEFINE , NETENT, L2TP, 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 }, + { DEFINE , NETENT, PPPSERIAL, NULL, CFDICTIONARY }, + { DEFINE , NETENT, PPTP, NULL, CFDICTIONARY }, { REGULAR, NETENT, PROXIES, NULL, CFDICTIONARY }, + { DEFINE , NETENT, STF, NULL, CFDICTIONARY }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/*\n * " KEY_PREFIX COMP NETWORK " Properties\n */", NULL }, @@ -371,10 +411,14 @@ struct { { DEFINE , NETPROP AIRPORT, SAVEPASSWORDS, NULL, CFNUMBER_BOOL }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/* " KEY_PREFIX NETPROP AIRPORT JOINMODE " values */", NULL, NULL, NULL }, + { DEFINE , NETVAL AIRPORT JOINMODE, AUTOMATIC, NULL, NULL }, { DEFINE , NETVAL AIRPORT JOINMODE, PREFERRED, NULL, NULL }, { DEFINE , NETVAL AIRPORT JOINMODE, RECENT, NULL, NULL }, { DEFINE , NETVAL AIRPORT JOINMODE, STRONGEST, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, + { COMMENT, "/* " KEY_PREFIX NETPROP AIRPORT PASSWORD ENCRYPTION " values */", NULL, NULL, NULL }, + { DEFINE , NETVAL AIRPORT AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL }, + { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/*\n * " KEY_PREFIX NETENT APPLETALK " Entity Keys\n */", NULL, NULL, NULL }, { REGULAR, NETPROP APPLETALK, COMPUTERNAME, NULL, CFSTRING }, @@ -406,6 +450,10 @@ struct { { DEFINE , NETPROP ETHERNET, MTU, NULL, CFNUMBER }, { COMMENT, "", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT FIREWIRE " (Hardware) Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL }, + { COMMENT, "", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT INTERFACE " Entity Keys\n */", NULL }, { REGULAR, NETPROP INTERFACE, DEVICENAME, NULL, CFSTRING }, { REGULAR, NETPROP INTERFACE, HARDWARE, NULL, CFSTRING }, @@ -415,12 +463,15 @@ struct { { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/* " KEY_PREFIX NETPROP INTERFACE TYPE " values */", NULL, NULL, NULL }, { REGULAR, NETVAL INTERFACE TYPE, ETHERNET, NULL, NULL }, + { DEFINE , NETVAL INTERFACE TYPE, FIREWIRE, NULL, NULL }, { REGULAR, NETVAL INTERFACE TYPE, PPP, NULL, NULL }, + { DEFINE , NETVAL INTERFACE TYPE, STF, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/* " KEY_PREFIX NETPROP SERVICE SUBTYPE " values (for " PPP ") */", NULL, NULL, NULL }, { REGULAR, NETVAL INTERFACE SUBTYPE, PPPOE, NULL, NULL }, { REGULAR, NETVAL INTERFACE SUBTYPE, PPPSERIAL, NULL, NULL }, { DEFINE , NETVAL INTERFACE SUBTYPE, PPTP, NULL, NULL }, + { DEFINE , NETVAL INTERFACE SUBTYPE, L2TP, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/*\n * " KEY_PREFIX NETENT IPV4 " Entity Keys\n */", NULL, NULL, NULL }, @@ -444,6 +495,20 @@ struct { { 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 }, + { DEFINE , NETPROP IPV6, DESTADDRESSES, NULL, CFARRAY_CFSTRING }, + { DEFINE , NETPROP IPV6, FLAGS, NULL, CFNUMBER }, + { DEFINE , NETPROP IPV6, PREFIXLENGTH, NULL, CFARRAY_CFNUMBER }, + { DEFINE , NETPROP IPV6, ROUTER, NULL, CFSTRING }, + { COMMENT, "", NULL, NULL, NULL }, + { COMMENT, "/* " KEY_PREFIX NETPROP IPV6 CONFIGMETHOD " values */", NULL, NULL, NULL }, + { DEFINE , NETVAL IPV6 CONFIGMETHOD, AUTOMATIC, NULL, NULL }, + { DEFINE , NETVAL IPV6 CONFIGMETHOD, MANUAL, NULL, NULL }, + { DEFINE , NETVAL IPV6 CONFIGMETHOD, ROUTERADVERTISEMENT, NULL, NULL }, + { DEFINE , NETVAL IPV6 CONFIGMETHOD, STF, NULL, NULL }, + { COMMENT, "", NULL, NULL, NULL }, + + { COMMENT, "/*\n * " KEY_PREFIX NETENT STF " Entity Keys\n */", NULL, NULL, NULL }, + { DEFINE , NETPROP STF, RELAY, NULL, CFSTRING }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/*\n * " KEY_PREFIX NETENT LINK " Entity Keys\n */", NULL, NULL, NULL }, @@ -493,6 +558,7 @@ struct { { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/*\n * " KEY_PREFIX NETENT PPP " Entity Keys\n */", NULL, NULL, NULL }, + { DEFINE , NETPROP PPP, ACSPENABLED, NULL, CFNUMBER_BOOL }, { DEFINE , NETPROP PPP, CONNECTTIME, NULL, CFNUMBER }, { DEFINE , NETPROP PPP, DEVICE LASTCAUSE, NULL, CFNUMBER }, { REGULAR, NETPROP PPP, DIALONDEMAND, NULL, CFNUMBER_BOOL }, @@ -500,25 +566,39 @@ struct { { REGULAR, NETPROP PPP, DISCONNECTONIDLETIMER, NULL, CFNUMBER }, { REGULAR, NETPROP PPP, DISCONNECTONLOGOUT, NULL, CFNUMBER_BOOL }, { DEFINE , NETPROP PPP, DISCONNECTONSLEEP, NULL, CFNUMBER_BOOL }, + { DEFINE , NETPROP PPP, DISCONNECTTIME, NULL, CFNUMBER }, { REGULAR, NETPROP PPP, IDLEREMINDERTIMER, NULL, CFNUMBER }, { REGULAR, NETPROP PPP, IDLEREMINDER, NULL, CFNUMBER_BOOL }, { DEFINE , NETPROP PPP, LASTCAUSE, NULL, CFNUMBER }, { REGULAR, NETPROP PPP, LOGFILE, NULL, CFSTRING }, { DEFINE , NETPROP PPP, PLUGINS, NULL, CFARRAY_CFSTRING }, + { DEFINE , NETPROP PPP, RETRYCONNECTTIME, NULL, CFNUMBER }, { DEFINE , NETPROP PPP, SESSIONTIMER, NULL, CFNUMBER }, - { DEFINE , NETPROP PPP, STATUS, NULL, CFSTRING }, + { DEFINE , NETPROP PPP, STATUS, NULL, CFNUMBER }, { DEFINE , NETPROP PPP, USE SESSIONTIMER, NULL, CFNUMBER_BOOL }, { REGULAR, NETPROP PPP, VERBOSELOGGING, NULL, CFNUMBER_BOOL }, { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/* " AUTH ": */", NULL, NULL, NULL }, + { DEFINE , NETPROP PPP, AUTH EAP PLUGINS, NULL, CFARRAY_CFSTRING }, { REGULAR, NETPROP PPP, AUTH NAME, NULL, CFSTRING }, { REGULAR, NETPROP PPP, AUTH PASSWORD, NULL, CFSTRING }, { REGULAR, NETPROP PPP, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING }, + { DEFINE , NETPROP PPP, AUTH PROMPT, NULL, CFSTRING }, { REGULAR, NETPROP PPP, AUTH PROTOCOL, NULL, CFARRAY_CFSTRING }, { COMMENT, "", NULL, NULL, NULL }, + { COMMENT, "/* " KEY_PREFIX NETPROP PPP AUTH PASSWORD ENCRYPTION " values */", NULL, NULL, NULL }, + { DEFINE , NETVAL PPP AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL }, + { COMMENT, "", NULL, NULL, NULL }, + { COMMENT, "/* " KEY_PREFIX NETPROP PPP AUTH PROMPT " values */", NULL, NULL, NULL }, + { DEFINE , NETVAL PPP AUTH PROMPT, BEFORE, NULL, CFSTRING }, + { DEFINE , NETVAL PPP AUTH PROMPT, AFTER, NULL, CFSTRING }, + { COMMENT, "", NULL, NULL, NULL }, { COMMENT, "/* " KEY_PREFIX NETPROP PPP AUTH PROTOCOL " values */", NULL, NULL, NULL }, { REGULAR, NETVAL PPP AUTH PROTOCOL, CHAP, NULL, CFSTRING }, + { DEFINE , NETVAL PPP AUTH PROTOCOL, EAP, NULL, CFSTRING }, + { DEFINE , NETVAL PPP AUTH PROTOCOL, MSCHAP1, NULL, CFSTRING }, + { DEFINE , NETVAL PPP AUTH PROTOCOL, MSCHAP2, NULL, CFSTRING }, { REGULAR, NETVAL PPP AUTH PROTOCOL, PAP, NULL, CFSTRING }, { COMMENT, "\n/* " COMM ": */", NULL, NULL, NULL }, @@ -558,6 +638,23 @@ struct { { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, + { COMMENT, "/*\n * " KEY_PREFIX NETENT PPTP " Entity Keys\n */", NULL, NULL, NULL }, + { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL }, + { COMMENT, "", NULL, NULL, NULL }, + + { COMMENT, "/*\n * " KEY_PREFIX NETENT L2TP " Entity Keys\n */", NULL, NULL, NULL }, + { DEFINE , NETPROP L2TP, IPSEC SHAREDSECRET, NULL, CFSTRING }, + { DEFINE , NETPROP L2TP, IPSEC SHAREDSECRET ENCRYPTION, NULL, CFSTRING }, + { DEFINE , NETPROP L2TP, TRANSPORT, NULL, CFSTRING }, + { COMMENT, "", NULL, NULL, NULL }, + { COMMENT, "/* " KEY_PREFIX NETPROP L2TP IPSEC SHAREDSECRET ENCRYPTION " values */", NULL, NULL, NULL }, + { DEFINE , NETVAL L2TP IPSEC SHAREDSECRET ENCRYPTION, KEYCHAIN, NULL, NULL }, + { COMMENT, "", NULL, NULL, NULL }, + { COMMENT, "/* " KEY_PREFIX NETPROP L2TP TRANSPORT " values */", NULL, NULL, NULL }, + { DEFINE , NETVAL L2TP TRANSPORT, IP, NULL, NULL }, + { DEFINE , NETVAL L2TP TRANSPORT, IPSEC, NULL, NULL }, + { COMMENT, "", 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 }, @@ -585,12 +682,6 @@ struct { { REGULAR, USERSENT, CONSOLEUSER, NULL, NULL }, { COMMENT, "", NULL, NULL, NULL }, - { 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 * " KEY_PREFIX COMP SYSTEM " Properties\n */", NULL, NULL, NULL }, { REGULAR, SYSTEMPROP, COMPUTERNAME, NULL, CFSTRING }, { REGULAR, SYSTEMPROP, COMPUTERNAME ENCODING, NULL, CFNUMBER }, @@ -617,31 +708,43 @@ struct { { 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 }, + { COMMENT, "/*\n * Obsolete schema definitions which will be removed \"soon\".\n */", NULL }, + { OBSOLETE, USERSPROP CONSOLEUSER, NAME, NULL, CFSTRING }, + { OBSOLETE, USERSPROP CONSOLEUSER, UID, NULL, CFNUMBER }, + { OBSOLETE, USERSPROP CONSOLEUSER, GID, NULL, CFNUMBER }, + { COMMENT, "", NULL, NULL, NULL }, { END, NULL, NULL, NULL, NULL }, }; +static inline void +setmax(int *max, char **maxstr, char *str) +{ + int l; + + l = strlen(str); + if (l > *max) { + if (*maxstr) free(*maxstr); + *maxstr = strdup(str); + *max = l; + } + return; +} + enum { - gen_extern_e, - gen_init_e, gen_header_e, + gen_hfile_e, + gen_cfile_e, }; void dump_names(int type) { int i; + int maxkbuf = 0; + char *maxkstr = NULL; + int maxvbuf = 0; + char *maxvstr = NULL; for (i = 0; TRUE; i++) { switch (names[i].control) { @@ -650,9 +753,14 @@ dump_names(int type) break; } case COMMENT: { - if (type != gen_extern_e && type != gen_init_e) { + switch (type) { + case gen_header_e: + case gen_hfile_e: if (names[i].prefix) printf("%s\n", names[i].prefix); + break; + default: + break; } break; } @@ -679,6 +787,31 @@ dump_names(int type) printf("#define %-40s %-40s\n", kbuf, vbuf); break; + case gen_hfile_e: + snprintf(kbuf, sizeof(kbuf), "(" KEY_PREFIX "%s%s);", + names[i].prefix, names[i].key); + setmax(&maxkbuf, &maxkstr, kbuf); + + snprintf(vbuf, sizeof(vbuf), "\"%s\"", + names[i].value ? names[i].value : names[i].key); + setmax(&maxvbuf, &maxvstr, vbuf); + + printf("SC_SCHEMA_DECLARATION%-42s /* %-17s %-30s */\n", + kbuf, + names[i].type ? names[i].type : "", + vbuf); + break; + case gen_cfile_e: + snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", + names[i].prefix, names[i].key); + + if (names[i].value) + printf("const CFStringRef %-45s = CFSTR(\"%s\");\n", + kbuf, names[i].value); + else + printf("const CFStringRef %-45s = CFSTR(\"%s\");\n", + kbuf, names[i].key); + break; default: break; } @@ -707,21 +840,29 @@ dump_names(int type) printf("#define %-40s %-40s\n", kbuf, vbuf); break; - case gen_extern_e: - snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", + case gen_hfile_e: + snprintf(kbuf, sizeof(kbuf), "(" KEY_PREFIX "%s%s);", names[i].prefix, names[i].key); + setmax(&maxkbuf, &maxkstr, kbuf); - printf("volatile CFStringRef " KEY_PREFIX "%s%s = NULL;\n", - names[i].prefix, names[i].key); + snprintf(vbuf, sizeof(vbuf), "\"%s\"", + names[i].value ? names[i].value : names[i].key); + setmax(&maxvbuf, &maxvstr, vbuf); + + printf("SC_SCHEMA_DECLARATION%-42s /* %-17s %-30s */\n", + kbuf, + names[i].type ? names[i].type : "", + vbuf); break; - case gen_init_e: + case gen_cfile_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", + printf("const CFStringRef %-45s = CFSTR(\"%s\");\n", kbuf, names[i].value); else - printf(" *((void **)&%s) = (void *)CFSTR(\"%s\");\n", + printf("const CFStringRef %-45s = CFSTR(\"%s\");\n", kbuf, names[i].key); break; default: @@ -730,25 +871,33 @@ dump_names(int type) break; } case OBSOLETE: { + static int nObsolete = 0; char kbuf[256]; + char vbuf[256]; switch (type) { - case gen_extern_e: - snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", - names[i].prefix, names[i].key); + case gen_hfile_e: + if (nObsolete++ == 0) { + printf("#ifndef SCSTR\n"); + printf("#include \n"); + printf("#define SCSTR(s) CFSTR(s)\n"); + printf("#endif\n"); + } - 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); + snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")", + names[i].value); else - printf(" *((void **)&%s) = (void *)CFSTR(\"%s\");\n", - kbuf, names[i].key); + snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")", + names[i].key); + + printf("#define %-40s %-40s /* %s */\n", + kbuf, + vbuf, + names[i].type ? names[i].type : ""); break; default: break; @@ -758,14 +907,26 @@ dump_names(int type) case FUTURE: { char kbuf[256]; - if (type == gen_header_e) { + switch (type) { + case gen_header_e: snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s", names[i].prefix, names[i].key); - printf("/* #define %-37s %-40s /* %s */\n", + printf("// #define %-37s %-40s /* %s */\n", kbuf, "SCSTR(\"???\") */", "RESERVED FOR FUTURE USE"); + break; + case gen_hfile_e: + snprintf(kbuf, sizeof(kbuf), "(" KEY_PREFIX "%s%s);", + names[i].prefix, names[i].key); + setmax(&maxkbuf, &maxkstr, kbuf); + + printf("// SC_SCHEMA_DECLARATION%-39s /* %s */\n", + kbuf, "RESERVED FOR FUTURE USE"); + break; + default: + break; } break; } @@ -775,6 +936,12 @@ dump_names(int type) } } done: + switch (type) { + case gen_hfile_e: + fprintf(stderr, "max key: length = %2d, string = %s\n", maxkbuf, maxkstr); + fprintf(stderr, "max val: length = %2d, string = %s\n", maxvbuf, maxvstr); + break; + } return; } @@ -786,7 +953,7 @@ main(int argc, char * argv[]) if (argc >= 2) type = argv[1]; - if (strcmp(type, "header") == 0) { + if (strcmp(type, "header-x") == 0) { printf("%s\n", copyright_string); printf("/*\n * This file is automatically generated\n * DO NOT EDIT!\n */\n\n"); @@ -798,7 +965,7 @@ main(int argc, char * argv[]) printf(" * #import \n"); printf(" */\n\n"); - printf("#ifndef _SCSCHEMADEFINITIONS_H\n#define _SCSCHEMADEFINITIONS_H\n\n"); + printf("#ifndef _SCSCHEMADEFINITIONS_10_1_H\n#define _SCSCHEMADEFINITIONS_10_1_H\n\n"); printf("#ifndef SCSTR\n"); printf("#include \n"); @@ -807,6 +974,42 @@ main(int argc, char * argv[]) printf("\n"); dump_names(gen_header_e); + printf("#endif /* _SCSCHEMADEFINITIONS_10_1_H */\n"); + } + else 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("/*\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 " SC_SCHEMA_DECLARATION "(x)\t\textern NSString * x\n"); + printf(" * #import \n"); + printf(" */\n\n"); + + printf("#ifndef _SCSCHEMADEFINITIONS_H\n#define _SCSCHEMADEFINITIONS_H\n\n"); + + printf("#ifndef SC_SCHEMA_DECLARATION\n"); + printf("#ifndef SCSTR\n"); + printf("#include \n"); + printf("#define " SC_SCHEMA_DECLARATION "(x)\textern const CFStringRef x\n"); + printf("#else\n"); + printf("#import \n"); + printf("#define " SC_SCHEMA_DECLARATION "(x)\textern NSString * x\n"); + printf("#endif\n"); + printf("#endif\n"); + + printf("\n"); + dump_names(gen_hfile_e); + + printf("#include \n"); + printf("#if MAC_OS_X_VERSION_10_3 > MAC_OS_X_VERSION_MIN_REQUIRED\n"); + printf(" #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED\n"); + printf(" #include \n"); + printf(" #endif\n"); + printf("#endif\n\n"); + printf("#endif /* _SCSCHEMADEFINITIONS_H */\n"); } else if (strcmp(type, "cfile") == 0) { @@ -817,20 +1020,7 @@ main(int argc, char * argv[]) printf("\n"); printf("#include \n"); printf("\n"); - dump_names(gen_extern_e); - 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"); + dump_names(gen_cfile_e); } exit(0); return (0); diff --git a/SystemConfiguration.fproj/moh.c b/SystemConfiguration.fproj/moh.c index 659e470..546c70e 100644 --- a/SystemConfiguration.fproj/moh.c +++ b/SystemConfiguration.fproj/moh.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -33,7 +36,6 @@ #include #include #include -#include #include #include @@ -131,7 +133,7 @@ __private_extern__ int MOHExec(int ref, u_long link, - u_int32_t cmd, + uint32_t cmd, void *request, u_long requestLen, void **reply, @@ -161,7 +163,7 @@ MOHExec(int ref, if (n == -1) { SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec writen() failed: %s"), strerror(errno)); return errno; - } else if (n != requestLen) { + } else if (n != (ssize_t)requestLen) { SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec writen() failed: wrote=%d"), n); return -1; } @@ -186,7 +188,7 @@ MOHExec(int ref, SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec readn() failed: error=%s"), strerror(errno)); CFAllocatorDeallocate(NULL, buf); return errno; - } else if (n != msg.m_len) { + } else if (n != (ssize_t)msg.m_len) { SCLog(_sc_verbose, LOG_ERR, CFSTR("MOHExec readn() failed: insufficent data, read=%d"), n); CFAllocatorDeallocate(NULL, buf); return -1; diff --git a/SystemConfiguration.fproj/moh.h b/SystemConfiguration.fproj/moh.h index 57ee428..14b54be 100644 --- a/SystemConfiguration.fproj/moh.h +++ b/SystemConfiguration.fproj/moh.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -47,7 +50,7 @@ MOHDispose ( int MOHExec (int ref, u_long link, - u_int32_t cmd, + uint32_t cmd, void *request, u_long requestLen, void **reply, diff --git a/SystemConfiguration.fproj/moh_msg.h b/SystemConfiguration.fproj/moh_msg.h index 0a3bc0f..4434db8 100644 --- a/SystemConfiguration.fproj/moh_msg.h +++ b/SystemConfiguration.fproj/moh_msg.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -31,19 +34,19 @@ /* MOH message paquets */ struct moh_msg_hdr { - u_int32_t m_type; // type of the message - u_int32_t m_result; // error code of notification message - u_int32_t m_cookie; // user param - u_int32_t m_link; // link for this message - u_int32_t m_len; // len of the following data + uint32_t m_type; // type of the message + uint32_t m_result; // error code of notification message + uint32_t m_cookie; // user param + uint32_t m_link; // link for this message + uint32_t m_len; // len of the following data }; struct moh_msg { - u_int32_t m_type; // type of the message - u_int32_t m_result; // error code of notification message - u_int32_t m_cookie; // user param, or error num for event - u_int32_t m_link; // link for this message - u_int32_t m_len; // len of the following data + uint32_t m_type; // type of the message + uint32_t m_result; // error code of notification message + uint32_t m_cookie; // user param, or error num for event + uint32_t m_link; // link for this message + uint32_t m_len; // len of the following data u_char m_data[1]; // msg data sent or received }; diff --git a/SystemConfiguration.fproj/ppp.c b/SystemConfiguration.fproj/ppp.c index df05869..12e5685 100644 --- a/SystemConfiguration.fproj/ppp.c +++ b/SystemConfiguration.fproj/ppp.c @@ -1,36 +1,45 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ /* * Modification History * - * Feb 28, 2002 Christophe Allie + * Nov 7, 2002 Allan Nathanson + * - use ServiceID *or* LinkID + * + * Oct 25, 2002 Christophe Allie + * - use ServiceID instead of LinkID + * + * Feb 28, 2002 Christophe Allie * - socket API fixes * - * Feb 10, 2001 Allan Nathanson + * Feb 10, 2001 Allan Nathanson * - cleanup API * - * Feb 2000 Christophe Allie - * - initial revision (as ppplib.c) + * Feb 2000 Christophe Allie + * - initial revision */ #include @@ -44,7 +53,7 @@ #include #include -#include "ppp_msg.h" +#include #include "ppp.h" @@ -128,39 +137,67 @@ PPPDispose(int ref) } -__private_extern__ -int +static int PPPExec(int ref, - u_long link, - u_int32_t cmd, + CFStringRef serviceID, + uint32_t link, + uint32_t cmd, + u_int16_t flags, void *request, - u_long requestLen, + uint32_t requestLen, void **reply, - u_long *replyLen) + uint32_t *replyLen) { struct ppp_msg_hdr msg; char *buf = NULL; ssize_t n; + CFDataRef sID = NULL; bzero(&msg, sizeof(msg)); - msg.m_type = cmd; - msg.m_link = link; - msg.m_len = ((request != NULL) && (requestLen > 0)) ? requestLen : 0; - // send the command - if (writen(ref, &msg, sizeof(msg)) < 0) { - SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno)); - return errno; - } + // first send request, if necessary + if (cmd) { + msg.m_type = cmd; + msg.m_flags = flags; + if (serviceID) { + sID = CFStringCreateExternalRepresentation(NULL, + serviceID, + kCFStringEncodingUTF8, + 0); + // serviceID is present, use it + msg.m_flags |= USE_SERVICEID; + msg.m_link = CFDataGetLength(sID); + } else { + // no service ID, use the requested link + msg.m_link = link; + } + msg.m_len = ((request != NULL) && (requestLen > 0)) ? requestLen : 0; - if ((request != NULL) && (requestLen > 0)) { - if (writen(ref, request, requestLen) < 0) { + // send the command + if (writen(ref, &msg, sizeof(msg)) < 0) { SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno)); + if (sID) CFRelease(sID); return errno; } + + if (sID) { + if (writen(ref, (void *)CFDataGetBytePtr(sID), msg.m_link) < 0) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno)); + CFRelease(sID); + return errno; + } + CFRelease(sID); + } + + if ((request != NULL) && (requestLen > 0)) { + if (writen(ref, request, requestLen) < 0) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno)); + return errno; + } + } } - // always expect a reply + // then read replies or incoming message n = readn(ref, &msg, sizeof(msg)); if (n == -1) { SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno)); @@ -170,6 +207,26 @@ PPPExec(int ref, return -1; } + if ((msg.m_flags & USE_SERVICEID) && msg.m_link) { + buf = CFAllocatorAllocate(NULL, msg.m_link, 0); + if (buf) { + // read reply + n = readn(ref, buf, msg.m_link); + if (n == -1) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno)); + CFAllocatorDeallocate(NULL, buf); + return errno; + } else if (n != (ssize_t)msg.m_link) { + SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno)); + CFAllocatorDeallocate(NULL, buf); + return -1; + } + // buf contains the service id we passed in the request + CFAllocatorDeallocate(NULL, buf); + buf = NULL; + } + } + if (msg.m_len) { buf = CFAllocatorAllocate(NULL, msg.m_len, 0); if (buf) { @@ -179,7 +236,7 @@ PPPExec(int ref, SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno)); CFAllocatorDeallocate(NULL, buf); return errno; - } else if (n != msg.m_len) { + } else if (n != (ssize_t)msg.m_len) { SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: insufficent data, read=%d"), n); CFAllocatorDeallocate(NULL, buf); return -1; @@ -199,195 +256,139 @@ PPPExec(int ref, } -#ifdef NOT_NEEDED +__private_extern__ int -PPPConnect(int ref, u_long link) +PPPGetLinkByInterface(int ref, char *if_name, uint32_t *link) { - int status; + void *replyBuf = NULL; + uint32_t replyBufLen = 0; + int status; status = PPPExec(ref, - link, - PPP_CONNECT, NULL, + -1, + PPP_GETLINKBYIFNAME, 0, - NULL, - NULL); + (void *)if_name, + strlen(if_name), + &replyBuf, + &replyBufLen); if (status != 0) { - SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_CONNECT) failed: status = %d"), status); return status; } + if (replyBuf && (replyBufLen == sizeof(uint32_t))) { + *link = *(uint32_t *)replyBuf; + } else { + status = -2; /* if not found */ + } + if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf); + return status; } +__private_extern__ int -PPPDisconnect(int ref, u_long link) +PPPConnect(int ref, CFStringRef serviceID, uint32_t link, void *data, uint32_t dataLen, int linger) { int status; status = PPPExec(ref, + serviceID, link, - PPP_DISCONNECT, - NULL, - 0, + PPP_CONNECT, + CONNECT_ARBITRATED_FLAG + (linger ? 0 : CONNECT_AUTOCLOSE_FLAG), + data, + dataLen, NULL, NULL); - if (status != 0) { - SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_DISCONNECT) failed: status = %d"), status); - return status; - } - return status; } -#endif /* NOT_NEEDED */ __private_extern__ int -PPPGetNumberOfLinks(int ref, u_long *nLinks) +PPPDisconnect(int ref, CFStringRef serviceID, uint32_t link, int force) { - void *replyBuf = NULL; - u_long replyBufLen = 0; int status; status = PPPExec(ref, - -1, - PPP_GETNBLINKS, - NULL, - 0, - &replyBuf, - &replyBufLen); - if (status != 0) { - SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_GETNBLINKS) failed: status = %d"), status); - return status; - } - - *nLinks = (replyBufLen == sizeof(u_long)) ? *(u_long *)replyBuf : 0; - if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf); - + serviceID, + link, + PPP_DISCONNECT, + force ? 0 : DISCONNECT_ARBITRATED_FLAG, + NULL, + 0, + NULL, + NULL); return status; } __private_extern__ int -PPPGetLinkByIndex(int ref, int index, u_int32_t *link) +PPPSuspend(int ref, CFStringRef serviceID, uint32_t link) { - u_int32_t i = index; - void *replyBuf = NULL; - u_long replyBufLen = 0; - int status; + int status; status = PPPExec(ref, - -1, - PPP_GETLINKBYINDEX, - (void *)&i, - sizeof(i), - &replyBuf, - &replyBufLen); - if (status != 0) { - SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_GETLINKBYINDEX) failed: status = %d"), status); - return status; - } - - if (replyBuf && (replyBufLen == sizeof(u_int32_t))) { - *link = *(u_int32_t *)replyBuf; - } else { - status = -2; /* if not found */ - } - if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf); - + serviceID, + link, + PPP_SUSPEND, + 0, + NULL, + 0, + NULL, + NULL); return status; } __private_extern__ int -PPPGetLinkByServiceID(int ref, CFStringRef serviceID, u_int32_t *link) +PPPResume(int ref, CFStringRef serviceID, uint32_t link) { - int i; - u_long nLinks; - int status; - CFDataRef sID; - - sID = CFStringCreateExternalRepresentation(NULL, - serviceID, - kCFStringEncodingMacRoman, - 0); - - status = PPPGetNumberOfLinks(ref, &nLinks); - if (status != 0) { - SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPGetNumberOfLinks() failed: %d"), status); - goto done; - } - - status = -2; /* assume no link */ - - for (i=0; io_data, dataLen); status = PPPExec(ref, + serviceID, link, PPP_SETOPTION, + 0, 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) +PPPGetConnectData(int ref, CFStringRef serviceID, uint32_t link, void **data, uint32_t *dataLen) { - void *replyBuf = NULL; - u_long replyBufLen = 0; int status; + *dataLen = 0; + *data = NULL; + status = PPPExec(ref, - link, - PPP_STATUS, - NULL, - 0, - &replyBuf, - &replyBufLen); + serviceID, + link, + PPP_GETCONNECTDATA, + 0, + NULL, + 0, + data, + dataLen); + return status; +} + + +__private_extern__ +int +PPPStatus(int ref, CFStringRef serviceID, uint32_t link, struct ppp_status **stat) +{ + void *replyBuf = NULL; + uint32_t replyBufLen = 0; + int status; + + *stat = NULL; + + status = PPPExec(ref, + serviceID, + link, + PPP_STATUS, + 0, + NULL, + 0, + &replyBuf, + &replyBufLen); if (status != 0) { - SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec(PPP_STATUS) failed: status = %d"), status); return status; } @@ -460,7 +482,6 @@ PPPStatus(int ref, u_long link, struct ppp_status **stat) *stat = (struct ppp_status *)replyBuf; } else { if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf); - *stat = NULL; status = -1; } @@ -468,29 +489,99 @@ PPPStatus(int ref, u_long link, struct ppp_status **stat) } -#ifdef NOT_NEEDED __private_extern__ int -PPPEnableEvents(int ref, u_long link, u_char enable) +PPPExtendedStatus(int ref, CFStringRef serviceID, uint32_t link, void **data, uint32_t *dataLen) { int status; + *dataLen = 0; + *data = NULL; + status = PPPExec(ref, + serviceID, link, - enable ? PPP_ENABLE_EVENT : PPP_DISABLE_EVENT, + PPP_EXTENDEDSTATUS, + 0, NULL, 0, + data, + dataLen); + return status; +} + + +__private_extern__ +int +PPPEnableEvents(int ref, CFStringRef serviceID, uint32_t link, u_char enable) +{ + int status; + uint32_t lval = 2; // status notifications + + status = PPPExec(ref, + serviceID, + link, + enable ? PPP_ENABLE_EVENT : PPP_DISABLE_EVENT, + 0, + &lval, + sizeof(lval), NULL, NULL); - if (status != 0) { - SCLog(_sc_verbose, - LOG_ERR, - CFSTR("PPPExec(%s) failed: status = %d"), - enable ? "PPP_ENABLE_EVENT" : "PPP_DISABLE_EVENT", - status); - return status; + return status; +} + + +__private_extern__ +int +PPPReadEvent(int ref, uint32_t *event) +{ + + *event = PPPExec(ref, NULL, 0, 0, 0, NULL, 0, NULL, NULL); + return 0; +} + + +__private_extern__ +CFDataRef +PPPSerialize(CFPropertyListRef obj, void **data, uint32_t *dataLen) +{ + CFDataRef xml; + + xml = CFPropertyListCreateXMLData(NULL, obj); + if (xml) { + *data = (void*)CFDataGetBytePtr(xml); + *dataLen = CFDataGetLength(xml); } + return xml; +} - return status; + +__private_extern__ +CFPropertyListRef +PPPUnserialize(void *data, uint32_t dataLen) +{ + CFDataRef xml; + CFStringRef xmlError; + CFPropertyListRef ref = NULL; + + xml = CFDataCreateWithBytesNoCopy(NULL, data, dataLen, kCFAllocatorNull); + if (xml) { + ref = CFPropertyListCreateFromXMLData(NULL, + xml, + kCFPropertyListImmutable, + &xmlError); + if (!ref) { + if (xmlError) { + SCLog(TRUE, + LOG_ERR, + CFSTR("CFPropertyListCreateFromXMLData() failed: %@"), + xmlError); + CFRelease(xmlError); + } + } + + CFRelease(xml); + } + + return ref; } -#endif /* NOT_NEEDED */ diff --git a/SystemConfiguration.fproj/ppp.h b/SystemConfiguration.fproj/ppp.h index c1d18f8..4ef7c40 100644 --- a/SystemConfiguration.fproj/ppp.h +++ b/SystemConfiguration.fproj/ppp.h @@ -1,28 +1,34 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ /* * Modification History * + * Nov 7, 2002 Allan Nathanson + * - use ServiceID *or* LinkID + * * Feb 10, 2001 Allan Nathanson * - cleanup API * @@ -34,8 +40,8 @@ #define _PPP_H #include +#include #include -#include "ppp_msg.h" __BEGIN_DECLS @@ -43,56 +49,75 @@ int PPPInit (int *ref); int PPPDispose (int ref); -int PPPExec (int ref, - u_long link, - u_int32_t cmd, - void *request, - u_long requestLen, - void **reply, - u_long *replyLen); +int PPPGetLinkByInterface (int ref, + char *if_name, + uint32_t *link); -#ifdef NOT_NEEDED int PPPConnect (int ref, - u_long link); + CFStringRef serviceid, + uint32_t link, + void *data, + uint32_t dataLen, + int linger); int PPPDisconnect (int ref, - u_long link); -#endif /* NOT_NEEDED */ - -int PPPGetNumberOfLinks (int ref, - u_long *nLinks); + CFStringRef serviceid, + uint32_t link, + int force); -int PPPGetLinkByIndex (int ref, - int index, - u_int32_t *link); +int PPPSuspend (int ref, + CFStringRef serviceID, + uint32_t link); -int PPPGetLinkByServiceID (int ref, +int PPPResume (int ref, CFStringRef serviceID, - u_int32_t *link); + uint32_t link); int PPPGetOption (int ref, - u_long link, - u_long option, + CFStringRef serviceid, + uint32_t link, + uint32_t option, void **data, - u_long *dataLen); + uint32_t *dataLen); -#ifdef NOT_NEEDED int PPPSetOption (int ref, - u_long link, - u_long option, + CFStringRef serviceid, + uint32_t link, + uint32_t option, void *data, - u_long dataLen); -#endif /* NOT_NEEDED */ + uint32_t dataLen); + +int PPPGetConnectData (int ref, + CFStringRef serviceID, + uint32_t link, + void **data, + uint32_t *dataLen); int PPPStatus (int ref, - u_long link, + CFStringRef serviceid, + uint32_t link, struct ppp_status **stat); -#ifdef NOT_NEEDED +int PPPExtendedStatus (int ref, + CFStringRef serviceid, + uint32_t link, + void **data, + uint32_t *dataLen); + int PPPEnableEvents (int ref, - u_long link, + CFStringRef serviceid, + uint32_t link, u_char enable); -#endif /* NOT_NEEDED */ + +int PPPReadEvent (int ref, + uint32_t *event); + +CFDataRef PPPSerialize (CFPropertyListRef obj, + void **data, + uint32_t *dataLen); + +CFPropertyListRef PPPUnserialize (void *data, + uint32_t dataLen); __END_DECLS diff --git a/SystemConfiguration.fproj/ppp_msg.h b/SystemConfiguration.fproj/ppp_msg.h deleted file mode 100644 index 6d6d002..0000000 --- a/SystemConfiguration.fproj/ppp_msg.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2000-2002 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 _PPP_MSG_H -#define _PPP_MSG_H - -#include - -/* local socket path */ -#define PPP_PATH "/var/run/pppconfd\0" - - -/* PPP message paquets */ -struct ppp_msg_hdr { - u_int32_t m_type; // type of the message - u_int32_t m_result; // error code of notification message - u_int32_t m_cookie; // user param - u_int32_t m_link; // link for this message - u_int32_t m_len; // len of the following data -}; - -struct ppp_msg { - u_int32_t m_type; // type of the message - u_int32_t m_result; // error code of notification message - u_int32_t m_cookie; // user param, or error num for event - u_int32_t m_link; // link for this message - u_int32_t m_len; // len of the following data - u_char m_data[1]; // msg data sent or received -}; - - - -/* codes for ppp messages */ -enum { - /* API client commands */ - PPP_VERSION = 1, - PPP_STATUS, - PPP_CONNECT, - PPP_DISCONNECT = 5, - PPP_GETOPTION, - PPP_SETOPTION, - PPP_ENABLE_EVENT, - PPP_DISABLE_EVENT, - PPP_EVENT, - PPP_GETNBLINKS, - PPP_GETLINKBYINDEX - -}; - -// struct for an option -struct ppp_opt_hdr { - u_int32_t o_type; -}; - -struct ppp_opt { - u_int32_t o_type; - u_char o_data[1]; -}; - - -/* codes for options management */ -enum { - - PPP_OPT_DEV_NAME = 1, // string - PPP_OPT_DEV_SPEED, // 4 bytes - PPP_OPT_DEV_CONNECTSCRIPT, // string - - PPP_OPT_COMM_IDLETIMER, // 4 bytes - PPP_OPT_COMM_REMOTEADDR, // string - - PPP_OPT_AUTH_PROTO, // 4 bytes - PPP_OPT_AUTH_NAME, // string - PPP_OPT_AUTH_PASSWD, // string - - PPP_OPT_LCP_HDRCOMP, // 4 bytes - PPP_OPT_LCP_MRU, // 4 bytes - PPP_OPT_LCP_MTU, // 4 bytes - PPP_OPT_LCP_RCACCM, // 4 bytes - PPP_OPT_LCP_TXACCM, // 4 bytes - - PPP_OPT_IPCP_HDRCOMP, // 4 bytes - PPP_OPT_IPCP_LOCALADDR, // 4 bytes - PPP_OPT_IPCP_REMOTEADDR, // 4 bytes - - PPP_OPT_LOGFILE, // string - PPP_OPT_RESERVED, // 4 bytes - PPP_OPT_REMINDERTIMER, // 4 bytes (not implemented) - PPP_OPT_ALERTENABLE, // 4 bytes (not implemented) - - PPP_OPT_LCP_ECHO, // struct ppp_opt_echo - - PPP_OPT_COMM_CONNECTDELAY, // 4 bytes - PPP_OPT_COMM_SESSIONTIMER, // 4 bytes - PPP_OPT_COMM_TERMINALMODE, // 4 bytes - PPP_OPT_COMM_TERMINALSCRIPT, // string. Additionnal connection script, once modem is connected - PPP_OPT_DEV_CAPS, // struct ppp_caps... - - 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 store - -}; - -// options values - -// PPP_LCP_OPT_HDRCOMP -- option ppp addr/ctrl compression -enum { - PPP_LCP_HDRCOMP_NONE = 0, - PPP_LCP_HDRCOMP_ADDR = 1, - PPP_LCP_HDRCOMP_PROTO = 2 -}; - -enum { - PPP_COMM_TERM_NONE = 0, - PPP_COMM_TERM_SCRIPT, - PPP_COMM_TERM_WINDOW -}; - -enum { - PPP_IPCP_HDRCOMP_NONE = 0, - PPP_IPCP_HDRCOMP_VJ -}; - -// PPP_LCP_OPT_RCACCM -- option receive control asynchronous character map -enum { - PPP_LCP_ACCM_NONE = 0, - PPP_LCP_ACCM_XONXOFF = 0x000A0000, - PPP_LCP_ACCM_ALL = 0xFFFFFFFF -}; - -// PPP_OPT_AUTH -enum { - PPP_AUTH_NONE = 0, - PPP_AUTH_PAPCHAP, - PPP_AUTH_PAP, - PPP_AUTH_CHAP -}; - -// state machine -enum { - PPP_IDLE = 0, - PPP_INITIALIZE, - PPP_CONNECTLINK, - PPP_STATERESERVED, - PPP_ESTABLISH, - PPP_AUTHENTICATE, - PPP_CALLBACK, - PPP_NETWORK, - PPP_RUNNING, - PPP_TERMINATE, - PPP_DISCONNECTLINK, - PPP_HOLDOFF, - PPP_ONHOLD -}; - -// events -enum { - PPP_EVT_DISCONNECTED = 1, - PPP_EVT_CONNSCRIPT_STARTED, - PPP_EVT_CONNSCRIPT_FINISHED, - PPP_EVT_TERMSCRIPT_STARTED, - PPP_EVT_TERMSCRIPT_FINISHED, - PPP_EVT_LOWERLAYER_UP, - PPP_EVT_LOWERLAYER_DOWN, - PPP_EVT_LCP_UP, - PPP_EVT_LCP_DOWN, - PPP_EVT_IPCP_UP, - PPP_EVT_IPCP_DOWN, - PPP_EVT_AUTH_STARTED, - PPP_EVT_AUTH_FAILED, - PPP_EVT_AUTH_SUCCEDED -}; - -struct ppp_opt_echo { // 0 for the following value will cancel echo option - u_int16_t interval; // delay in seconds between echo requests - u_int16_t failure; // # of failure before declaring the link down -}; - -struct ppp_status { - // connection stats - u_int32_t status; - union { - struct connected { - u_int32_t timeElapsed; - u_int32_t timeRemaining; - // bytes stats - u_int32_t inBytes; - u_int32_t inPackets; - u_int32_t inErrors; - u_int32_t outBytes; - u_int32_t outPackets; - u_int32_t outErrors; - } run; - struct disconnected { - u_int32_t lastDiscCause; - } disc; - } s; -}; - -enum { - // from 0 to 255, we use bsd error codes from errno.h - - // ppp speficic error codes - PPP_ERR_GEN_ERROR = 256, - PPP_ERR_CONNSCRIPTFAILED, - PPP_ERR_TERMSCRIPTFAILED, - PPP_ERR_LCPFAILED, - PPP_ERR_AUTHFAILED, - PPP_ERR_IDLETIMEOUT, - PPP_ERR_SESSIONTIMEOUT, - PPP_ERR_LOOPBACK, - PPP_ERR_PEERDEAD, - PPP_ERR_DISCSCRIPTFAILED, - - // modem specific error codes - PPP_ERR_MOD_NOCARRIER = 512, - PPP_ERR_MOD_BUSY, - PPP_ERR_MOD_NODIALTONE, - PPP_ERR_MOD_ERROR -}; - -#endif /* _PPP_MSG_H */ - diff --git a/SystemConfiguration.fproj/v1Compatibility.c b/SystemConfiguration.fproj/v1Compatibility.c deleted file mode 100644 index 9a233ab..0000000 --- a/SystemConfiguration.fproj/v1Compatibility.c +++ /dev/null @@ -1,816 +0,0 @@ -/* - * 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 deleted file mode 100644 index a99e435..0000000 --- a/SystemConfiguration.fproj/v1Compatibility.h +++ /dev/null @@ -1,378 +0,0 @@ -/* - * 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 c7e4f8d..c6bcd09 100644 --- a/configd.tproj/Makefile +++ b/configd.tproj/Makefile @@ -13,20 +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 pattern.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\ - _confignotify.c _notifyadd.c _notifyremove.c _notifychanges.c\ - _notifyviaport.c _notifyviafd.c _notifyviasignal.c\ - _notifycancel.c _snapshot.c + session.c pattern.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 configd.plist MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles @@ -40,6 +40,7 @@ DEBUG_LIBS = $(LIBS) PROF_LIBS = $(LIBS) +NEXTSTEP_PB_LDFLAGS = -prebind_all_twolevel_modules FRAMEWORKS = -framework CoreFoundation -framework SystemConfiguration diff --git a/configd.tproj/Makefile.postamble b/configd.tproj/Makefile.postamble index ce9e54f..0bd75f1 100644 --- a/configd.tproj/Makefile.postamble +++ b/configd.tproj/Makefile.postamble @@ -64,6 +64,7 @@ # the include path (defaults to -I.) # DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags # passed to ld/libtool (defaults to nothing) +WARNING_CFLAGS=-Wall # Library and Framework projects only: @@ -98,4 +99,8 @@ # owned by the top-level Makefile API and no context has been set up for where # derived files should go. # +MACH_INIT_DIR = /private/etc/mach_init.d +install_extra: + $(MKDIRS) $(DSTROOT)$(MACH_INIT_DIR) + install -c -m 644 configd.plist $(DSTROOT)$(MACH_INIT_DIR)/configd.plist diff --git a/configd.tproj/Makefile.preamble b/configd.tproj/Makefile.preamble index 027ceaa..ea74460 100644 --- a/configd.tproj/Makefile.preamble +++ b/configd.tproj/Makefile.preamble @@ -134,7 +134,8 @@ OTHER_GENERATED_OFILES = $(VERS_OFILE) # Change this definition to install projects somewhere other than the # standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems # and "" on other systems. -# DSTROOT = $(HOME) +DSTROOT = $(HOME) +AFTER_INSTALL = install_extra # Additional flags (for MiG generated files) ALL_MIGFLAGS = -F$(SYMROOT) diff --git a/configd.tproj/PB.project b/configd.tproj/PB.project index 6534995..3ceaa3c 100644 --- a/configd.tproj/PB.project +++ b/configd.tproj/PB.project @@ -11,6 +11,7 @@ "notify_server.h", "plugin_support.h", "session.h", + "pattern.h", "notify.h" ); "OTHER_LIBS" = (objc); @@ -21,6 +22,7 @@ "notify_server.c", "plugin_support.c", "session.c", + "pattern.c", "notify.c", "_configopen.c", "_configclose.c", @@ -49,7 +51,8 @@ "Makefile.postamble", "m.template", "h.template", - "config.defs" + "config.defs", + "configd.plist" ); "PRECOMPILED_HEADERS" = (); "PROJECT_HEADERS" = (); @@ -61,6 +64,7 @@ "NEXTSTEP_BUILDTOOL" = "/usr/bin/gnumake"; "NEXTSTEP_INSTALLDIR" = "/usr/sbin"; "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac"; + "NEXTSTEP_LINKEROPTIONS" = "-prebind_all_twolevel_modules"; "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc"; "PDO_UNIX_BUILDTOOL" = "$NEXT_ROOT/Developer/bin/make"; "PDO_UNIX_INSTALLDIR" = "/bin"; diff --git a/configd.tproj/_SCD.c b/configd.tproj/_SCD.c index b087f8d..57bdaad 100644 --- a/configd.tproj/_SCD.c +++ b/configd.tproj/_SCD.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -34,25 +37,29 @@ #include "configd.h" -CFMutableDictionaryRef sessionData = NULL; +__private_extern__ CFMutableDictionaryRef sessionData = NULL; -CFMutableDictionaryRef storeData = NULL; -CFMutableDictionaryRef storeData_s = NULL; +__private_extern__ CFMutableDictionaryRef storeData = NULL; +__private_extern__ CFMutableDictionaryRef storeData_s = NULL; -CFMutableSetRef changedKeys = NULL; -CFMutableSetRef changedKeys_s = NULL; +__private_extern__ CFMutableDictionaryRef patternData = NULL; +__private_extern__ CFMutableDictionaryRef patternData_s = NULL; -CFMutableSetRef deferredRemovals = NULL; -CFMutableSetRef deferredRemovals_s = NULL; +__private_extern__ CFMutableSetRef changedKeys = NULL; +__private_extern__ CFMutableSetRef changedKeys_s = NULL; -CFMutableSetRef removedSessionKeys = NULL; -CFMutableSetRef removedSessionKeys_s = NULL; +__private_extern__ CFMutableSetRef deferredRemovals = NULL; +__private_extern__ CFMutableSetRef deferredRemovals_s = NULL; -CFMutableSetRef needsNotification = NULL; +__private_extern__ CFMutableSetRef removedSessionKeys = NULL; +__private_extern__ CFMutableSetRef removedSessionKeys_s = NULL; -int storeLocked = 0; /* > 0 if dynamic store locked */ +__private_extern__ CFMutableSetRef needsNotification = NULL; +__private_extern__ int storeLocked = 0; /* > 0 if dynamic store locked */ + +__private_extern__ void _swapLockedStoreData() { @@ -62,6 +69,10 @@ _swapLockedStoreData() storeData = storeData_s; storeData_s = temp; + temp = patternData; + patternData = patternData_s; + patternData_s = temp; + temp = changedKeys; changedKeys = changedKeys_s; changedKeys_s = temp; @@ -78,6 +89,7 @@ _swapLockedStoreData() } +__private_extern__ void _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) { @@ -160,144 +172,7 @@ _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) } -/* - * _addRegexWatcherByKey() - * - * This is a CFDictionaryApplierFunction which will iterate over each key - * 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 - * 2. the compiled regular expression associated with the above key. - * - * If a (real) dictionary key is found which matches the provided regular - * expression then we mark that key as being watched by the session. - */ -void -_addRegexWatcherByKey(const void *key, void *val, void *context) -{ - CFStringRef storeStr = key; - CFDictionaryRef info = val; - mach_port_t sessionID = ((addContextRef)context)->store->server; - regex_t *preg = ((addContextRef)context)->preg; - int storeKeyLen; - char *storeKey; - CFNumberRef sessionNum; - int reError; - char reErrBuf[256]; - int reErrStrLen; - - if (!CFDictionaryContainsKey(info, kSCDData)) { - /* if no data (yet) */ - return; - } - - /* 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 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, storeStr); - CFRelease(sessionNum); - break; - case REG_NOMATCH : - /* no match */ - break; - default : - reErrStrLen = regerror(reError, preg, reErrBuf, sizeof(reErrBuf)); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); - break; - } - CFAllocatorDeallocate(NULL, storeKey); -} - - -/* - * _addRegexWatchersBySession() - * - * 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 store key being added. - * - * If an active session includes any regular expression keys which match the - * key being added to the "storeData" dictionary then we mark this key as being - * watched by the session. - */ -void -_addRegexWatchersBySession(const void *key, void *val, void *context) -{ - CFStringRef sessionKey = key; - CFDictionaryRef info = val; - CFStringRef addedKey = context; - CFIndex newKeyLen; - char *newKeyStr; - CFArrayRef rKeys; - CFArrayRef rData; - CFIndex i; - - rKeys = CFDictionaryGetValue(info, kSCDRegexKeys); - if (rKeys == NULL) { - /* if no regex keys for this session */ - return; - } - rData = CFDictionaryGetValue(info, kSCDRegexData); - - /* convert new key to C string */ - newKeyLen = CFStringGetLength(addedKey) + 1; - newKeyStr = CFAllocatorAllocate(NULL, newKeyLen, 0); - if (!CFStringGetCString(addedKey, newKeyStr, newKeyLen, kCFStringEncodingMacRoman)) { - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert new key to C string")); - CFAllocatorDeallocate(NULL, newKeyStr); - return; - } - - /* iterate over the regex keys looking for an pattern which matches the new key */ - for (i=0; istore->server; - regex_t *preg = ((removeContextRef)context)->preg; - CFNumberRef sessionNum; - CFArrayRef watchers; - int storeKeyLen; - char *storeKey; - int reError; - char reErrBuf[256]; - int reErrStrLen; - - if (CFDictionaryContainsKey(info, kSCDWatchers) == FALSE) { - /* if no watchers */ - return; - } - - sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionID); - - watchers = CFDictionaryGetValue(info, kSCDWatchers); - if (CFArrayContainsValue(watchers, - CFRangeMake(0, CFArrayGetCount(watchers)), - sessionNum) == FALSE) { - /* this session is not watching this key */ - CFRelease(sessionNum); - return; - } - - /* convert 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 key to C string")); - CFAllocatorDeallocate(NULL, storeKey); - CFRelease(sessionNum); - return; - } - - /* check if this key matches the regular expression */ - reError = regexec(preg, storeKey, 0, NULL, 0); - switch (reError) { - case 0 : - /* we've got a match */ - _removeWatcher(sessionNum, storeStr); - break; - case REG_NOMATCH : - /* no match */ - break; - default : - reErrStrLen = regerror(reError, preg, reErrBuf, sizeof(reErrBuf)); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); - break; - } - CFAllocatorDeallocate(NULL, storeKey); - CFRelease(sessionNum); -} - - -/* - * _removeRegexWatchersBySession() - * - * 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 store key being removed. - * - * If an active session includes any regular expression keys which match the - * key being removed from the "storeData" dictionary then we clear this keys - * reference of being watched. - */ -void -_removeRegexWatchersBySession(const void *key, void *val, void *context) -{ - CFStringRef sessionKey = key; - CFDictionaryRef info = val; - CFStringRef removedKey = context; - CFIndex oldKeyLen; - char *oldKeyStr; - CFArrayRef rKeys; - CFArrayRef rData; - CFIndex i; - - rKeys = CFDictionaryGetValue(info, kSCDRegexKeys); - if (rKeys == NULL) { - /* if no regex keys for this session */ - return; - } - rData = CFDictionaryGetValue(info, kSCDRegexData); - - /* convert new key to C string */ - oldKeyLen = CFStringGetLength(removedKey) + 1; - oldKeyStr = CFAllocatorAllocate(NULL, oldKeyLen, 0); - if (!CFStringGetCString(removedKey, oldKeyStr, oldKeyLen, kCFStringEncodingMacRoman)) { - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert old key to C string")); - CFAllocatorDeallocate(NULL, oldKeyStr); - return; - } - - /* iterate over the regex keys looking for an pattern which matches the old key */ - for (i=0; iserver == MACH_PORT_NULL)) { return kSCStatusNoStoreSession; /* you must have an open session to play */ } + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, CFSTR("add : %5d : %@\n"), storePrivate->server, key); + } + /* * 1. Ensure that we hold the lock. */ @@ -59,7 +73,7 @@ __SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyLis /* * 2. Ensure that this is a new key. */ - sc_status = __SCDynamicStoreCopyValue(store, key, &tempValue); + sc_status = __SCDynamicStoreCopyValue(store, key, &tempValue, TRUE); switch (sc_status) { case kSCStatusNoKey : /* store key does not exist, proceed */ @@ -72,14 +86,14 @@ __SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyLis goto done; default : - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _SCDGet(): %s"), SCErrorString(sc_status)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status)); goto done; } /* * 3. Save the new key. */ - sc_status = __SCDynamicStoreSetValue(store, key, value); + sc_status = __SCDynamicStoreSetValue(store, key, value, TRUE); /* * 4. Release our lock. @@ -91,6 +105,7 @@ __SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyLis } +__private_extern__ kern_return_t _configadd(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -103,29 +118,29 @@ _configadd(mach_port_t server, { serverSessionRef mySession = getSession(server); CFStringRef key; /* key (un-serialized) */ - CFPropertyListRef data; /* data (un-serialized) */ + CFDataRef data; /* data (un-serialized) */ - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Add key to configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Add key to configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } *sc_status = kSCStatusOK; /* un-serialize the key */ - if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) { + if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; - } - - if (!isA_CFString(key)) { + } else if (!isA_CFString(key)) { *sc_status = kSCStatusInvalidArgument; } /* un-serialize the data */ - if (!_SCUnserialize((CFPropertyListRef *)&data, (void *)dataRef, dataLen)) { + if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) { *sc_status = kSCStatusFailed; } - if (!isA_CFPropertyList(data)) { - *sc_status = kSCStatusInvalidArgument; + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ } if (*sc_status != kSCStatusOK) { diff --git a/configd.tproj/_configadd_s.c b/configd.tproj/_configadd_s.c index 8c369b9..b4f96e7 100644 --- a/configd.tproj/_configadd_s.c +++ b/configd.tproj/_configadd_s.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -33,8 +36,9 @@ #include "configd.h" #include "session.h" +__private_extern__ int -__SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value) +__SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; int sc_status = kSCStatusOK; @@ -44,9 +48,15 @@ __SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFPr 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 (_configd_verbose) { + CFPropertyListRef val; + + (void) _SCUnserialize(&val, value, NULL, NULL); + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreAddTemporaryValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), val); + CFRelease(val); + } if (!store || (storePrivate->server == MACH_PORT_NULL)) { return kSCStatusNoStoreSession; /* you must have an open session to play */ @@ -110,6 +120,7 @@ __SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFPr } +__private_extern__ kern_return_t _configadd_s(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -122,29 +133,29 @@ _configadd_s(mach_port_t server, { serverSessionRef mySession = getSession(server); CFStringRef key; /* key (un-serialized) */ - CFPropertyListRef data; /* data (un-serialized) */ + CFDataRef data; /* data (un-serialized) */ - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Add (session) key to configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Add (session) key to configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } *sc_status = kSCStatusOK; /* un-serialize the key */ - if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) { + if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; - } - - if (!isA_CFString(key)) { + } else if (!isA_CFString(key)) { *sc_status = kSCStatusInvalidArgument; } /* un-serialize the data */ - if (!_SCUnserialize((CFPropertyListRef *)&data, (void *)dataRef, dataLen)) { + if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) { *sc_status = kSCStatusFailed; } - if (!isA_CFPropertyList(data)) { - *sc_status = kSCStatusInvalidArgument; + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ } if (*sc_status != kSCStatusOK) { diff --git a/configd.tproj/_configclose.c b/configd.tproj/_configclose.c index 810420c..b408b89 100644 --- a/configd.tproj/_configclose.c +++ b/configd.tproj/_configclose.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -35,6 +38,8 @@ #include "configd.h" #include "session.h" +#define N_QUICK 16 + static Boolean isMySessionKey(CFStringRef sessionKey, CFStringRef key) { @@ -62,8 +67,42 @@ isMySessionKey(CFStringRef sessionKey, CFStringRef key) } +static void +removeAllKeys(SCDynamicStoreRef store, Boolean isRegex) +{ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + CFSetRef keys; + CFIndex n; + + keys = isRegex ? storePrivate->patterns : storePrivate->keys; + n = CFSetGetCount(keys); + if (n > 0) { + CFIndex i; + CFArrayRef keysToRemove; + const void * watchedKeys_q[N_QUICK]; + const void ** watchedKeys = watchedKeys_q; + + if (n > (CFIndex)(sizeof(watchedKeys_q) / sizeof(CFStringRef))) + watchedKeys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0); + CFSetGetValues(keys, watchedKeys); + keysToRemove = CFArrayCreate(NULL, watchedKeys, n, &kCFTypeArrayCallBacks); + if (watchedKeys != watchedKeys_q) CFAllocatorDeallocate(NULL, watchedKeys); + for (i = 0; i < n; i++) { + (void) __SCDynamicStoreRemoveWatchedKey(store, + CFArrayGetValueAtIndex(keysToRemove, i), + isRegex, + TRUE); + } + CFRelease(keysToRemove); + } + + return; +} + + +__private_extern__ int -__SCDynamicStoreClose(SCDynamicStoreRef *store) +__SCDynamicStoreClose(SCDynamicStoreRef *store, Boolean internal) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)*store; CFIndex keyCnt; @@ -78,43 +117,16 @@ __SCDynamicStoreClose(SCDynamicStoreRef *store) return kSCStatusNoStoreSession; /* you must have an open session to play */ } - /* Remove notification keys */ - keyCnt = CFSetGetCount(storePrivate->keys); - if (keyCnt > 0) { - const 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; iserver); } - /* Remove regex notification keys */ - keyCnt = CFSetGetCount(storePrivate->reKeys); - if (keyCnt > 0) { - const 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; istore); + *sc_status = __SCDynamicStoreClose(&mySession->store, FALSE); 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 c51edd3..b211b6b 100644 --- a/configd.tproj/_configget.c +++ b/configd.tproj/_configget.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -33,19 +36,30 @@ #include "configd.h" #include "session.h" +__private_extern__ int -__SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef *value) +__SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef *value, Boolean internal) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; CFDictionaryRef dict; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyValue:")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + } if (!store || (storePrivate->server == MACH_PORT_NULL)) { return kSCStatusNoStoreSession; /* you must have an open session to play */ } + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, + CFSTR("%s : %5d : %@\n"), + internal ? "*copy " : "copy ", + storePrivate->server, + key); + } + dict = CFDictionaryGetValue(storeData, key); if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDData) == FALSE)) { /* key doesn't exist (or data never defined) */ @@ -55,11 +69,18 @@ __SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyLi /* Return the data associated with the key */ *value = CFRetain(CFDictionaryGetValue(dict, kSCDData)); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" value = %@"), *value); + if (_configd_verbose) { + CFPropertyListRef val; + + (void) _SCUnserialize(&val, *value, NULL, NULL); + SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), val); + CFRelease(val); + } return kSCStatusOK; } +__private_extern__ kern_return_t _configget(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -73,34 +94,42 @@ _configget(mach_port_t server, CFStringRef key; /* key (un-serialized) */ serverSessionRef mySession = getSession(server); Boolean ok; - CFPropertyListRef value; + CFDataRef value; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Get key from configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Get key from configuration database.")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + } *dataRef = NULL; *dataLen = 0; /* un-serialize the key */ - if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) { + if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; return KERN_SUCCESS; } if (!isA_CFString(key)) { - CFRelease(key); *sc_status = kSCStatusInvalidArgument; + CFRelease(key); + return KERN_SUCCESS; + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + CFRelease(key); return KERN_SUCCESS; } - *sc_status = __SCDynamicStoreCopyValue(mySession->store, key, &value); + *sc_status = __SCDynamicStoreCopyValue(mySession->store, key, &value, FALSE); CFRelease(key); if (*sc_status != kSCStatusOK) { return KERN_SUCCESS; } /* serialize the data */ - ok = _SCSerialize(value, NULL, (void **)dataRef, (CFIndex *)dataLen); + ok = _SCSerializeData(value, (void **)dataRef, (CFIndex *)dataLen); CFRelease(value); if (!ok) { *sc_status = kSCStatusFailed; @@ -126,16 +155,16 @@ typedef struct { static void addSpecificKey(const void *value, void *context) { + CFDataRef data; CFStringRef key = (CFStringRef)value; addSpecificRef myContextRef = (addSpecificRef)context; int sc_status; - CFPropertyListRef data; if (!isA_CFString(key)) { return; } - sc_status = __SCDynamicStoreCopyValue(myContextRef->store, key, &data); + sc_status = __SCDynamicStoreCopyValue(myContextRef->store, key, &data, TRUE); if (sc_status == kSCStatusOK) { CFDictionaryAddValue(myContextRef->dict, key, data); CFRelease(data); @@ -168,6 +197,66 @@ addSpecificPattern(const void *value, void *context) return; } +__private_extern__ +int +__SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRef patterns, CFDictionaryRef *values) +{ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + addSpecific myContext; + + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyMultiple:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" keys = %@"), keys); + SCLog(TRUE, LOG_DEBUG, CFSTR(" patterns = %@"), patterns); + } + + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ + } + + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, + CFSTR("copy m : %5d : %d keys, %d patterns\n"), + storePrivate->server, + keys ? CFArrayGetCount(keys) : 0, + patterns ? CFArrayGetCount(patterns) : 0); + } + + myContext.store = store; + myContext.dict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (keys) { + CFArrayApplyFunction(keys, + CFRangeMake(0, CFArrayGetCount(keys)), + addSpecificKey, + &myContext); + } + + if (patterns) { + CFArrayApplyFunction(patterns, + CFRangeMake(0, CFArrayGetCount(patterns)), + addSpecificPattern, + &myContext); + } + + /* Return the keys/values associated with the key */ + *values = myContext.dict; + + if (_configd_verbose) { + CFDictionaryRef expDict; + + expDict = _SCUnserializeMultiple(*values); + SCLog(TRUE, LOG_DEBUG, CFSTR(" values = %@"), expDict); + CFRelease(expDict); + } + + return kSCStatusOK; +} + +__private_extern__ kern_return_t _configget_m(mach_port_t server, xmlData_t keysRef, @@ -178,14 +267,16 @@ _configget_m(mach_port_t server, mach_msg_type_number_t *dataLen, int *sc_status) { + CFDictionaryRef dict = NULL; /* keys/values (un-serialized) */ CFArrayRef keys = NULL; /* keys (un-serialized) */ - addSpecific myContext; serverSessionRef mySession = getSession(server); Boolean ok; CFArrayRef patterns = NULL; /* patterns (un-serialized) */ - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Get key from configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Get keys from configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } *dataRef = NULL; *dataLen = 0; @@ -193,7 +284,7 @@ _configget_m(mach_port_t server, if (keysRef && (keysLen > 0)) { /* un-serialize the keys */ - if (!_SCUnserialize((CFPropertyListRef *)&keys, (void *)keysRef, keysLen)) { + if (!_SCUnserialize((CFPropertyListRef *)&keys, NULL, (void *)keysRef, keysLen)) { *sc_status = kSCStatusFailed; } @@ -204,7 +295,7 @@ _configget_m(mach_port_t server, if (patternsRef && (patternsLen > 0)) { /* un-serialize the patterns */ - if (!_SCUnserialize((CFPropertyListRef *)&patterns, (void *)patternsRef, patternsLen)) { + if (!_SCUnserialize((CFPropertyListRef *)&patterns, NULL, (void *)patternsRef, patternsLen)) { *sc_status = kSCStatusFailed; } @@ -213,37 +304,23 @@ _configget_m(mach_port_t server, } } + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + } + if (*sc_status != kSCStatusOK) { if (keys) CFRelease(keys); if (patterns) CFRelease(patterns); 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); - } + *sc_status = __SCDynamicStoreCopyMultiple(mySession->store, keys, patterns, &dict); + if (keys) CFRelease(keys); + if (patterns) CFRelease(patterns); /* serialize the dictionary of matching keys/patterns */ - ok = _SCSerialize(myContext.dict, NULL, (void **)dataRef, (CFIndex *)dataLen); - CFRelease(myContext.dict); + ok = _SCSerialize(dict, NULL, (void **)dataRef, (CFIndex *)dataLen); + CFRelease(dict); if (!ok) { *sc_status = kSCStatusFailed; return KERN_SUCCESS; diff --git a/configd.tproj/_configlist.c b/configd.tproj/_configlist.c index da7a970..bd0277a 100644 --- a/configd.tproj/_configlist.c +++ b/configd.tproj/_configlist.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -32,28 +35,26 @@ #include "configd.h" #include "session.h" +#include "pattern.h" + +#define N_QUICK 64 +__private_extern__ int __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, CFArrayRef *subKeys) { - SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; - CFIndex storeCnt; - const void **storeKeys; - const void **storeValues; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; CFMutableArrayRef keyArray; - int i; + regex_t preg; + CFIndex storeCnt; 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 (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, 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 */ @@ -63,56 +64,31 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is 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("$")); - } - - /* - * compile the provided regular expression using the - * provided isRegex. - */ - 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; - } + CFStringRef reErrStr; - reError = regcomp(&preg, regexBuf, REG_EXTENDED); - if (reError != 0) { - reErrStrLen = regerror(reError, &preg, reErrBuf, sizeof(reErrBuf)); - storeStr = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingMacRoman); - CFArrayAppendValue(keyArray, storeStr); - CFRelease(storeStr); + if (!patternCompile(key, &preg, &reErrStr)) { + CFArrayAppendValue(keyArray, reErrStr); + CFRelease(reErrStr); *subKeys = CFArrayCreateCopy(NULL, keyArray); CFRelease(keyArray); - CFAllocatorDeallocate(NULL, regexBuf); return kSCStatusFailed; } } if (storeCnt > 0) { - storeKeys = CFAllocatorAllocate(NULL, storeCnt * sizeof(CFStringRef), 0); - storeValues = CFAllocatorAllocate(NULL, storeCnt * sizeof(CFStringRef), 0); + int i; + const void * storeKeys_q[N_QUICK]; + const void ** storeKeys = storeKeys_q; + const void * storeValues_q[N_QUICK]; + const void ** storeValues = storeValues_q; + + if (storeCnt > (CFIndex)(sizeof(storeKeys_q) / sizeof(CFStringRef))) { + storeKeys = CFAllocatorAllocate(NULL, storeCnt * sizeof(CFStringRef), 0); + storeValues = CFAllocatorAllocate(NULL, storeCnt * sizeof(CFStringRef), 0); + } + CFDictionaryGetKeysAndValues(storeData, storeKeys, storeValues); - for (i=0; i (CFIndex)sizeof(storeKey_q)) + storeKey = CFAllocatorAllocate(NULL, storeKeyLen, 0); + if (_SC_cfstring_to_cstring(storeStr, storeKey, storeKeyLen, kCFStringEncodingASCII) == NULL) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string")); + if (storeKey != storeKey_q) CFAllocatorDeallocate(NULL, storeKey); continue; } - reError = regexec(&preg, - storeKey, - 0, - NULL, - 0); + reError = regexec(&preg, storeKey, 0, NULL, 0); switch (reError) { case 0 : /* we've got a match */ @@ -147,15 +120,19 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is case REG_NOMATCH : /* no match */ break; - default : + default : { + char reErrBuf[256]; + int reErrStrLen; + reErrStrLen = regerror(reError, &preg, reErrBuf, sizeof(reErrBuf)); SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); break; + } } - CFAllocatorDeallocate(NULL, storeKey); + if (storeKey != storeKey_q) CFAllocatorDeallocate(NULL, storeKey); } else { /* * only return those keys which are prefixed by the @@ -167,13 +144,15 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is } } } - CFAllocatorDeallocate(NULL, storeKeys); - CFAllocatorDeallocate(NULL, storeValues); + + if (storeKeys != storeKeys_q) { + CFAllocatorDeallocate(NULL, storeKeys); + CFAllocatorDeallocate(NULL, storeValues); + } } if (isRegex) { regfree(&preg); - CFAllocatorDeallocate(NULL, regexBuf); } *subKeys = keyArray; @@ -182,6 +161,7 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is } +__private_extern__ kern_return_t _configlist(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -197,25 +177,33 @@ _configlist(mach_port_t server, Boolean ok; CFArrayRef subKeys; /* array of CFStringRef's */ - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("List keys in configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("List keys in configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } *listRef = NULL; *listLen = 0; /* un-serialize the key */ - if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) { + if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; return KERN_SUCCESS; } if (!isA_CFString(key)) { - CFRelease(key); *sc_status = kSCStatusInvalidArgument; + CFRelease(key); + return KERN_SUCCESS; + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + CFRelease(key); return KERN_SUCCESS; } - *sc_status = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex, &subKeys); + *sc_status = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex != 0, &subKeys); CFRelease(key); if (*sc_status != kSCStatusOK) { return KERN_SUCCESS; diff --git a/configd.tproj/_configlock.c b/configd.tproj/_configlock.c index 8544c78..2e6b33a 100644 --- a/configd.tproj/_configlock.c +++ b/configd.tproj/_configlock.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -35,6 +38,7 @@ #include "session.h" +__private_extern__ int __SCDynamicStoreLock(SCDynamicStoreRef store, Boolean recursive) { @@ -62,6 +66,10 @@ __SCDynamicStoreLock(SCDynamicStoreRef store, Boolean recursive) return kSCStatusAccessError; } + if (!recursive && _configd_trace) { + SCTrace(TRUE, _configd_trace, CFSTR("lock : %5d\n"), storePrivate->server); + } + storeLocked = 1; /* global lock flag */ storePrivate->locked = TRUE; /* per-session lock flag */ @@ -70,11 +78,13 @@ __SCDynamicStoreLock(SCDynamicStoreRef store, Boolean recursive) */ if (storeData_s) { CFRelease(storeData_s); + CFRelease(patternData_s); CFRelease(changedKeys_s); CFRelease(deferredRemovals_s); CFRelease(removedSessionKeys_s); } storeData_s = CFDictionaryCreateMutableCopy(NULL, 0, storeData); + patternData_s = CFDictionaryCreateMutableCopy(NULL, 0, patternData); changedKeys_s = CFSetCreateMutableCopy(NULL, 0, changedKeys); deferredRemovals_s = CFSetCreateMutableCopy(NULL, 0, deferredRemovals); removedSessionKeys_s = CFSetCreateMutableCopy(NULL, 0, removedSessionKeys); @@ -86,13 +96,21 @@ __SCDynamicStoreLock(SCDynamicStoreRef store, Boolean recursive) } +__private_extern__ kern_return_t _configlock(mach_port_t server, int *sc_status) { serverSessionRef mySession = getSession(server); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Lock configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Lock configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + return KERN_SUCCESS; + } *sc_status = __SCDynamicStoreLock(mySession->store, FALSE); if (*sc_status != kSCStatusOK) { diff --git a/configd.tproj/_confignotify.c b/configd.tproj/_confignotify.c index c45b083..0d5b7c6 100644 --- a/configd.tproj/_confignotify.c +++ b/configd.tproj/_confignotify.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -30,22 +33,33 @@ #include "configd.h" #include "session.h" +__private_extern__ int -__SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key) +__SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key, Boolean internal) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; int sc_status = kSCStatusOK; CFDictionaryRef dict; Boolean newValue = FALSE; - CFPropertyListRef value; + CFDataRef value; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyValue:")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + } if (!store || (storePrivate->server == MACH_PORT_NULL)) { return kSCStatusNoStoreSession; /* you must have an open session to play */ } + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, + CFSTR("%s : %5d : %@\n"), + internal ? "*notify" : "notify ", + storePrivate->server, + key); + } + /* * 1. Ensure that we hold the lock. */ @@ -60,16 +74,16 @@ __SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key) dict = CFDictionaryGetValue(storeData, key); if (!dict || !CFDictionaryGetValueIfPresent(dict, kSCDData, (const void **)&value)) { /* key doesn't exist (or data never defined) */ - value = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); + (void)_SCSerialize(kCFBooleanTrue, &value, NULL, NULL); newValue = TRUE; } /* replace or store initial/temporary existing value */ - __SCDynamicStoreSetValue(store, key, value); + __SCDynamicStoreSetValue(store, key, value, TRUE); if (newValue) { /* remove the value we just created */ - __SCDynamicStoreRemoveValue(store, key); + __SCDynamicStoreRemoveValue(store, key, TRUE); CFRelease(value); } @@ -82,6 +96,7 @@ __SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key) } +__private_extern__ kern_return_t _confignotify(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -92,22 +107,30 @@ _confignotify(mach_port_t server, serverSessionRef mySession = getSession(server); CFStringRef key; /* key (un-serialized) */ - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Notify key in configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Notify key in configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } /* un-serialize the key */ - if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) { - *sc_status = kSCStatusFailed; - return KERN_SUCCESS; - } + if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { + *sc_status = kSCStatusFailed; + return KERN_SUCCESS; + } if (!isA_CFString(key)) { - CFRelease(key); *sc_status = kSCStatusInvalidArgument; + CFRelease(key); + return KERN_SUCCESS; + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + CFRelease(key); return KERN_SUCCESS; } - *sc_status = __SCDynamicStoreNotifyValue(mySession->store, key); + *sc_status = __SCDynamicStoreNotifyValue(mySession->store, key, FALSE); CFRelease(key); return KERN_SUCCESS; diff --git a/configd.tproj/_configopen.c b/configd.tproj/_configopen.c index 0b6e6ad..705b2f6 100644 --- a/configd.tproj/_configopen.c +++ b/configd.tproj/_configopen.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -34,26 +37,33 @@ #include "configd_server.h" #include "session.h" +__private_extern__ int __SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name) { - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreOpen:")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" name = %@"), name); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreOpen:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" name = %@"), name); + } /* * allocate and initialize a new session */ - *store = __SCDynamicStoreCreatePrivate(NULL, name, NULL, NULL); + *store = (SCDynamicStoreRef)__SCDynamicStoreCreatePrivate(NULL, name, NULL, NULL); /* * If necessary, initialize the store and session data dictionaries */ if (storeData == NULL) { + sessionData = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); storeData = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - sessionData = CFDictionaryCreateMutable(NULL, + patternData = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -72,6 +82,7 @@ __SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name) } +__private_extern__ kern_return_t _configopen(mach_port_t server, xmlData_t nameRef, /* raw XML bytes */ @@ -88,11 +99,13 @@ _configopen(mach_port_t server, CFMutableDictionaryRef newInfo; CFMachPortRef mp; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Open new session.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Open new session.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } /* un-serialize the name */ - if (!_SCUnserialize((CFPropertyListRef *)&name, (void *)nameRef, nameLen)) { + if (!_SCUnserializeString(&name, NULL, (void *)nameRef, nameLen)) { *sc_status = kSCStatusFailed; return KERN_SUCCESS; } @@ -134,6 +147,10 @@ _configopen(mach_port_t server, newSession->callerEUID = mySession->callerEUID; newSession->callerEGID = mySession->callerEGID; + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, CFSTR("open : %5d : %@\n"), *newServer, name); + } + *sc_status = __SCDynamicStoreOpen(&newSession->store, name); /* diff --git a/configd.tproj/_configremove.c b/configd.tproj/_configremove.c index c48844c..7a37c8c 100644 --- a/configd.tproj/_configremove.c +++ b/configd.tproj/_configremove.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -33,8 +36,9 @@ #include "configd.h" #include "session.h" +__private_extern__ int -__SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) +__SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key, Boolean internal) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; int sc_status = kSCStatusOK; @@ -42,13 +46,23 @@ __SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) CFMutableDictionaryRef newDict; CFStringRef sessionKey; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreRemoveValue:")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreRemoveValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + } if (!store || (storePrivate->server == MACH_PORT_NULL)) { return kSCStatusNoStoreSession; /* you must have an open session to play */ } + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, + CFSTR("%s : %5d : %@\n"), + internal ? "*remove" : "remove ", + storePrivate->server, + key); + } + /* * 1. Ensure that we hold the lock. */ @@ -99,11 +113,9 @@ __SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) } /* - * 6. Remove data, remove instance, and update/remove - * the dictionary store entry. + * 6. Remove data and update/remove the dictionary store entry. */ CFDictionaryRemoveValue(newDict, kSCDData); - CFDictionaryRemoveValue(newDict, kSCDInstance); if (CFDictionaryGetCount(newDict) > 0) { /* this key is still being "watched" */ CFDictionarySetValue(storeData, key, newDict); @@ -123,6 +135,7 @@ __SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) } +__private_extern__ kern_return_t _configremove(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -133,22 +146,30 @@ _configremove(mach_port_t server, serverSessionRef mySession = getSession(server); CFStringRef key; /* key (un-serialized) */ - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Remove key from configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Remove key from configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } /* un-serialize the key */ - if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) { + if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; return KERN_SUCCESS; } if (!isA_CFString(key)) { - CFRelease(key); *sc_status = kSCStatusInvalidArgument; + CFRelease(key); + return KERN_SUCCESS; + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + CFRelease(key); return KERN_SUCCESS; } - *sc_status = __SCDynamicStoreRemoveValue(mySession->store, key); + *sc_status = __SCDynamicStoreRemoveValue(mySession->store, key, FALSE); CFRelease(key); return KERN_SUCCESS; diff --git a/configd.tproj/_configset.c b/configd.tproj/_configset.c index 1f80c79..e2a41f6 100644 --- a/configd.tproj/_configset.c +++ b/configd.tproj/_configset.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -30,11 +33,15 @@ * - initial revision */ + #include "configd.h" #include "session.h" +#include "pattern.h" + +__private_extern__ int -__SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value) +__SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value, Boolean internal) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; int sc_status = kSCStatusOK; @@ -44,14 +51,28 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyLis CFStringRef sessionKey; CFStringRef storeSessionKey; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreSetValue:")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" value = %@"), value); + if (_configd_verbose) { + CFPropertyListRef val; + + (void) _SCUnserialize(&val, value, NULL, NULL); + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), val); + CFRelease(val); + } if (!store || (storePrivate->server == MACH_PORT_NULL)) { return kSCStatusNoStoreSession; /* you must have an open session to play */ } + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, + CFSTR("%s : %5d : %@\n"), + internal ? "*set " : "set ", + storePrivate->server, + key); + } + /* * 1. Ensure that we hold the lock. */ @@ -123,9 +144,7 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyLis if (CFSetContainsValue(deferredRemovals, key)) { CFSetRemoveValue(deferredRemovals, key); } else { - CFDictionaryApplyFunction(sessionData, - (CFDictionaryApplierFunction)_addRegexWatchersBySession, - (void *)key); + patternAddKey(key); } } @@ -143,6 +162,7 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyLis return sc_status; } +__private_extern__ kern_return_t _configset(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -156,29 +176,29 @@ _configset(mach_port_t server, { serverSessionRef mySession = getSession(server); CFStringRef key; /* key (un-serialized) */ - CFPropertyListRef data; /* data (un-serialized) */ + CFDataRef data; /* data (un-serialized) */ - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Set key to configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Set key to configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } *sc_status = kSCStatusOK; /* un-serialize the key */ - if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) { + if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; - } - - if (!isA_CFString(key)) { + } else if (!isA_CFString(key)) { *sc_status = kSCStatusInvalidArgument; } /* un-serialize the data */ - if (!_SCUnserialize((CFPropertyListRef *)&data, (void *)dataRef, dataLen)) { + if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) { *sc_status = kSCStatusFailed; } - if (!isA_CFPropertyList(data)) { - *sc_status = kSCStatusInvalidArgument; + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ } if (*sc_status != kSCStatusOK) { @@ -187,7 +207,7 @@ _configset(mach_port_t server, return KERN_SUCCESS; } - *sc_status = __SCDynamicStoreSetValue(mySession->store, key, data); + *sc_status = __SCDynamicStoreSetValue(mySession->store, key, data, FALSE); *newInstance = 0; CFRelease(key); @@ -200,18 +220,18 @@ static void setSpecificKey(const void *key, const void *value, void *context) { CFStringRef k = (CFStringRef)key; - CFPropertyListRef v = (CFPropertyListRef)value; + CFDataRef v = (CFDataRef)value; SCDynamicStoreRef store = (SCDynamicStoreRef)context; if (!isA_CFString(k)) { return; } - if (!isA_CFPropertyList(v)) { + if (!isA_CFData(v)) { return; } - (void) __SCDynamicStoreSetValue(store, k, v); + (void) __SCDynamicStoreSetValue(store, k, v, TRUE); return; } @@ -226,7 +246,7 @@ removeSpecificKey(const void *value, void *context) return; } - (void) __SCDynamicStoreRemoveValue(store, k); + (void) __SCDynamicStoreRemoveValue(store, k, TRUE); return; } @@ -241,11 +261,86 @@ notifySpecificKey(const void *value, void *context) return; } - (void) __SCDynamicStoreNotifyValue(store, k); + (void) __SCDynamicStoreNotifyValue(store, k, TRUE); return; } +__private_extern__ +int +__SCDynamicStoreSetMultiple(SCDynamicStoreRef store, CFDictionaryRef keysToSet, CFArrayRef keysToRemove, CFArrayRef keysToNotify) +{ + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + int sc_status = kSCStatusOK; + + if (_configd_verbose) { + CFDictionaryRef expDict; + + expDict = keysToSet ? _SCUnserializeMultiple(keysToSet) : NULL; + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetMultiple:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToSet = %@"), expDict); + SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToRemove = %@"), keysToRemove); + SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToNotify = %@"), keysToNotify); + if (expDict) CFRelease(expDict); + } + + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ + } + + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, + CFSTR("set m : %5d : %d set, %d remove, %d notify\n"), + storePrivate->server, + keysToSet ? CFDictionaryGetCount(keysToSet) : 0, + keysToRemove ? CFArrayGetCount (keysToRemove) : 0, + keysToNotify ? CFArrayGetCount (keysToNotify) : 0); + } + + /* + * Ensure that we hold the lock + */ + sc_status = __SCDynamicStoreLock(store, TRUE); + if (sc_status != kSCStatusOK) { + return sc_status; + } + + /* + * Set the new/updated keys + */ + if (keysToSet) { + CFDictionaryApplyFunction(keysToSet, + setSpecificKey, + (void *)store); + } + + /* + * Remove the specified keys + */ + if (keysToRemove) { + CFArrayApplyFunction(keysToRemove, + CFRangeMake(0, CFArrayGetCount(keysToRemove)), + removeSpecificKey, + (void *)store); + } + + /* + * Notify the specified keys + */ + if (keysToNotify) { + CFArrayApplyFunction(keysToNotify, + CFRangeMake(0, CFArrayGetCount(keysToNotify)), + notifySpecificKey, + (void *)store); + } + + /* Release our lock */ + __SCDynamicStoreUnlock(store, TRUE); + + return sc_status; +} + +__private_extern__ kern_return_t _configset_m(mach_port_t server, xmlData_t dictRef, @@ -261,86 +356,50 @@ _configset_m(mach_port_t server, 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); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Set/remove/notify keys to configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } *sc_status = kSCStatusOK; if (dictRef && (dictLen > 0)) { /* un-serialize the key/value pairs to set */ - if (!_SCUnserialize((CFPropertyListRef *)&dict, (void *)dictRef, dictLen)) { + if (!_SCUnserialize((CFPropertyListRef *)&dict, NULL, (void *)dictRef, dictLen)) { *sc_status = kSCStatusFailed; - } - - if (!isA_CFDictionary(dict)) { + } else if (!isA_CFDictionary(dict)) { *sc_status = kSCStatusInvalidArgument; } } if (removeRef && (removeLen > 0)) { /* un-serialize the keys to remove */ - if (!_SCUnserialize((CFPropertyListRef *)&remove, (void *)removeRef, removeLen)) { + if (!_SCUnserialize((CFPropertyListRef *)&remove, NULL, (void *)removeRef, removeLen)) { *sc_status = kSCStatusFailed; - } - - if (!isA_CFArray(remove)) { + } else if (!isA_CFArray(remove)) { *sc_status = kSCStatusInvalidArgument; } } if (notifyRef && (notifyLen > 0)) { /* un-serialize the keys to notify */ - if (!_SCUnserialize((CFPropertyListRef *)¬ify, (void *)notifyRef, notifyLen)) { + if (!_SCUnserialize((CFPropertyListRef *)¬ify, NULL, (void *)notifyRef, notifyLen)) { *sc_status = kSCStatusFailed; - } - - if (!isA_CFArray(notify)) { + } else if (!isA_CFArray(notify)) { *sc_status = kSCStatusInvalidArgument; } } - if (*sc_status != kSCStatusOK) { - goto done; + if (!mySession) { + /* you must have an open session to play */ + *sc_status = kSCStatusNoStoreSession; } - /* - * 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 */ + *sc_status = __SCDynamicStoreSetMultiple(mySession->store, dict, remove, notify); done : diff --git a/configd.tproj/_configtouch.c b/configd.tproj/_configtouch.c index 6835fbe..8a082b8 100644 --- a/configd.tproj/_configtouch.c +++ b/configd.tproj/_configtouch.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -33,21 +36,27 @@ #include "configd.h" #include "session.h" +__private_extern__ int __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) { SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; int sc_status; - Boolean newValue = FALSE; - CFPropertyListRef value; + CFDataRef value; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreTouchValue:")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreTouchValue:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + } if (!store || (storePrivate->server == MACH_PORT_NULL)) { return kSCStatusNoStoreSession; /* you must have an open session to play */ } + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, CFSTR("touch : %5d : %@\n"), storePrivate->server, key); + } + /* * 1. Ensure that we hold the lock. */ @@ -59,36 +68,45 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) /* * 2. Grab the current (or establish a new) store entry for this key. */ - sc_status = __SCDynamicStoreCopyValue(store, key, &value); + sc_status = __SCDynamicStoreCopyValue(store, key, &value, TRUE); switch (sc_status) { - case kSCStatusNoKey : + case kSCStatusNoKey : { + CFDateRef now; + /* store entry does not exist, create */ - value = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); - newValue = TRUE; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" new time stamp = %@"), value); + + now = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" new time stamp = %@"), now); + (void) _SCSerialize(now, &value, NULL, NULL); + CFRelease(now); break; + } + + case kSCStatusOK : { + CFDateRef now; - case kSCStatusOK : /* store entry exists */ - if (isA_CFDate(value)) { + + (void) _SCUnserialize((CFPropertyListRef *)&now, value, NULL, NULL); + if (isA_CFDate(now)) { /* the value is a CFDate, update the time stamp */ + CFRelease(now); CFRelease(value); - value = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); - newValue = TRUE; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" new time stamp = %@"), value); + now = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" new time stamp = %@"), now); + (void) _SCSerialize(now, &value, NULL, NULL); } /* else, we'll just save the data (again) to bump the instance */ - break; + CFRelease(now); + break; + } default : SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status)); goto done; } - sc_status = __SCDynamicStoreSetValue(store, key, value); - - if (newValue) { - CFRelease(value); - } + sc_status = __SCDynamicStoreSetValue(store, key, value, TRUE); + CFRelease(value); done : @@ -101,6 +119,7 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) } +__private_extern__ kern_return_t _configtouch(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -111,18 +130,26 @@ _configtouch(mach_port_t server, serverSessionRef mySession = getSession(server); CFStringRef key; /* key (un-serialized) */ - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Touch key in configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Touch key in configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } /* un-serialize the key */ - if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) { + if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; return KERN_SUCCESS; } if (!isA_CFString(key)) { - CFRelease(key); *sc_status = kSCStatusInvalidArgument; + CFRelease(key); + return KERN_SUCCESS; + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + CFRelease(key); return KERN_SUCCESS; } diff --git a/configd.tproj/_configunlock.c b/configd.tproj/_configunlock.c index 77a1d32..253a26d 100644 --- a/configd.tproj/_configunlock.c +++ b/configd.tproj/_configunlock.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -34,29 +37,38 @@ #include "configd.h" #include "configd_server.h" #include "session.h" +#include "pattern.h" + + +#define N_QUICK 32 static void _notifyWatchers() { CFIndex keyCnt; - const void **keys; + const void * keys_q[N_QUICK]; + const void ** keys = keys_q; keyCnt = CFSetGetCount(changedKeys); if (keyCnt == 0) return; /* if nothing to do */ - keys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); + if (keyCnt > (CFIndex)(sizeof(keys_q) / sizeof(CFStringRef))) + keys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); + CFSetGetValues(changedKeys, keys); + while (--keyCnt >= 0) { + CFArrayRef changes; CFDictionaryRef dict; - CFArrayRef sessionsWatchingKey; - CFIndex watcherCnt; - const void **watchers; CFDictionaryRef info; CFMutableDictionaryRef newInfo; - CFArrayRef changes; CFMutableArrayRef newChanges; + CFArrayRef sessionsWatchingKey; + CFIndex watcherCnt; + const void * watchers_q[N_QUICK]; + const void ** watchers = watchers_q; dict = CFDictionaryGetValue(storeData, (CFStringRef)keys[keyCnt]); if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDWatchers) == FALSE)) { @@ -70,56 +82,62 @@ _notifyWatchers() */ sessionsWatchingKey = CFDictionaryGetValue(dict, kSCDWatchers); watcherCnt = CFArrayGetCount(sessionsWatchingKey); - if (watcherCnt > 0) { - watchers = CFAllocatorAllocate(NULL, watcherCnt * sizeof(CFNumberRef), 0); - CFArrayGetValues(sessionsWatchingKey, - CFRangeMake(0, CFArrayGetCount(sessionsWatchingKey)), - watchers); - while (--watcherCnt >= 0) { - CFStringRef sessionKey; - - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), watchers[watcherCnt]); - info = CFDictionaryGetValue(sessionData, sessionKey); - if (info) { - newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info); - } else { - newInfo = CFDictionaryCreateMutable(NULL, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - } - - changes = CFDictionaryGetValue(newInfo, kSCDChangedKeys); - if (changes) { - newChanges = CFArrayCreateMutableCopy(NULL, 0, changes); - } else { - newChanges = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - } - - if (CFArrayContainsValue(newChanges, - CFRangeMake(0, CFArrayGetCount(newChanges)), - (CFStringRef)keys[keyCnt]) == FALSE) { - CFArrayAppendValue(newChanges, (CFStringRef)keys[keyCnt]); - } - CFDictionarySetValue(newInfo, kSCDChangedKeys, newChanges); - CFRelease(newChanges); - CFDictionarySetValue(sessionData, sessionKey, newInfo); - CFRelease(newInfo); - CFRelease(sessionKey); - - /* - * flag this session as needing a kick - */ - if (needsNotification == NULL) - needsNotification = CFSetCreateMutable(NULL, - 0, - &kCFTypeSetCallBacks); - CFSetAddValue(needsNotification, watchers[watcherCnt]); + if (watcherCnt == 0) { + /* if no watchers */ + continue; + } + + if (watcherCnt > (CFIndex)(sizeof(watchers_q) / sizeof(CFNumberRef))) + watchers = CFAllocatorAllocate(NULL, watcherCnt * sizeof(CFNumberRef), 0); + + CFArrayGetValues(sessionsWatchingKey, CFRangeMake(0, watcherCnt), watchers); + + while (--watcherCnt >= 0) { + CFStringRef sessionKey; + + sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), watchers[watcherCnt]); + info = CFDictionaryGetValue(sessionData, sessionKey); + if (info) { + newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info); + } else { + newInfo = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); } - CFAllocatorDeallocate(NULL, watchers); + + changes = CFDictionaryGetValue(newInfo, kSCDChangedKeys); + if (changes) { + newChanges = CFArrayCreateMutableCopy(NULL, 0, changes); + } else { + newChanges = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + + if (CFArrayContainsValue(newChanges, + CFRangeMake(0, CFArrayGetCount(newChanges)), + (CFStringRef)keys[keyCnt]) == FALSE) { + CFArrayAppendValue(newChanges, (CFStringRef)keys[keyCnt]); + } + CFDictionarySetValue(newInfo, kSCDChangedKeys, newChanges); + CFRelease(newChanges); + CFDictionarySetValue(sessionData, sessionKey, newInfo); + CFRelease(newInfo); + CFRelease(sessionKey); + + /* + * flag this session as needing a kick + */ + if (needsNotification == NULL) + needsNotification = CFSetCreateMutable(NULL, + 0, + &kCFTypeSetCallBacks); + CFSetAddValue(needsNotification, watchers[watcherCnt]); } + + if (watchers != watchers_q) CFAllocatorDeallocate(NULL, watchers); } - CFAllocatorDeallocate(NULL, keys); + + if (keys != keys_q) CFAllocatorDeallocate(NULL, keys); /* * The list of changed keys have been updated for any sessions @@ -135,20 +153,23 @@ static void _processDeferredRemovals() { CFIndex keyCnt; - const void **keys; + const void * keys_q[N_QUICK]; + const void ** keys = keys_q; keyCnt = CFSetGetCount(deferredRemovals); if (keyCnt == 0) return; /* if nothing to do */ - keys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); + if (keyCnt > (CFIndex)(sizeof(keys_q) / sizeof(CFStringRef))) + keys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0); + CFSetGetValues(deferredRemovals, keys); + while (--keyCnt >= 0) { - CFDictionaryApplyFunction(sessionData, - (CFDictionaryApplierFunction)_removeRegexWatchersBySession, - (void *)keys[keyCnt]); + patternRemoveKey((CFStringRef)keys[keyCnt]); } - CFAllocatorDeallocate(NULL, keys); + + if (keys != keys_q) CFAllocatorDeallocate(NULL, keys); /* * All regex keys associated with removed store dictionary keys have @@ -229,6 +250,7 @@ _cleanupRemovedSessionKeys(const void *value, void *context) } +__private_extern__ int __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive) { @@ -251,10 +273,15 @@ __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive) return kSCStatusOK; } + if (!recursive && _configd_trace) { + SCTrace(TRUE, _configd_trace, CFSTR("unlock : %5d\n"), storePrivate->server); + } + /* * all of the changes can be committed to the (real) store. */ CFDictionaryRemoveAllValues(storeData_s); + CFDictionaryRemoveAllValues(patternData_s); CFSetRemoveAllValues (changedKeys_s); CFSetRemoveAllValues (deferredRemovals_s); CFSetRemoveAllValues (removedSessionKeys_s); @@ -263,7 +290,7 @@ __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive) 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); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("patterns I'm watching = %@"), storePrivate->patterns); #endif /* DEBUG */ /* @@ -298,13 +325,21 @@ __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive) } +__private_extern__ kern_return_t _configunlock(mach_port_t server, int *sc_status) { serverSessionRef mySession = getSession(server); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Unlock configuration database.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Unlock configuration database.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + return KERN_SUCCESS; + } *sc_status = __SCDynamicStoreUnlock(mySession->store, FALSE); if (*sc_status != kSCStatusOK) { diff --git a/configd.tproj/_notifyadd.c b/configd.tproj/_notifyadd.c index 55b9268..739171f 100644 --- a/configd.tproj/_notifyadd.c +++ b/configd.tproj/_notifyadd.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -32,172 +35,96 @@ #include "configd.h" #include "session.h" +#include "pattern.h" static __inline__ void -my_CFDictionaryApplyFunction(CFDictionaryRef theDict, - CFDictionaryApplierFunction applier, - void *context) +my_CFSetApplyFunction(CFSetRef theSet, + CFSetApplierFunction applier, + void *context) { CFAllocatorRef myAllocator; - CFDictionaryRef myDict; + CFSetRef mySet; - myAllocator = CFGetAllocator(theDict); - myDict = CFDictionaryCreateCopy(myAllocator, theDict); - CFDictionaryApplyFunction(myDict, applier, context); - CFRelease(myDict); + myAllocator = CFGetAllocator(theSet); + mySet = CFSetCreateCopy(myAllocator, theSet); + CFSetApplyFunction(mySet, applier, context); + CFRelease(mySet); return; } +__private_extern__ int -__SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex) +__SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, Boolean internal) { - SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + int sc_status = kSCStatusOK; + CFNumberRef sessionNum = NULL; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreAddWatchedKey:")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE"); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreAddWatchedKey:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, 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 */ } - /* - * add new key after checking if key has already been defined - */ - 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(storePrivate->keys, key)) - return kSCStatusKeyExists; /* sorry, key already exists in notifier list */ - CFSetAddValue(storePrivate->keys, key); /* add key to this sessions notifier list */ + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, + CFSTR("%s : %5d : %s : %@\n"), + internal ? "*watch+" : "watch+ ", + storePrivate->server, + isRegex ? "pattern" : "key", + key); } - if (isRegex) { - CFStringRef sessionKey; - int regexStrLen; - char *regexStr; - CFMutableDataRef regexData; - int reError; - char reErrBuf[256]; - int reErrStrLen; - addContext context; - CFDictionaryRef info; - CFMutableDictionaryRef newInfo; - CFArrayRef rKeys; - CFMutableArrayRef newRKeys; - CFArrayRef rData; - CFMutableArrayRef newRData; - - /* - * We are adding a regex key. As such, we need to flag - * any keys currently in the store. - */ - - /* 1. Extract a C String version of the key pattern string. */ - - regexStrLen = CFStringGetLength(key) + 1; - regexStr = CFAllocatorAllocate(NULL, regexStrLen, 0); - if (!CFStringGetCString(key, - regexStr, - regexStrLen, - kCFStringEncodingMacRoman)) { - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert regex key to C string")); - CFAllocatorDeallocate(NULL, regexStr); - return kSCStatusFailed; - } + sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server); - /* 2. Compile the regular expression from the pattern string. */ - - regexData = CFDataCreateMutable(NULL, sizeof(regex_t)); - CFDataSetLength(regexData, sizeof(regex_t)); - reError = regcomp((regex_t *)CFDataGetBytePtr(regexData), - regexStr, - REG_EXTENDED); - CFAllocatorDeallocate(NULL, regexStr); - if (reError != 0) { - reErrStrLen = regerror(reError, - (regex_t *)CFDataGetBytePtr(regexData), - reErrBuf, - sizeof(reErrBuf)); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regcomp() key: %s"), reErrBuf); - CFRelease(regexData); - return kSCStatusFailed; + if (isRegex) { + if (CFSetContainsValue(storePrivate->patterns, key)) { + /* sorry, pattern already exists in notifier list */ + sc_status = kSCStatusKeyExists; + goto done; } /* - * 3. Iterate over the current keys and add this session as a "watcher" - * for any key already defined in the store. - */ - - 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. + * add this session as a pattern watcher */ - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); - - info = CFDictionaryGetValue(sessionData, sessionKey); - if (info) { - newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info); - } else { - newInfo = CFDictionaryCreateMutable(NULL, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); + if (!patternAddSession(key, sessionNum)) { + sc_status = kSCStatusInvalidArgument; + goto done; } - rKeys = CFDictionaryGetValue(newInfo, kSCDRegexKeys); - if ((rKeys == NULL) || - (CFArrayContainsValue(rKeys, - CFRangeMake(0, CFArrayGetCount(rKeys)), - key) == FALSE)) { - rData = CFDictionaryGetValue(newInfo, kSCDRegexData); - if (rKeys) { - newRKeys = CFArrayCreateMutableCopy(NULL, 0, rKeys); - newRData = CFArrayCreateMutableCopy(NULL, 0, rData); - } else { - newRKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - newRData = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - } - - /* save the regex key */ - CFArrayAppendValue(newRKeys, key); - CFDictionarySetValue(newInfo, kSCDRegexKeys, newRKeys); - CFRelease(newRKeys); - /* ...and the compiled expression */ - CFArrayAppendValue(newRData, regexData); - CFDictionarySetValue(newInfo, kSCDRegexData, newRData); - CFRelease(newRData); - CFDictionarySetValue(sessionData, sessionKey, newInfo); - } - CFRelease(regexData); - CFRelease(newInfo); - CFRelease(sessionKey); + /* add pattern to this sessions notifier list */ + CFSetAddValue(storePrivate->patterns, key); } else { - CFNumberRef sessionNum; + if (CFSetContainsValue(storePrivate->keys, key)) { + /* sorry, key already exists in notifier list */ + sc_status = kSCStatusKeyExists; + goto done; + } /* * We are watching a specific key. As such, update the * store to mark our interest in any changes. */ - sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server); _addWatcher(sessionNum, key); - CFRelease(sessionNum); + + /* add key to this sessions notifier list */ + CFSetAddValue(storePrivate->keys, key); } - return kSCStatusOK; + done : + + if (sessionNum) CFRelease(sessionNum); + return sc_status; } +__private_extern__ kern_return_t _notifyadd(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -209,23 +136,204 @@ _notifyadd(mach_port_t server, serverSessionRef mySession = getSession(server); CFStringRef key; /* key (un-serialized) */ - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Add notification key for this session.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Add notification key for this session.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } /* un-serialize the key */ - if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) { + if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; return KERN_SUCCESS; } if (!isA_CFString(key)) { - CFRelease(key); *sc_status = kSCStatusInvalidArgument; + CFRelease(key); + return KERN_SUCCESS; + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + CFRelease(key); return KERN_SUCCESS; } - *sc_status = __SCDynamicStoreAddWatchedKey(mySession->store, key, isRegex); + *sc_status = __SCDynamicStoreAddWatchedKey(mySession->store, key, isRegex != 0, FALSE); CFRelease(key); return KERN_SUCCESS; } + + +/* + * "context" argument for removeOldKey() and addNewKey() + */ +typedef struct { + SCDynamicStoreRef store; + CFSetRef oldKeys; /* for addNewKey */ + CFArrayRef newKeys; /* for removeOldKey */ + Boolean isRegex; + int sc_status; +} updateKeysContext, *updateKeysContextRef; + + +static void +removeOldKey(const void *value, void *context) +{ + CFStringRef oldKey = (CFStringRef)value; + updateKeysContextRef myContextRef = (updateKeysContextRef)context; + + if (myContextRef->sc_status != kSCStatusOK) { + return; + } + + if (!myContextRef->newKeys || + !CFArrayContainsValue(myContextRef->newKeys, + CFRangeMake(0, CFArrayGetCount(myContextRef->newKeys)), + oldKey)) { + /* the old notification key is not being retained, remove it */ + myContextRef->sc_status = __SCDynamicStoreRemoveWatchedKey(myContextRef->store, + oldKey, + myContextRef->isRegex, + TRUE); + } + + return; +} + + +static void +addNewKey(const void *value, void *context) +{ + CFStringRef newKey = (CFStringRef)value; + updateKeysContextRef myContextRef = (updateKeysContextRef)context; + + if (myContextRef->sc_status != kSCStatusOK) { + return; + } + + if (!myContextRef->oldKeys || + !CFSetContainsValue(myContextRef->oldKeys, newKey)) { + /* if this is a new notification key */ + myContextRef->sc_status = __SCDynamicStoreAddWatchedKey(myContextRef->store, + newKey, + myContextRef->isRegex, + TRUE); + } + + return; +} + + +__private_extern__ +int +__SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRef patterns) +{ + updateKeysContext myContext; + SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; + + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetNotificationKeys:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" keys = %@"), keys); + SCLog(TRUE, LOG_DEBUG, CFSTR(" patterns = %@"), patterns); + } + + if (!store || (storePrivate->server == MACH_PORT_NULL)) { + return kSCStatusNoStoreSession; /* you must have an open session to play */ + } + + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, + CFSTR("watch : %5d : %d keys, %d patterns\n"), + storePrivate->server, + keys ? CFArrayGetCount(keys) : 0, + patterns ? CFArrayGetCount(patterns) : 0); + } + + myContext.store = store; + myContext.sc_status = kSCStatusOK; + + /* remove any previously registered keys, register any new keys */ + myContext.oldKeys = CFSetCreateCopy(NULL, storePrivate->keys); + myContext.newKeys = keys; + myContext.isRegex = FALSE; + my_CFSetApplyFunction(storePrivate->keys, removeOldKey, &myContext); + if (keys) { + CFArrayApplyFunction(keys, + CFRangeMake(0, CFArrayGetCount(keys)), + addNewKey, + &myContext); + } + CFRelease(myContext.oldKeys); + + /* remove any previously registered patterns, register any new patterns */ + myContext.oldKeys = CFSetCreateCopy(NULL, storePrivate->patterns); + myContext.newKeys = patterns; + myContext.isRegex = TRUE; + my_CFSetApplyFunction(storePrivate->patterns, removeOldKey, &myContext); + if (patterns) { + CFArrayApplyFunction(patterns, + CFRangeMake(0, CFArrayGetCount(patterns)), + addNewKey, + &myContext); + } + CFRelease(myContext.oldKeys); + + return myContext.sc_status; +} + + +__private_extern__ +kern_return_t +_notifyset(mach_port_t server, + xmlData_t keysRef, /* raw XML bytes */ + mach_msg_type_number_t keysLen, + xmlData_t patternsRef, /* raw XML bytes */ + mach_msg_type_number_t patternsLen, + int *sc_status +) +{ + serverSessionRef mySession = getSession(server); + CFArrayRef keys = NULL; /* key (un-serialized) */ + CFArrayRef patterns = NULL; /* patterns (un-serialized) */ + + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Add notification key for this session.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } + + *sc_status = kSCStatusOK; + + if (keysRef && (keysLen > 0)) { + /* un-serialize the keys */ + if (!_SCUnserialize((CFPropertyListRef *)&keys, NULL, (void *)keysRef, keysLen)) { + *sc_status = kSCStatusFailed; + } else if (!isA_CFArray(keys)) { + *sc_status = kSCStatusInvalidArgument; + } + } + + if (patternsRef && (patternsLen > 0)) { + /* un-serialize the patterns */ + if (!_SCUnserialize((CFPropertyListRef *)&patterns, NULL, (void *)patternsRef, patternsLen)) { + *sc_status = kSCStatusFailed; + } else if (!isA_CFArray(patterns)) { + *sc_status = kSCStatusInvalidArgument; + } + } + + if (!mySession) { + /* you must have an open session to play */ + *sc_status = kSCStatusNoStoreSession; + } + + if (*sc_status == kSCStatusOK) { + *sc_status = __SCDynamicStoreSetNotificationKeys(mySession->store, keys, patterns); + } + + if (keys) CFRelease(keys); + if (patterns) CFRelease(patterns); + + return KERN_SUCCESS; +} diff --git a/configd.tproj/_notifycancel.c b/configd.tproj/_notifycancel.c index bcf06d7..1352d6a 100644 --- a/configd.tproj/_notifycancel.c +++ b/configd.tproj/_notifycancel.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -36,6 +39,7 @@ #include "session.h" +__private_extern__ int __SCDynamicStoreNotifyCancel(SCDynamicStoreRef store) { @@ -94,14 +98,22 @@ __SCDynamicStoreNotifyCancel(SCDynamicStoreRef store) } +__private_extern__ kern_return_t _notifycancel(mach_port_t server, int *sc_status) { serverSessionRef mySession = getSession(server); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Cancel requested notifications.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Cancel requested notifications.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + return KERN_SUCCESS; + } *sc_status = __SCDynamicStoreNotifyCancel(mySession->store); if (*sc_status != kSCStatusOK) { diff --git a/configd.tproj/_notifychanges.c b/configd.tproj/_notifychanges.c index 4d9595a..87a7de1 100644 --- a/configd.tproj/_notifychanges.c +++ b/configd.tproj/_notifychanges.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -33,6 +36,7 @@ #include "configd.h" #include "session.h" +__private_extern__ int __SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store, CFArrayRef *notifierKeys) { @@ -73,6 +77,7 @@ __SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store, CFArrayRef *notifierKe } +__private_extern__ kern_return_t _notifychanges(mach_port_t server, xmlDataOut_t *listRef, /* raw XML bytes */ @@ -84,12 +89,19 @@ _notifychanges(mach_port_t server, CFArrayRef notifierKeys; /* array of CFStringRef's */ Boolean ok; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("List notification keys which have changed.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("List notification keys which have changed.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } *listRef = NULL; *listLen = 0; + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + return KERN_SUCCESS; + } + *sc_status = __SCDynamicStoreCopyNotifiedKeys(mySession->store, ¬ifierKeys); if (*sc_status != kSCStatusOK) { return KERN_SUCCESS; diff --git a/configd.tproj/_notifyremove.c b/configd.tproj/_notifyremove.c index 5461ed9..710d2e0 100644 --- a/configd.tproj/_notifyremove.c +++ b/configd.tproj/_notifyremove.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -30,119 +33,64 @@ * - initial revision */ + #include "configd.h" #include "session.h" +#include "pattern.h" -static __inline__ void -my_CFDictionaryApplyFunction(CFDictionaryRef theDict, - CFDictionaryApplierFunction applier, - void *context) -{ - CFAllocatorRef myAllocator; - CFDictionaryRef myDict; - - myAllocator = CFGetAllocator(theDict); - myDict = CFDictionaryCreateCopy(myAllocator, theDict); - CFDictionaryApplyFunction(myDict, applier, context); - CFRelease(myDict); - return; -} - - +__private_extern__ int -__SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex) +__SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, Boolean internal) { + CFNumberRef sessionNum; SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; - 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 (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreRemoveWatchedKey:")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key); + SCLog(TRUE, 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 */ } + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, + CFSTR("%s : %5d : %s : %@\n"), + internal ? "*watch-" : "watch- ", + storePrivate->server, + isRegex ? "pattern" : "key", + key); + } + /* * remove key from this sessions notifier list after checking that * it was previously defined. */ if (isRegex) { - if (!CFSetContainsValue(storePrivate->reKeys, key)) + if (!CFSetContainsValue(storePrivate->patterns, key)) return kSCStatusNoKey; /* sorry, key does not exist in notifier list */ - CFSetRemoveValue(storePrivate->reKeys, key); /* remove key from this sessions notifier list */ + + /* remove key from this sessions notifier list */ + CFSetRemoveValue(storePrivate->patterns, key); + + /* remove this session as a pattern watcher */ + sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server); + patternRemoveSession(key, sessionNum); + CFRelease(sessionNum); } else { 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 (isRegex) { - CFStringRef sessionKey; - CFDictionaryRef info; - CFMutableDictionaryRef newInfo; - CFArrayRef rKeys; - CFMutableArrayRef newRKeys; - CFArrayRef rData; - CFMutableArrayRef newRData; - CFIndex i; - CFDataRef regexData; - removeContext context; - - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); - - info = CFDictionaryGetValue(sessionData, sessionKey); - newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info); - - rKeys = CFDictionaryGetValue(newInfo, kSCDRegexKeys); - newRKeys = CFArrayCreateMutableCopy(NULL, 0, rKeys); - - rData = CFDictionaryGetValue(newInfo, kSCDRegexData); - newRData = CFArrayCreateMutableCopy(NULL, 0, rData); - - i = CFArrayGetFirstIndexOfValue(newRKeys, - CFRangeMake(0, CFArrayGetCount(newRData)), - key); - regexData = CFArrayGetValueAtIndex(newRData, i); - - context.store = storePrivate; - context.preg = (regex_t *)CFDataGetBytePtr(regexData); - my_CFDictionaryApplyFunction(storeData, - (CFDictionaryApplierFunction)_removeRegexWatcherByKey, - &context); - - /* remove the regex key */ - CFArrayRemoveValueAtIndex(newRKeys, i); - if (CFArrayGetCount(newRKeys) > 0) { - CFDictionarySetValue(newInfo, kSCDRegexKeys, newRKeys); - } else { - CFDictionaryRemoveValue(newInfo, kSCDRegexKeys); - } - CFRelease(newRKeys); - - /* ...and the compiled expression */ - regfree((regex_t *)CFDataGetBytePtr(regexData)); - CFArrayRemoveValueAtIndex(newRData, i); - if (CFArrayGetCount(newRData) > 0) { - CFDictionarySetValue(newInfo, kSCDRegexData, newRData); - } else { - CFDictionaryRemoveValue(newInfo, kSCDRegexData); - } - CFRelease(newRData); - - /* save the updated session data */ - CFDictionarySetValue(sessionData, sessionKey, newInfo); - CFRelease(newInfo); - - CFRelease(sessionKey); - } else { - CFNumberRef sessionNum; + /* remove key from this sessions notifier list */ + CFSetRemoveValue(storePrivate->keys, key); /* * We are watching a specific key. As such, update the * store to mark our interest in any changes. */ - sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server); _removeWatcher(sessionNum, key); CFRelease(sessionNum); @@ -152,6 +100,7 @@ __SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boole } +__private_extern__ kern_return_t _notifyremove(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ @@ -163,22 +112,33 @@ _notifyremove(mach_port_t server, serverSessionRef mySession = getSession(server); CFStringRef key; /* key (un-serialized) */ - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Remove notification key for this session.")); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Remove notification key for this session.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + } /* un-serialize the key */ - if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) { + if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; return KERN_SUCCESS; } if (!isA_CFString(key)) { - CFRelease(key); *sc_status = kSCStatusInvalidArgument; + CFRelease(key); + return KERN_SUCCESS; + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + CFRelease(key); return KERN_SUCCESS; } - *sc_status = __SCDynamicStoreRemoveWatchedKey(mySession->store, key, isRegex); + *sc_status = __SCDynamicStoreRemoveWatchedKey(mySession->store, + key, + isRegex != 0, + FALSE); CFRelease(key); return KERN_SUCCESS; diff --git a/configd.tproj/_notifyviafd.c b/configd.tproj/_notifyviafd.c index dd7f3ab..dda1bb1 100644 --- a/configd.tproj/_notifyviafd.c +++ b/configd.tproj/_notifyviafd.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -40,6 +43,7 @@ #include "session.h" +__private_extern__ int __SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, int32_t identifier, @@ -89,6 +93,7 @@ __SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, } +__private_extern__ kern_return_t _notifyviafd(mach_port_t server, xmlData_t pathRef, @@ -105,9 +110,11 @@ _notifyviafd(mach_port_t server, int bufSiz = sizeof(storePrivate->notifyFileIdentifier); int nbioYes = 1; - 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 (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Send message via UNIX domain socket when a notification key changes.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %s"), pathRef); + } /* * if socket currently open, close it! @@ -134,6 +141,11 @@ _notifyviafd(mach_port_t server, /* non-fatal???, proceed */ } + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + return KERN_SUCCESS; + } + /* do common sanity checks, get socket */ *sc_status = __SCDynamicStoreNotifyFileDescriptor(mySession->store, identifier, &sock); diff --git a/configd.tproj/_notifyviaport.c b/configd.tproj/_notifyviaport.c index 0c20ffe..08ee0d7 100644 --- a/configd.tproj/_notifyviaport.c +++ b/configd.tproj/_notifyviaport.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -33,6 +36,7 @@ #include "configd.h" #include "session.h" +__private_extern__ int __SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier, @@ -79,6 +83,7 @@ __SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, } +__private_extern__ kern_return_t _notifyviaport(mach_port_t server, mach_port_t port, @@ -89,10 +94,17 @@ _notifyviaport(mach_port_t server, serverSessionRef mySession = getSession(server); SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)mySession->store; - 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 (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Send mach message when a notification key changes.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(TRUE, LOG_DEBUG, CFSTR(" port = %d"), port); + SCLog(TRUE, LOG_DEBUG, CFSTR(" message id = %d"), identifier); + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + return KERN_SUCCESS; + } if (storePrivate->notifyPort != MACH_PORT_NULL) { SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" destroying old callback mach port %d"), storePrivate->notifyPort); diff --git a/configd.tproj/_notifyviasignal.c b/configd.tproj/_notifyviasignal.c index 7c9b35f..29cd45b 100644 --- a/configd.tproj/_notifyviasignal.c +++ b/configd.tproj/_notifyviasignal.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -34,6 +37,7 @@ #include "configd_server.h" #include "session.h" +__private_extern__ int __SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig) { @@ -83,6 +87,7 @@ __SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig) } +__private_extern__ kern_return_t _notifyviasignal(mach_port_t server, task_t task, @@ -97,15 +102,21 @@ _notifyviasignal(mach_port_t server, mach_port_t oldNotify; #endif /* NOTYET */ - 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); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("Send signal when a notification key changes.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server); + SCLog(TRUE, LOG_DEBUG, CFSTR(" task = %d"), task); + SCLog(TRUE, LOG_DEBUG, CFSTR(" signal = %d"), sig); + } status = pid_for_task(task, &pid); if (status != KERN_SUCCESS) { - /* could not determine pid for task */ - *sc_status = kSCStatusFailed; + *sc_status = kSCStatusFailed; /* could not determine pid for task */ + return KERN_SUCCESS; + } + + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ return KERN_SUCCESS; } diff --git a/configd.tproj/_snapshot.c b/configd.tproj/_snapshot.c index 9f6764f..d07fa1f 100644 --- a/configd.tproj/_snapshot.c +++ b/configd.tproj/_snapshot.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -40,12 +43,90 @@ #define SNAPSHOT_PATH_STORE _PATH_VARTMP "configd-store.xml" +#define SNAPSHOT_PATH_PATTERN _PATH_VARTMP "configd-pattern.xml" #define SNAPSHOT_PATH_SESSION _PATH_VARTMP "configd-session.xml" +#define N_QUICK 100 + +static CFDictionaryRef +_expandStore(CFDictionaryRef storeData) +{ + const void * keys_q[N_QUICK]; + const void ** keys = keys_q; + CFIndex nElements; + CFDictionaryRef newStoreData = NULL; + const void * nValues_q[N_QUICK]; + const void ** nValues = nValues_q; + const void * oValues_q[N_QUICK]; + const void ** oValues = oValues_q; + + nElements = CFDictionaryGetCount(storeData); + if (nElements > 0) { + CFIndex i; + + if (nElements > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { + keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + oValues = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + nValues = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0); + } + bzero(nValues, nElements * sizeof(CFTypeRef)); + + CFDictionaryGetKeysAndValues(storeData, keys, oValues); + for (i = 0; i < nElements; i++) { + CFDataRef data; + + data = CFDictionaryGetValue(oValues[i], kSCDData); + if (data) { + CFPropertyListRef plist; + + if (!_SCUnserialize(&plist, data, NULL, NULL)) { + goto done; + } + + nValues[i] = CFDictionaryCreateMutableCopy(NULL, 0, oValues[i]); + CFDictionarySetValue((CFMutableDictionaryRef)nValues[i], + kSCDData, + plist); + CFRelease(plist); + } else { + nValues[i] = CFRetain(oValues[i]); + } + } + } + + newStoreData = CFDictionaryCreate(NULL, + keys, + nValues, + nElements, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + done : + + if (nElements > 0) { + CFIndex i; + + for (i = 0; i < nElements; i++) { + if (nValues[i]) CFRelease(nValues[i]); + } + + if (keys != keys_q) { + CFAllocatorDeallocate(NULL, keys); + CFAllocatorDeallocate(NULL, oValues); + CFAllocatorDeallocate(NULL, nValues); + } + } + + return newStoreData; +} + + +__private_extern__ int __SCDynamicStoreSnapshot(SCDynamicStoreRef store) { + CFDictionaryRef expandedStoreData; int fd; serverSessionRef mySession; SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; @@ -68,7 +149,27 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store) return kSCStatusFailed; } - xmlData = CFPropertyListCreateXMLData(NULL, storeData); + expandedStoreData = _expandStore(storeData); + xmlData = CFPropertyListCreateXMLData(NULL, expandedStoreData); + CFRelease(expandedStoreData); + if (!xmlData) { + SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed")); + close(fd); + return kSCStatusFailed; + } + (void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData)); + (void) close(fd); + CFRelease(xmlData); + + /* Save a snapshot of the "pattern" data */ + + (void) unlink(SNAPSHOT_PATH_PATTERN); + fd = open(SNAPSHOT_PATH_PATTERN, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd < 0) { + return kSCStatusFailed; + } + + xmlData = CFPropertyListCreateXMLData(NULL, patternData); if (!xmlData) { SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed")); close(fd); @@ -86,8 +187,6 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store) return kSCStatusFailed; } - /* Save a snapshot of the "session" data */ - xmlData = CFPropertyListCreateXMLData(NULL, sessionData); if (!xmlData) { SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed")); @@ -102,6 +201,7 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store) } +__private_extern__ kern_return_t _snapshot(mach_port_t server, int *sc_status) { @@ -109,6 +209,11 @@ _snapshot(mach_port_t server, int *sc_status) SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Snapshot configuration database.")); + if (!mySession) { + *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ + return KERN_SUCCESS; + } + *sc_status = __SCDynamicStoreSnapshot(mySession->store); if (*sc_status != kSCStatusOK) { SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreSnapshot(): %s"), SCErrorString(*sc_status)); diff --git a/configd.tproj/config.defs b/configd.tproj/config.defs index 0d4056a..12c6e0c 100644 --- a/configd.tproj/config.defs +++ b/configd.tproj/config.defs @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ /* * Import the real "config.defs" file from the framework. * diff --git a/configd.tproj/configd.h b/configd.tproj/configd.h index f04426d..cb7ddf8 100644 --- a/configd.tproj/configd.h +++ b/configd.tproj/configd.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -49,8 +52,8 @@ #include "config_types.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 FILE *_configd_trace; /* non-NULL if tracing enabled */ extern CFMutableSetRef _plugins_exclude; /* bundle identifiers to exclude from loading */ extern CFMutableSetRef _plugins_verbose; /* bundle identifiers to enable verbose logging */ diff --git a/configd.tproj/configd.m b/configd.tproj/configd.m index 3a4658f..925dc7b 100644 --- a/configd.tproj/configd.m +++ b/configd.tproj/configd.m @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -30,6 +33,7 @@ * - created */ +#include #include #include #include @@ -44,16 +48,29 @@ #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 */ + +__private_extern__ +FILE *_configd_trace = NULL; /* non-NULL if tracing enabled */ + +__private_extern__ CFMutableSetRef _plugins_exclude = NULL; /* bundle identifiers to exclude from loading */ + +__private_extern__ CFMutableSetRef _plugins_verbose = NULL; /* bundle identifiers to enable verbose logging */ -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" , - "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1", "USR2" +static CFMachPortRef termRequested = NULL; /* Mach port used to notify runloop of a shutdown request */ + + +static struct option longopts[] = { +// { "no-bundles", no_argument, 0, 'b' }, +// { "exclude-plugin", required_argument, 0, 'B' }, +// { "no-fork", no_argument, 0, 'd' }, +// { "test-bundle", required_argument, 0, 't' }, +// { "verbose", no_argument, 0, 'v' }, +// { "verbose-bundle", required_argument, 0, 'V' }, + { "help", no_argument, 0, '?' }, + { 0, 0, 0, 0 } }; @@ -68,7 +85,7 @@ usage(const char *prog) 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); + SCPrint(TRUE, stderr, CFSTR("\t\t (Note: only the plug-in will be started)\n")); exit (EX_USAGE); } @@ -76,33 +93,107 @@ usage(const char *prog) static void catcher(int signum) { - /* - * log the signal - * - * Note: we can't use SCLog() since the signal may be received while the - * logging thread lock is held. - */ - if (_configd_verbose) { - syslog (LOG_INFO, "caught SIG%s" , signames[signum]); - } else { - fprintf(stderr, "caught SIG%s\n", signames[signum]); - fflush (stderr); + switch (signum) { + case SIGTERM : + if (termRequested) { + mach_msg_empty_send_t msg; + mach_msg_option_t options; + kern_return_t status; + + /* + * send message to indicate that a request has been made + * for the daemon to be shutdown. + */ + msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); + msg.header.msgh_size = sizeof(msg); + msg.header.msgh_remote_port = CFMachPortGetPort(termRequested); + msg.header.msgh_local_port = MACH_PORT_NULL; + msg.header.msgh_id = 0; + options = MACH_SEND_TIMEOUT; + status = mach_msg(&msg.header, /* msg */ + MACH_SEND_MSG|options, /* options */ + msg.header.msgh_size, /* send_size */ + 0, /* rcv_size */ + MACH_PORT_NULL, /* rcv_name */ + 0, /* timeout */ + MACH_PORT_NULL); /* notify */ + } + break; } return; } + +static void +term(CFMachPortRef port, void *msg, CFIndex size, void *info) +{ + server_shutdown(); +} + + static void parent_exit(int i) { _exit (0); } + +static void +init_fds() +{ + int fd; + int i; + + /* close any open FDs */ + for (i = getdtablesize()-1; i>=0; i--) close(i); + + /* set stdin, stdout, stderr */ + fd = open(_PATH_DEVNULL, O_RDWR, 0); + if (fd != -1) { + int ofd; + + // stdin + (void) dup2(fd, STDIN_FILENO); + + // stdout, stderr + ofd = open("/var/log/configd.log", O_WRONLY|O_APPEND, 0); + if (ofd != -1) { + if (fd > STDIN_FILENO) { + (void) close(fd); + } + fd = ofd; + } + (void) dup2(fd, STDOUT_FILENO); + (void) dup2(fd, STDERR_FILENO); + if (fd > STDERR_FILENO) { + (void) close(fd); + } + } + + return; +} + + +static void +set_trace() +{ + int fd; + + /* set _configd_trace */ + fd = open("/var/log/configd.trace", O_WRONLY|O_APPEND, 0); + if (fd != -1) { + _configd_trace = fdopen(fd, "a"); + } + + return; +} + + static int fork_child() { int child_pid; - int fd; signal(SIGTERM, parent_exit); child_pid = fork(); @@ -139,28 +230,6 @@ fork_child() (void) chdir("/"); - fd = open(_PATH_DEVNULL, O_RDWR, 0); - if (fd != -1) { - int ofd; - - // stdin - (void) dup2(fd, STDIN_FILENO); - - // stdout, stderr - ofd = open("/var/log/configd.log", O_WRONLY|O_APPEND, 0); - if (ofd != -1) { - if (fd > STDIN_FILENO) { - (void) close(fd); - } - fd = ofd; - } - (void) dup2(fd, STDOUT_FILENO); - (void) dup2(fd, STDERR_FILENO); - if (fd > STDERR_FILENO) { - (void) close(fd); - } - } - return 0; } @@ -181,20 +250,23 @@ writepid(void) int main(int argc, char * const argv[]) { - Boolean loadBundles = TRUE; + Boolean enableRestart = (argc <= 1); /* only if there are no arguments */ + Boolean forceForeground = FALSE; + Boolean loadBundles = TRUE; struct sigaction nact; int opt; extern int optind; - const char *prog = argv[0]; + const char *prog = argv[0]; + mach_port_t service_port = MACH_PORT_NULL; CFStringRef str; - const char *testBundle = NULL; + const char *testBundle = NULL; _plugins_exclude = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); _plugins_verbose = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); /* process any arguments */ - while ((opt = getopt(argc, argv, "bB:dt:vV:")) != -1) { + while ((opt = getopt_long(argc, argv, "bB:dt:vV:", longopts, NULL)) != -1) { switch(opt) { case 'b': loadBundles = FALSE; @@ -205,7 +277,7 @@ main(int argc, char * const argv[]) CFRelease(str); break; case 'd': - _configd_fork = FALSE; + forceForeground = TRUE; break; case 't': testBundle = optarg; @@ -217,9 +289,9 @@ main(int argc, char * const argv[]) if (strcmp(optarg, "com.apple.SystemConfiguration") == 0) { _sc_verbose = TRUE; } else { - str = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingMacRoman); - CFSetSetValue(_plugins_verbose, str); - CFRelease(str); + str = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingMacRoman); + CFSetSetValue(_plugins_verbose, str); + CFRelease(str); } break; case '?': @@ -232,10 +304,12 @@ main(int argc, char * const argv[]) /* * display an error if configd is already running and we are - * not executing/testing a bundle. + * not solely executing/testing a bundle. */ - if ((testBundle == NULL) && (server_active() == TRUE)) { - exit (EX_UNAVAILABLE); + if (testBundle == NULL) { + if (server_active(&service_port)) { + exit (EX_UNAVAILABLE); + } } /* check credentials */ @@ -244,23 +318,33 @@ main(int argc, char * const argv[]) exit (EX_NOPERM); } - if (_configd_fork) { + if (!forceForeground && (service_port == MACH_PORT_NULL)) { + /* + * if we haven't been asked to run in the foreground + * and have not been started by mach_init (i.e. we're + * not already running as a Foreground process) then + * daemonize ourself. + */ if (fork_child() == -1) { fprintf(stderr, "configd: fork() failed, %s\n", strerror(errno)); exit (1); } - /* now the child process, parent waits in fork_child */ - } - /* record process id */ - if (testBundle == NULL) { - writepid(); + /* + * Note: we are now the child process. The parent + * waits/exits in fork_child. + */ } - /* open syslog() facility */ - if (_configd_fork) { + /* + * close file descriptors, establish stdin/stdout/stderr, + * setup logging. + */ + if (!forceForeground) { int logopt = LOG_NDELAY|LOG_PID; + init_fds(); + if (_configd_verbose) logopt |= LOG_CONS; openlog("configd", logopt, LOG_DAEMON); @@ -268,12 +352,18 @@ main(int argc, char * const argv[]) _sc_log = FALSE; /* redirect SCLog() to stdout/stderr */ } - /* add signal handler to catch a SIGHUP */ + /* check/enable trace logging */ + set_trace(); + /* record process id */ + if (testBundle == NULL) { + writepid(); + } + + /* 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"), @@ -281,35 +371,60 @@ main(int argc, char * const argv[]) } /* add signal handler to catch a SIGPIPE */ - if (sigaction(SIGPIPE, &nact, NULL) == -1) { SCLog(_configd_verbose, LOG_ERR, CFSTR("sigaction(SIGPIPE, ...) failed: %s"), strerror(errno)); } - /* get set */ + /* add signal handler to catch a SIGTERM (if dynamic store) */ + if (testBundle == NULL) { + if (enableRestart) { + mach_port_limits_t limits; + CFRunLoopSourceRef rls; + kern_return_t status; + + /* add signal handler */ + if (sigaction(SIGTERM, &nact, NULL) == -1) { + SCLog(_configd_verbose, LOG_ERR, + CFSTR("sigaction(SIGTERM, ...) failed: %s"), + strerror(errno)); + } - objc_setMultithreaded(YES); + /* create the "shutdown requested" notification port */ + termRequested = CFMachPortCreate(NULL, term, NULL, NULL); + + // set queue limit + limits.mpl_qlimit = 1; + status = mach_port_set_attributes(mach_task_self(), + CFMachPortGetPort(termRequested), + MACH_PORT_LIMITS_INFO, + (mach_port_info_t)&limits, + MACH_PORT_LIMITS_INFO_COUNT); + if (status != KERN_SUCCESS) { + perror("mach_port_set_attributes"); + } + + // add to our runloop + rls = CFMachPortCreateRunLoopSource(NULL, termRequested, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + CFRelease(rls); + } - if (testBundle == NULL) { /* initialize primary (store management) thread */ - server_init(); + server_init(service_port, enableRestart); + + if (!forceForeground && (service_port == MACH_PORT_NULL)) { + /* synchronize with parent process */ + kill(getppid(), SIGTERM); + } /* load/initialize/start bundles into the secondary thread */ if (loadBundles) { + objc_setMultithreaded(YES); plugin_init(); - } else { - if (_configd_fork) { - /* synchronize with parent process */ - kill(getppid(), SIGTERM); - } } - } - - /* go */ - if (testBundle == NULL) { /* start primary (store management) thread */ server_loop(); } else { diff --git a/configd.tproj/configd.plist b/configd.tproj/configd.plist new file mode 100644 index 0000000..a8d692a --- /dev/null +++ b/configd.tproj/configd.plist @@ -0,0 +1,12 @@ + + + + + ServiceName + com.apple.SystemConfiguration.configd + Command + /usr/sbin/configd + OnDemand + + + diff --git a/configd.tproj/configd_server.c b/configd.tproj/configd_server.c index c009c55..642d748 100644 --- a/configd.tproj/configd_server.c +++ b/configd.tproj/configd_server.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -43,67 +46,67 @@ 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) */ +/* configd server port (for new session requests) */ +static CFMachPortRef configd_port = NULL; +/* priviledged bootstrap port (for registering/unregistering w/mach_init) */ +static mach_port_t priv_bootstrap_port = MACH_PORT_NULL; +__private_extern__ boolean_t config_demux(mach_msg_header_t *request, mach_msg_header_t *reply) { Boolean processed = FALSE; + serverSessionRef thisSession; mach_msg_format_0_trailer_t *trailer; - /* Feed the request into the ("MiG" generated) server */ - if (!processed && - (request->msgh_id >= _config_subsystem.start && request->msgh_id < _config_subsystem.end)) { - serverSessionRef thisSession; - - thisSession = getSession(request->msgh_local_port); - if (thisSession) { - /* - * Get the caller's credentials (eUID/eGID) from the message trailer. - */ - trailer = (mach_msg_security_trailer_t *)((vm_offset_t)request + - round_msg(request->msgh_size)); - - if ((trailer->msgh_trailer_type == MACH_MSG_TRAILER_FORMAT_0) && - (trailer->msgh_trailer_size >= MACH_MSG_TRAILER_FORMAT_0_SIZE)) { - thisSession->callerEUID = trailer->msgh_sender.val[0]; - thisSession->callerEGID = trailer->msgh_sender.val[1]; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("caller has eUID = %d, eGID = %d"), - thisSession->callerEUID, - thisSession->callerEGID); - } else { - static Boolean warned = FALSE; - - if (!warned) { - SCLog(_configd_verbose, LOG_WARNING, CFSTR("caller's credentials not available.")); - warned = TRUE; - } - thisSession->callerEUID = 0; - thisSession->callerEGID = 0; - } - } - + thisSession = getSession(request->msgh_local_port); + if (thisSession) { /* - * Process configd requests. + * Get the caller's credentials (eUID/eGID) from the message trailer. */ - processed = config_server(request, reply); + trailer = (mach_msg_security_trailer_t *)((vm_offset_t)request + + round_msg(request->msgh_size)); + + if ((trailer->msgh_trailer_type == MACH_MSG_TRAILER_FORMAT_0) && + (trailer->msgh_trailer_size >= MACH_MSG_TRAILER_FORMAT_0_SIZE)) { + thisSession->callerEUID = trailer->msgh_sender.val[0]; + thisSession->callerEGID = trailer->msgh_sender.val[1]; + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("caller has eUID = %d, eGID = %d"), + thisSession->callerEUID, + thisSession->callerEGID); + } else { + static Boolean warned = FALSE; + + if (!warned) { + SCLog(_configd_verbose, LOG_WARNING, CFSTR("caller's credentials not available.")); + warned = TRUE; + } + thisSession->callerEUID = 0; + thisSession->callerEGID = 0; + } } - if (!processed && - (request->msgh_id >= MACH_NOTIFY_FIRST && request->msgh_id < MACH_NOTIFY_LAST)) { + /* + * (attemp to) process configd requests. + */ + processed = config_server(request, reply); + + if (!processed) { + /* + * (attempt to) process (NO MORE SENDERS) notification messages. + */ processed = notify_server(request, reply); } if (!processed) { 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_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; + reply->msgh_size = sizeof(mig_reply_error_t); /* Minimal size */ + reply->msgh_local_port = MACH_PORT_NULL; + reply->msgh_id = request->msgh_id + 100; ((mig_reply_error_t *)reply)->NDR = NDR_record; ((mig_reply_error_t *)reply)->RetCode = MIG_BAD_ID; } @@ -112,101 +115,106 @@ config_demux(mach_msg_header_t *request, mach_msg_header_t *reply) } +#define MACH_MSG_BUFFER_SIZE 128 + + +__private_extern__ void configdCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) { - mig_reply_error_t *bufRequest = msg; - mig_reply_error_t *bufReply = CFAllocatorAllocate(NULL, _config_subsystem.maxsize, 0); + mig_reply_error_t * bufRequest = msg; + uint32_t bufReply_q[MACH_MSG_BUFFER_SIZE/sizeof(uint32_t)]; + mig_reply_error_t * bufReply = (mig_reply_error_t *)bufReply_q; mach_msg_return_t mr; int options; + if (_config_subsystem.maxsize > sizeof(bufReply_q)) { + static Boolean warned = FALSE; + + if (!warned) { + SCLog(_configd_verbose, LOG_NOTICE, + CFSTR("configdCallback(): buffer size should be increased > %d"), + _config_subsystem.maxsize); + warned = TRUE; + } + bufReply = CFAllocatorAllocate(NULL, _config_subsystem.maxsize, 0); + } + /* we have a request message */ (void) config_demux(&bufRequest->Head, &bufReply->Head); - if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) && (bufReply->RetCode != KERN_SUCCESS)) { - + if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)) { if (bufReply->RetCode == MIG_NO_REPLY) { + bufReply->Head.msgh_remote_port = MACH_PORT_NULL; + } else if ((bufReply->RetCode != KERN_SUCCESS) && + (bufRequest->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)) { /* - * This return code is a little tricky -- it appears that the - * demux routine found an error of some sort, but since that - * error would not normally get returned either to the local - * user or the remote one, we pretend it's ok. + * destroy the request - but not the reply port */ - CFAllocatorDeallocate(NULL, bufReply); - return; + bufRequest->Head.msgh_remote_port = MACH_PORT_NULL; + mach_msg_destroy(&bufRequest->Head); } + } + if (bufReply->Head.msgh_remote_port != MACH_PORT_NULL) { /* - * destroy any out-of-line data in the request buffer but don't destroy - * the reply port right (since we need that to send an error message). + * send reply. + * + * We don't want to block indefinitely because the client + * isn't receiving messages from the reply port. + * If we have a send-once right for the reply port, then + * this isn't a concern because the send won't block. + * If we have a send right, we need to use MACH_SEND_TIMEOUT. + * To avoid falling off the kernel's fast RPC path unnecessarily, + * we only supply MACH_SEND_TIMEOUT when absolutely necessary. */ - bufRequest->Head.msgh_remote_port = MACH_PORT_NULL; - mach_msg_destroy(&bufRequest->Head); - } - if (bufReply->Head.msgh_remote_port == MACH_PORT_NULL) { - /* no reply port, so destroy the reply */ - if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) { - mach_msg_destroy(&bufReply->Head); + options = MACH_SEND_MSG; + if (MACH_MSGH_BITS_REMOTE(bufReply->Head.msgh_bits) != MACH_MSG_TYPE_MOVE_SEND_ONCE) { + options |= MACH_SEND_TIMEOUT; + } + mr = mach_msg(&bufReply->Head, /* msg */ + options, /* option */ + bufReply->Head.msgh_size, /* send_size */ + 0, /* rcv_size */ + MACH_PORT_NULL, /* rcv_name */ + MACH_MSG_TIMEOUT_NONE, /* timeout */ + MACH_PORT_NULL); /* notify */ + + /* Has a message error occurred? */ + switch (mr) { + case MACH_SEND_INVALID_DEST: + case MACH_SEND_TIMED_OUT: + break; + default : + /* Includes success case. */ + goto done; } - CFAllocatorDeallocate(NULL, bufReply); - return; } - /* - * send reply. - * - * We don't want to block indefinitely because the client - * isn't receiving messages from the reply port. - * If we have a send-once right for the reply port, then - * this isn't a concern because the send won't block. - * If we have a send right, we need to use MACH_SEND_TIMEOUT. - * To avoid falling off the kernel's fast RPC path unnecessarily, - * we only supply MACH_SEND_TIMEOUT when absolutely necessary. - */ - - options = MACH_SEND_MSG; - if (MACH_MSGH_BITS_REMOTE(bufReply->Head.msgh_bits) == MACH_MSG_TYPE_MOVE_SEND_ONCE) { - options |= MACH_SEND_TIMEOUT; + if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) { + mach_msg_destroy(&bufReply->Head); } - mr = mach_msg(&bufReply->Head, /* msg */ - options, /* option */ - bufReply->Head.msgh_size, /* send_size */ - 0, /* rcv_size */ - MACH_PORT_NULL, /* rcv_name */ - MACH_MSG_TIMEOUT_NONE, /* timeout */ - MACH_PORT_NULL); /* notify */ - - - /* Has a message error occurred? */ - switch (mr) { - case MACH_SEND_INVALID_DEST: - case MACH_SEND_TIMED_OUT: - /* the reply can't be delivered, so destroy it */ - mach_msg_destroy(&bufReply->Head); - break; - default : - /* Includes success case. */ - break; - } + done : - CFAllocatorDeallocate(NULL, bufReply); + if (bufReply != (mig_reply_error_t *)bufReply_q) + CFAllocatorDeallocate(NULL, bufReply); return; } +__private_extern__ boolean_t -server_active() +server_active(mach_port_t *restart_service_port) { - boolean_t active; mach_port_t bootstrap_port; - char *server_name; + char *service_name; kern_return_t status; - server_name = getenv("SCD_SERVER"); - if (!server_name) { - server_name = SCD_SERVER; + service_name = getenv("SCD_SERVER"); + if (!service_name) { + service_name = SCD_SERVER; } /* Getting bootstrap server port */ @@ -218,65 +226,122 @@ server_active() } /* Check "configd" server status */ - status = bootstrap_status(bootstrap_port, server_name, &active); + status = bootstrap_check_in(bootstrap_port, service_name, restart_service_port); switch (status) { case BOOTSTRAP_SUCCESS : - if (active) { - fprintf(stderr, "configd: '%s' server already active\n", - server_name); - return TRUE; - } + /* if we are being restarted by mach_init */ + priv_bootstrap_port = bootstrap_port; break; + case BOOTSTRAP_SERVICE_ACTIVE : + case BOOTSTRAP_NOT_PRIVILEGED : + /* if another instance of the server is active (or starting) */ + fprintf(stderr, "'%s' server already active\n", + service_name); + return TRUE; case BOOTSTRAP_UNKNOWN_SERVICE : + /* if the server is not currently registered/active */ + *restart_service_port = MACH_PORT_NULL; break; default : - fprintf(stderr, "bootstrap_status(): %s\n", - mach_error_string(status)); + fprintf(stderr, "bootstrap_check_in() failed: status=%d\n", status); exit (EX_UNAVAILABLE); } + return FALSE; } + +__private_extern__ void -server_init() +server_init(mach_port_t restart_service_port, Boolean enableRestart) { - boolean_t active; mach_port_t bootstrap_port; CFRunLoopSourceRef rls; - char *server_name; + char *service_name; + mach_port_t service_port = restart_service_port; kern_return_t status; - server_name = getenv("SCD_SERVER"); - if (!server_name) { - server_name = SCD_SERVER; + service_name = getenv("SCD_SERVER"); + if (!service_name) { + service_name = SCD_SERVER; } /* Getting bootstrap server port */ status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port); if (status != KERN_SUCCESS) { - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status)); + SCLog(TRUE, LOG_ERR, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status)); exit (EX_UNAVAILABLE); } - /* Check "configd" server status */ - status = bootstrap_status(bootstrap_port, server_name, &active); - switch (status) { - case BOOTSTRAP_SUCCESS : - if (active) { - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("\"%s\" is currently active, exiting."), server_name); + if (service_port == MACH_PORT_NULL) { + mach_port_t service_send_port; + + /* Check "configd" server status */ + status = bootstrap_check_in(bootstrap_port, service_name, &service_port); + switch (status) { + case BOOTSTRAP_SUCCESS : + /* if we are being restarted by mach_init */ + priv_bootstrap_port = bootstrap_port; + break; + case BOOTSTRAP_NOT_PRIVILEGED : + /* if another instance of the server is starting */ + SCLog(TRUE, LOG_ERR, CFSTR("'%s' server already starting"), service_name); exit (EX_UNAVAILABLE); - } - break; - case BOOTSTRAP_UNKNOWN_SERVICE : - /* service not currently registered, "a good thing" (tm) */ - break; - default : - fprintf(stderr, "bootstrap_status(): %s\n", mach_error_string(status)); - exit (EX_UNAVAILABLE); + case BOOTSTRAP_UNKNOWN_SERVICE : + /* service not currently registered, "a good thing" (tm) */ + if (enableRestart) { + status = bootstrap_create_server(bootstrap_port, + "/usr/sbin/configd", + geteuid(), + FALSE, /* not onDemand == restart now */ + &priv_bootstrap_port); + if (status != BOOTSTRAP_SUCCESS) { + SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_create_server() failed: status=%d"), status); + exit (EX_UNAVAILABLE); + } + } else { + priv_bootstrap_port = bootstrap_port; + } + + status = bootstrap_create_service(priv_bootstrap_port, service_name, &service_send_port); + if (status != BOOTSTRAP_SUCCESS) { + SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_create_service() failed: status=%d"), status); + exit (EX_UNAVAILABLE); + } + + status = bootstrap_check_in(priv_bootstrap_port, service_name, &service_port); + if (status != BOOTSTRAP_SUCCESS) { + SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_check_in() failed: status=%d"), status); + exit (EX_UNAVAILABLE); + } + break; + case BOOTSTRAP_SERVICE_ACTIVE : + /* if another instance of the server is active */ + SCLog(TRUE, LOG_ERR, CFSTR("'%s' server already active"), service_name); + exit (EX_UNAVAILABLE); + default : + SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_check_in() failed: status=%d"), status); + exit (EX_UNAVAILABLE); + } + + } + + /* we don't want to pass our priviledged bootstrap port along to any spawned helpers so... */ + status = bootstrap_unprivileged(priv_bootstrap_port, &bootstrap_port); + if (status != BOOTSTRAP_SUCCESS) { + SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_unprivileged() failed: status=%d"), status); + exit (EX_UNAVAILABLE); + } + + status = task_set_bootstrap_port(mach_task_self(), bootstrap_port); + if (status != BOOTSTRAP_SUCCESS) { + SCLog(TRUE, LOG_ERR, CFSTR("task_set_bootstrap_port(): %s"), + mach_error_string(status)); + exit (EX_UNAVAILABLE); } /* Create the primary / new connection port */ - configd_port = CFMachPortCreate(NULL, configdCallback, NULL, NULL); + configd_port = CFMachPortCreateWithPort(NULL, service_port, configdCallback, NULL, NULL); /* * Create and add a run loop source for the port and add this source @@ -293,27 +358,59 @@ server_init() /* Create a session for the primary / new connection port */ (void) addSession(configd_port); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Registering service \"%s\""), server_name); - status = bootstrap_register(bootstrap_port, server_name, CFMachPortGetPort(configd_port)); + return; +} + + +__private_extern__ +void +server_shutdown() +{ + char *service_name; + mach_port_t service_port; + kern_return_t status; + + /* + * Note: we can't use SCLog() since the signal may be received while the + * logging thread lock is held. + */ + if ((priv_bootstrap_port == MACH_PORT_NULL) || (configd_port == NULL)) { + return; + } + + service_name = getenv("SCD_SERVER"); + if (!service_name) { + service_name = SCD_SERVER; + } + + service_port = CFMachPortGetPort(configd_port); + if (service_port != MACH_PORT_NULL) { + (void) mach_port_destroy(mach_task_self(), service_port); + } + + status = bootstrap_register(priv_bootstrap_port, service_name, MACH_PORT_NULL); switch (status) { case BOOTSTRAP_SUCCESS : - /* service not currently registered, "a good thing" (tm) */ break; - case BOOTSTRAP_NOT_PRIVILEGED : - SCLog(_configd_verbose, LOG_ERR, CFSTR("bootstrap_register(): bootstrap not privileged")); - exit (EX_OSERR); - case BOOTSTRAP_SERVICE_ACTIVE : - SCLog(_configd_verbose, LOG_ERR, CFSTR("bootstrap_register(): bootstrap service active")); - exit (EX_OSERR); + case MACH_SEND_INVALID_DEST : + case MIG_SERVER_DIED : + /* something happened to mach_init */ + break; default : - SCLog(_configd_verbose, LOG_ERR, CFSTR("bootstrap_register(): %s"), mach_error_string(status)); - exit (EX_OSERR); + if (_configd_verbose) { + syslog (LOG_ERR, "bootstrap_register() failed: status=%d" , status); + } else { + fprintf(stderr, "bootstrap_register() failed: status=%d\n", status); + fflush (stderr); + } + exit (EX_UNAVAILABLE); } - return; + exit(EX_OK); } +__private_extern__ void server_loop() { diff --git a/configd.tproj/configd_server.h b/configd.tproj/configd_server.h index cb1c29c..9104deb 100644 --- a/configd.tproj/configd_server.h +++ b/configd.tproj/configd_server.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -39,8 +42,6 @@ #include #include -extern CFMachPortRef configd_port; /* configd server port (for new session requests) */ - __BEGIN_DECLS void configdCallback (CFMachPortRef port, @@ -48,9 +49,12 @@ void configdCallback (CFMachPortRef port, CFIndex size, void *info); -boolean_t server_active (); +boolean_t server_active (mach_port_t *service_port); + +void server_init (mach_port_t service_port, + Boolean enableRestart); -void server_init (); +void server_shutdown (); void server_loop (); @@ -182,6 +186,13 @@ kern_return_t _notifyviasignal kern_return_t _notifycancel (mach_port_t server, int *sc_status); +kern_return_t _notifyset (mach_port_t server, + xmlData_t keysRef, + mach_msg_type_number_t keysLen, + xmlData_t patternsRef, + mach_msg_type_number_t patternsLen, + int *sc_status); + __END_DECLS #endif /* !_S_CONFIGD_SERVER_H */ diff --git a/configd.tproj/notify.c b/configd.tproj/notify.c index 37a3259..0a75827 100644 --- a/configd.tproj/notify.c +++ b/configd.tproj/notify.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -38,6 +41,7 @@ #include "session.h" +__private_extern__ void pushNotifications() { @@ -71,9 +75,11 @@ pushNotifications() /* * Post notification as mach message */ - 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); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("sending mach message notification.")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" port = %d"), storePrivate->notifyPort); + SCLog(TRUE, 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 = storePrivate->notifyPort; @@ -93,9 +99,11 @@ pushNotifications() (storePrivate->notifyFile >= 0)) { ssize_t written; - 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); + if (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("sending (UNIX domain) socket notification")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" fd = %d"), storePrivate->notifyFile); + SCLog(TRUE, LOG_DEBUG, CFSTR(" msgid = %d"), storePrivate->notifyFileIdentifier); + } written = write(storePrivate->notifyFile, &storePrivate->notifyFileIdentifier, @@ -126,9 +134,11 @@ pushNotifications() */ status = pid_for_task(storePrivate->notifySignalTask, &pid); if (status == KERN_SUCCESS) { - 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 (_configd_verbose) { + SCLog(TRUE, LOG_DEBUG, CFSTR("sending signal notification")); + SCLog(TRUE, LOG_DEBUG, CFSTR(" pid = %d"), pid); + SCLog(TRUE, 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; diff --git a/configd.tproj/notify.h b/configd.tproj/notify.h index 790e781..7050f40 100644 --- a/configd.tproj/notify.h +++ b/configd.tproj/notify.h @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/configd.tproj/notify_server.c b/configd.tproj/notify_server.c index 734b90d..4ddc272 100644 --- a/configd.tproj/notify_server.c +++ b/configd.tproj/notify_server.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -31,42 +34,49 @@ #include "session.h" #include "notify.h" +__private_extern__ boolean_t notify_server(mach_msg_header_t *request, mach_msg_header_t *reply) { - mach_no_senders_notification_t *notify = (mach_no_senders_notification_t *)request; + mach_no_senders_notification_t *Request = (mach_no_senders_notification_t *)request; + mig_reply_error_t *Reply = (mig_reply_error_t *)reply; + + 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: update as needed */ + reply->msgh_local_port = MACH_PORT_NULL; + reply->msgh_id = request->msgh_id + 100; - if ((notify->not_header.msgh_id > MACH_NOTIFY_LAST) || - (notify->not_header.msgh_id < MACH_NOTIFY_FIRST)) { + if ((Request->not_header.msgh_id > MACH_NOTIFY_LAST) || + (Request->not_header.msgh_id < MACH_NOTIFY_FIRST)) { + Reply->NDR = NDR_record; + Reply->RetCode = MIG_BAD_ID; return FALSE; /* if this is not a notification message */ } - switch (notify->not_header.msgh_id) { + switch (Request->not_header.msgh_id) { case MACH_NOTIFY_NO_SENDERS : 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); - - (void) mach_port_destroy(mach_task_self(), notify->not_header.msgh_local_port); - - notify->not_header.msgh_remote_port = MACH_PORT_NULL; - return TRUE; - case MACH_NOTIFY_DEAD_NAME : - 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); + Request->not_header.msgh_local_port); + cleanupSession(Request->not_header.msgh_local_port); - (void) mach_port_destroy(mach_task_self(), notify->not_header.msgh_local_port); + (void) mach_port_mod_refs(mach_task_self(), + Request->not_header.msgh_local_port, + MACH_PORT_RIGHT_RECEIVE, -1); - notify->not_header.msgh_remote_port = MACH_PORT_NULL; + Reply->Head.msgh_bits = 0; + Reply->Head.msgh_remote_port = MACH_PORT_NULL; + Reply->RetCode = KERN_SUCCESS; return TRUE; default : break; } 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); + Request->not_header.msgh_local_port, + Request->not_header.msgh_id); - return FALSE; + Reply->NDR = NDR_record; + Reply->RetCode = MIG_BAD_ID; + return FALSE; /* if this is not a notification we are handling */ } diff --git a/configd.tproj/notify_server.h b/configd.tproj/notify_server.h index 150b58e..18a3e5b 100644 --- a/configd.tproj/notify_server.h +++ b/configd.tproj/notify_server.h @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/configd.tproj/pattern.c b/configd.tproj/pattern.c new file mode 100644 index 0000000..444fb86 --- /dev/null +++ b/configd.tproj/pattern.c @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Modification History + * + * April 23, 2003 Allan Nathanson + * - initial revision + */ + + +#include "configd.h" +#include "pattern.h" + + +/* + * Notes: + * + * - pattern matching information is maintained in a dictionary (patternData). + * - the dictionary "key" is the regular expression being matched + * - the dictionary "value" is a CFArray with the following contents + * [0] = CFData consisting of the pre-compiled regular expression + * [1] = CFArray[CFNumber] consisting of the sessions watching this pattern + * [2-n] = dynamic store keys which match this pattern + */ + + +typedef struct { + CFMutableArrayRef pInfo; + regex_t *preg; +} addContext, *addContextRef; + + +static __inline__ void +my_CFDictionaryApplyFunction(CFDictionaryRef theDict, + CFDictionaryApplierFunction applier, + void *context) +{ + CFAllocatorRef myAllocator; + CFDictionaryRef myDict; + + myAllocator = CFGetAllocator(theDict); + myDict = CFDictionaryCreateCopy(myAllocator, theDict); + CFDictionaryApplyFunction(myDict, applier, context); + CFRelease(myDict); + return; +} + + +static void +identifyKeyForPattern(const void *key, void *val, void *context) +{ + CFStringRef storeKey = (CFStringRef)key; + CFDictionaryRef storeValue = (CFDictionaryRef)val; + CFMutableArrayRef pInfo = ((addContextRef)context)->pInfo; + regex_t * preg = ((addContextRef)context)->preg; + + CFIndex len; + int reError; + char str_q[256]; + char * str = str_q; + + if (!CFDictionaryContainsKey(storeValue, kSCDData)) { + /* if no data (yet) */ + return; + } + + /* convert store key to C string */ + len = CFStringGetLength(storeKey) + 1; + if (len > (CFIndex)sizeof(str_q)) + str = CFAllocatorAllocate(NULL, len, 0); + if (_SC_cfstring_to_cstring(storeKey, str, len, kCFStringEncodingASCII) == NULL) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string")); + goto done; + } + + /* compare store key to new notification keys regular expression pattern */ + reError = regexec(preg, str, 0, NULL, 0); + switch (reError) { + case 0 : + /* we've got a match */ + CFArrayAppendValue(pInfo, storeKey); + break; + case REG_NOMATCH : + /* no match */ + break; + default : { + char reErrBuf[256]; + + (void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); + break; + } + } + + done : + + if (str != str_q) CFAllocatorDeallocate(NULL, str); + return; +} + + +__private_extern__ Boolean +patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error) +{ + Boolean append = FALSE; + Boolean insert = FALSE; + CFIndex len = 0; + Boolean ok; + char str_q[256]; + char * str = str_q; + + if (!CFStringHasPrefix(pattern, CFSTR("^"))) { + insert = TRUE; + } + + if (!CFStringHasSuffix(pattern, CFSTR("$")) || + CFStringHasSuffix(pattern, CFSTR("\\$"))) { + append = TRUE; + } + + /* if regex pattern is not bounded at both ends */ + if (insert || append) { + pattern = CFStringCreateWithFormat(NULL, + NULL, + CFSTR("%s%@%s"), + insert ? "^" : "", + pattern, + append ? "$" : ""); + } + + (void)CFStringGetBytes(pattern, + CFRangeMake(0, CFStringGetLength(pattern)), + kCFStringEncodingASCII, + 0, + FALSE, + NULL, + 0, + &len); + if (++len > (CFIndex)sizeof(str_q)) { + str = CFAllocatorAllocate(NULL, len, 0); + } + ok = (_SC_cfstring_to_cstring(pattern, str, len, kCFStringEncodingASCII) != NULL); + if (insert || append) { + CFRelease(pattern); + } + if (ok) { + int reError; + + reError = regcomp(preg, str, REG_EXTENDED); + if (reError != 0) { + char reErrBuf[256]; + + (void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf)); + *error = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingASCII); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regcomp(%s) failed: %s"), str, reErrBuf); + ok = FALSE; + } + } else { + *error = CFRetain(CFSTR("could not convert pattern to regex string")); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("%@"), *error); + } + + if (str != str_q) CFAllocatorDeallocate(NULL, str); + return ok; +} + + +__private_extern__ +CFMutableArrayRef +patternCopy(CFStringRef pattern) +{ + CFArrayRef pInfo; + + pInfo = CFDictionaryGetValue(patternData, pattern); + return pInfo ? CFArrayCreateMutableCopy(NULL, 0, pInfo) : NULL; +} + + +__private_extern__ +CFMutableArrayRef +patternNew(CFStringRef pattern) +{ + addContext context; + CFStringRef err; + CFMutableArrayRef pInfo; + CFMutableDataRef pRegex; + CFArrayRef pSessions; + + /* create the pattern info */ + pInfo = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + /* compile the regular expression from the pattern string. */ + pRegex = CFDataCreateMutable(NULL, sizeof(regex_t)); + CFDataSetLength(pRegex, sizeof(regex_t)); + if (!patternCompile(pattern, (regex_t *)CFDataGetBytePtr(pRegex), &err)) { + CFRelease(err); + CFRelease(pRegex); + CFRelease(pInfo); + return NULL; + } + + /* add the compiled regular expression to the pattern info */ + CFArrayAppendValue(pInfo, pRegex); + + /* add the initial (empty) list of sessions watching this pattern */ + pSessions = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(pInfo, pSessions); + CFRelease(pSessions); + + /* identify/add all existing keys that match the specified pattern */ + context.pInfo = pInfo; + context.preg = (regex_t *)CFDataGetBytePtr(pRegex); + my_CFDictionaryApplyFunction(storeData, + (CFDictionaryApplierFunction)identifyKeyForPattern, + &context); + + CFRelease(pRegex); + return pInfo; +} + + +__private_extern__ +Boolean +patternAddSession(CFStringRef pattern, CFNumberRef sessionNum) +{ + CFIndex i; + CFIndex n; + CFMutableArrayRef pInfo; + CFMutableArrayRef pSessions; + + /* find (or create new instance of) this pattern */ + pInfo = patternCopy(pattern); + if (!pInfo) { + /* if new pattern */ + pInfo = patternNew(pattern); + if (!pInfo) { + return FALSE; + } + } + + /* add this session as a pattern watcher */ + pSessions = (CFMutableArrayRef)CFArrayGetValueAtIndex(pInfo, 1); + pSessions = CFArrayCreateMutableCopy(NULL, 0, pSessions); + CFArrayAppendValue(pSessions, sessionNum); + CFArraySetValueAtIndex(pInfo, 1, pSessions); + CFRelease(pSessions); + + /* update pattern watcher info */ + CFDictionarySetValue(patternData, pattern, pInfo); + + /* add this session as a watcher of any existing keys */ + n = CFArrayGetCount(pInfo); + for (i = 2; i < n; i++) { + CFStringRef matchingKey; + + matchingKey = CFArrayGetValueAtIndex(pInfo, i); + _addWatcher(sessionNum, matchingKey); + } + + CFRelease(pInfo); + return TRUE; +} + + +__private_extern__ +void +patternRemoveSession(CFStringRef pattern, CFNumberRef sessionNum) +{ + CFIndex i; + CFIndex n; + CFMutableArrayRef pInfo; + CFDataRef pRegex; + CFMutableArrayRef pSessions; + + /* find instance of this pattern */ + pInfo = patternCopy(pattern); + + /* remove this session as a watcher from all matching keys */ + n = CFArrayGetCount(pInfo); + for (i = 2; i < n; i++) { + CFStringRef matchingKey; + + matchingKey = CFArrayGetValueAtIndex(pInfo, i); + _removeWatcher(sessionNum, matchingKey); + } + + /* remove session from watchers */ + pSessions = (CFMutableArrayRef)CFArrayGetValueAtIndex(pInfo, 1); + n = CFArrayGetCount(pSessions); + if (n > 1) { + /* if other sessions are watching this pattern */ + + pSessions = CFArrayCreateMutableCopy(NULL, 0, pSessions); + i = CFArrayGetFirstIndexOfValue(pSessions, CFRangeMake(0, n), sessionNum); + CFArrayRemoveValueAtIndex(pSessions, i); + CFArraySetValueAtIndex(pInfo, 1, pSessions); + CFRelease(pSessions); + + CFDictionarySetValue(patternData, pattern, pInfo); + } else { + /* if no other sessions are watching this pattern */ + + pRegex = CFArrayGetValueAtIndex(pInfo, 0); + regfree((regex_t *)CFDataGetBytePtr(pRegex)); + CFDictionaryRemoveValue(patternData, pattern); + } + + CFRelease(pInfo); + return; +} + + +static void +addKeyForPattern(const void *key, void *val, void *context) +{ + CFStringRef pattern = (CFStringRef)key; + CFArrayRef pInfo = (CFArrayRef)val; + CFStringRef storeKey = (CFStringRef)context; + + CFIndex len; + regex_t *preg; + int reError; + char str_q[256]; + char * str = str_q; + + /* convert store key to C string */ + len = CFStringGetLength(storeKey) + 1; + if (len > (CFIndex)sizeof(str_q)) + str = CFAllocatorAllocate(NULL, len, 0); + if (_SC_cfstring_to_cstring(storeKey, str, len, kCFStringEncodingASCII) == NULL) { + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string")); + goto done; + } + + /* compare new store key to regular expression pattern */ + preg = (regex_t *)CFDataGetBytePtr(CFArrayGetValueAtIndex(pInfo, 0)); + reError = regexec(preg, str, 0, NULL, 0); + switch (reError) { + case 0 : { + /* + * we've got a match + */ + CFIndex i; + CFIndex n; + CFMutableArrayRef pInfo_new; + CFArrayRef pSessions; + + /* add watchers */ + pSessions = CFArrayGetValueAtIndex(pInfo, 1); + n = CFArrayGetCount(pSessions); + for (i = 0; i < n; i++) { + CFNumberRef sessionNum = CFArrayGetValueAtIndex(pSessions, i); + + _addWatcher(sessionNum, storeKey); + } + + /* add key, update pattern watcher info */ + pInfo_new = CFArrayCreateMutableCopy(NULL, 0, pInfo); + CFArrayAppendValue(pInfo_new, storeKey); + CFDictionarySetValue(patternData, pattern, pInfo_new); + CFRelease(pInfo_new); + break; + } + case REG_NOMATCH : + /* no match */ + break; + default : { + char reErrBuf[256]; + + (void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf)); + SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); + break; + } + } + + done : + + if (str != str_q) CFAllocatorDeallocate(NULL, str); + return; +} + + +__private_extern__ +void +patternAddKey(CFStringRef key) +{ + my_CFDictionaryApplyFunction(patternData, + (CFDictionaryApplierFunction)addKeyForPattern, + (void *)key); + + return; +} + + +static void +removeKeyFromPattern(const void *key, void *val, void *context) +{ + CFStringRef pattern = (CFStringRef)key; + CFArrayRef pInfo = (CFArrayRef)val; + CFStringRef storeKey = (CFStringRef)context; + + CFIndex i; + CFIndex n; + CFMutableArrayRef pInfo_new; + CFArrayRef pSessions; + + n = CFArrayGetCount(pInfo); + if (n <= 2) { + /* if no keys match this pattern */ + return; + } + + i = CFArrayGetFirstIndexOfValue(pInfo, CFRangeMake(2, n-2), storeKey); + if (i == -1) { + /* if this key wasn't matched by this pattern */ + return; + } + + /* remove key from pattern info */ + pInfo_new = CFArrayCreateMutableCopy(NULL, 0, pInfo); + CFArrayRemoveValueAtIndex(pInfo_new, i); + + /* remove watchers */ + pSessions = CFArrayGetValueAtIndex(pInfo_new, 1); + n = CFArrayGetCount(pSessions); + for (i = 0; i < n; i++) { + CFNumberRef sessionNum = CFArrayGetValueAtIndex(pSessions, i); + + _removeWatcher(sessionNum, storeKey); + } + + CFDictionarySetValue(patternData, pattern, pInfo_new); + CFRelease(pInfo_new); + return; +} + + +__private_extern__ +void +patternRemoveKey(CFStringRef key) +{ + my_CFDictionaryApplyFunction(patternData, + (CFDictionaryApplierFunction)removeKeyFromPattern, + (void *)key); + + return; +} diff --git a/configd.tproj/pattern.h b/configd.tproj/pattern.h new file mode 100644 index 0000000..89535c4 --- /dev/null +++ b/configd.tproj/pattern.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Modification History + * + * April 23, 2003 Allan Nathanson + * - initial revision + */ + + +#ifndef _S_PATTERN_H +#define _S_PATTERN_H + +#include + +__BEGIN_DECLS + +Boolean patternCompile (CFStringRef pattern, + regex_t *preg, + CFStringRef *error); + +CFMutableArrayRef patternCopy (CFStringRef pattern); + +CFMutableArrayRef patternNew (CFStringRef pattern); + +Boolean patternAddSession (CFStringRef pattern, + CFNumberRef sessionNum); + +void patternRemoveSession (CFStringRef pattern, + CFNumberRef sessionNum); + +void patternAddKey (CFStringRef key); + +void patternRemoveKey (CFStringRef key); + +__END_DECLS + +#endif /* !_S_PATTERN_H */ diff --git a/configd.tproj/plugin_support.c b/configd.tproj/plugin_support.c index 1f92749..c9e1177 100644 --- a/configd.tproj/plugin_support.c +++ b/configd.tproj/plugin_support.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -343,7 +346,7 @@ startBundle(const void *value, void *context) { /* check if this directory entry is a valid bundle name */ len = strlen(cp); - if (len <= sizeof(BUNDLE_DIR_EXTENSION)) { + if (len <= (int)sizeof(BUNDLE_DIR_EXTENSION)) { /* if entry name isn't long enough */ return; } @@ -404,14 +407,16 @@ sortBundles(CFMutableArrayRef orig) new = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); while (CFArrayGetCount(orig) > 0) { int i; - Boolean inserted = FALSE; + Boolean inserted = FALSE; + int nOrig = CFArrayGetCount(orig); - for (i = 0; i < CFArrayGetCount(orig); i++) { + for (i = 0; i < nOrig; i++) { CFBundleRef bundle1 = (CFBundleRef)CFArrayGetValueAtIndex(orig, i); CFStringRef bundleID1 = CFBundleGetIdentifier(bundle1); int count; CFDictionaryRef dict; int j; + int nRequires; CFArrayRef requires = NULL; dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundle1)); @@ -425,12 +430,14 @@ sortBundles(CFMutableArrayRef orig) inserted = TRUE; break; } - count = CFArrayGetCount(requires); - for (j = 0; j < CFArrayGetCount(requires); j++) { + count = nRequires = CFArrayGetCount(requires); + for (j = 0; j < nRequires; j++) { int k; + int nNew; CFStringRef r = CFArrayGetValueAtIndex(requires, j); - for (k = 0; k < CFArrayGetCount(new); k++) { + nNew = CFArrayGetCount(new); + for (k = 0; k < nNew; k++) { CFBundleRef bundle2 = (CFBundleRef)CFArrayGetValueAtIndex(new, k); CFStringRef bundleID2 = CFBundleGetIdentifier(bundle2); @@ -468,6 +475,7 @@ sortBundles(CFMutableArrayRef orig) } +__private_extern__ void * plugin_exec(void *arg) { @@ -476,8 +484,8 @@ plugin_exec(void *arg) /* keep track of bundles */ allBundles = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - /* allow plug-ins to exec child/helper processes */ - _SCDPluginExecInit(); + /* allow plug-ins to exec child/helper processes */ + _SCDPluginExecInit(); if (arg == NULL) { char path[MAXPATHLEN]; @@ -594,11 +602,6 @@ plugin_exec(void *arg) } #endif /* DEBUG */ - if (_configd_fork) { - /* synchronize with parent process */ - kill(getppid(), SIGTERM); - } - /* * The assumption is that each loaded plugin will establish CFMachPortRef, * CFSocketRef, and CFRunLoopTimerRef input sources to handle any events @@ -613,6 +616,7 @@ plugin_exec(void *arg) } +__private_extern__ void plugin_init() { diff --git a/configd.tproj/plugin_support.h b/configd.tproj/plugin_support.h index 5097a4c..9664ef2 100644 --- a/configd.tproj/plugin_support.h +++ b/configd.tproj/plugin_support.h @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/configd.tproj/session.c b/configd.tproj/session.c index 0ded56d..d2175fc 100644 --- a/configd.tproj/session.c +++ b/configd.tproj/session.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -39,6 +42,7 @@ static serverSessionRef *sessions = NULL; static int nSessions = 0; +__private_extern__ serverSessionRef getSession(mach_port_t server) { @@ -49,19 +53,17 @@ getSession(mach_port_t server) return NULL; } - if (nSessions > 0) { - for (i=0; ikey == server) { - return thisSession; /* we've seen this server before */ - } else if (thisSession->store && - (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) { - return thisSession; - } + for (i = 0; i < nSessions; i++) { + serverSessionRef thisSession = sessions[i]; + + if (thisSession == NULL) { + /* found an empty slot, skip it */ + continue; + } else if (thisSession->key == server) { + return thisSession; /* we've seen this server before */ + } else if (thisSession->store && + (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) { + return thisSession; } } @@ -70,6 +72,7 @@ getSession(mach_port_t server) } +__private_extern__ serverSessionRef addSession(CFMachPortRef server) { @@ -82,7 +85,7 @@ addSession(CFMachPortRef server) n = 0; nSessions = 1; } else { - for (i=0; ikey == server)) { @@ -158,6 +163,10 @@ cleanupSession(mach_port_t server) * session entry still exists. */ + if (_configd_trace) { + SCTrace(TRUE, _configd_trace, CFSTR("cleanup : %5d\n"), server); + } + /* * Ensure that any changes made while we held the "lock" * are discarded. @@ -176,7 +185,7 @@ cleanupSession(mach_port_t server) * Close any open connections including cancelling any outstanding * notification requests and releasing any locks. */ - (void) __SCDynamicStoreClose(&thisSession->store); + (void) __SCDynamicStoreClose(&thisSession->store, TRUE); /* * Lastly, remove the session entry. @@ -190,13 +199,14 @@ cleanupSession(mach_port_t server) } +__private_extern__ void listSessions() { int i; fprintf(stderr, "Current sessions:"); - for (i=0; i - - + + CurrentSet /Sets/0 @@ -18,13 +18,17 @@ DNS Ethernet - - + IPv4 ConfigMethod DHCP + IPv6 + + ConfigMethod + Automatic + Interface DeviceName @@ -133,7 +137,6 @@ System - - + diff --git a/scselect.tproj/Makefile.postamble b/scselect.tproj/Makefile.postamble index e6f3e09..46b1c86 100644 --- a/scselect.tproj/Makefile.postamble +++ b/scselect.tproj/Makefile.postamble @@ -64,6 +64,7 @@ # the include path (defaults to -I.) # DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags # passed to ld/libtool (defaults to nothing) +WARNING_CFLAGS=-Wall # Library and Framework projects only: diff --git a/scselect.tproj/scselect.c b/scselect.tproj/scselect.c index ec6b6a3..2e29fe2 100644 --- a/scselect.tproj/scselect.c +++ b/scselect.tproj/scselect.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -30,7 +33,9 @@ * - initial revision */ +#include #include +#include #include #include @@ -39,11 +44,20 @@ Boolean apply = TRUE; +static struct option longopts[] = { +// { "debug", no_argument, 0, 'd' }, +// { "verbose", no_argument, 0, 'v' }, +// { "do-not-apply", no_argument, 0, 'n' }, + { "help", no_argument, 0, '?' }, + { 0, 0, 0, 0 } +}; + + void usage(const char *command) { SCPrint(TRUE, stderr, CFSTR("usage: %s [-n] new-set-name\n"), command); - return; + exit (EX_USAGE); } @@ -67,7 +81,7 @@ main(int argc, char **argv) /* process any arguments */ - while ((opt = getopt(argc, argv, "dvn")) != -1) + while ((opt = getopt_long(argc, argv, "dvn", longopts, NULL)) != -1) switch(opt) { case 'd': _sc_debug = TRUE; @@ -146,7 +160,7 @@ main(int argc, char **argv) } /* check for set with matching name */ - for (i=0; i 0) ? " (* == current set)" : ""); - for (i=0; i #include "scutil.h" +#include "cache.h" static CFComparisonResult @@ -76,7 +80,7 @@ do_list(int argc, char **argv) NULL); if (listCnt > 0) { - for (i=0; i +#include "SCDynamicStoreInternal.h" const cmdInfo commands[] = { @@ -96,8 +99,8 @@ const cmdInfo commands[] = { { "set", 1, 1, do_set, 4, 0, " set key : set key in data store w/current dict" }, - { "show", 1, 1, do_show, 4, 1, - " show key : show dict in data store w/key" }, + { "show", 1, 2, do_show, 4, 0, + " show key [\"pattern\"] : show values in data store w/key" }, { "remove", 1, 1, do_remove, 4, 0, " remove key : remove key from data store" }, @@ -153,7 +156,7 @@ do_command(int argc, char **argv) int i; char *cmd = argv[0]; - for (i=0; i 1) && !enablePrivateAPI) { continue; /* if "private" API and access has not been enabled */ } @@ -185,7 +188,7 @@ do_help(int argc, char **argv) int i; SCPrint(TRUE, stdout, CFSTR("\nAvailable commands:\n")); - for (i=0; i 0) && !enablePrivateAPI) { continue; /* if "private" API and access has not been enabled */ } @@ -208,13 +211,16 @@ do_help(int argc, char **argv) void do_readFile(int argc, char **argv) { - CFSocketContext context; - FILE *fp = fopen(argv[0], "r"); - CFSocketRef in; - CFRunLoopSourceRef rls; + InputRef src; - if (fp == NULL) { + /* allocate command input stream */ + src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0); + src->el = NULL; + src->fp = fopen(argv[0], "r"); + + if (src->fp == NULL) { SCPrint(TRUE, stdout, CFSTR("f.read: could not open file (%s).\n"), strerror(errno)); + CFAllocatorDeallocate(NULL, src); return; } @@ -222,38 +228,13 @@ do_readFile(int argc, char **argv) SCPrint(TRUE, stdout, CFSTR("f.read: reading file (%s).\n"), argv[0]); 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); + while (process_line(src) == TRUE) { + /* debug information, diagnostics */ + __showMachPortStatus(); + } + + (void)fclose(src->fp); + CFAllocatorDeallocate(NULL, src); return; } diff --git a/scutil.tproj/commands.h b/scutil.tproj/commands.h index 00b7ecd..e5eb65f 100644 --- a/scutil.tproj/commands.h +++ b/scutil.tproj/commands.h @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/scutil.tproj/dictionary.c b/scutil.tproj/dictionary.c index 5b846c6..1261a5c 100644 --- a/scutil.tproj/dictionary.c +++ b/scutil.tproj/dictionary.c @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -31,6 +34,7 @@ */ #include "scutil.h" +#include "dictionary.h" //#include diff --git a/scutil.tproj/dictionary.h b/scutil.tproj/dictionary.h index 0a521a0..1f8d63a 100644 --- a/scutil.tproj/dictionary.h +++ b/scutil.tproj/dictionary.h @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/scutil.tproj/notify.c b/scutil.tproj/notify.c index ec3ec89..492b6e7 100644 --- a/scutil.tproj/notify.c +++ b/scutil.tproj/notify.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -30,15 +33,14 @@ * - initial revision */ +#include #include #include #include #include #include "scutil.h" - -#include -#include "v1Compatibility.h" +#include "notify.h" static int osig; @@ -63,7 +65,7 @@ storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) n = CFArrayGetCount(changedKeys); if (n > 0) { - for (i=0; i 0) { - for (i=0; i 0) { - for (i=0; i + * - initial revision + */ + +#include "scutil.h" +#include "prefs.h" + +#include + + +static SCPreferencesRef +_open() +{ + SCPreferencesRef prefs; + + prefs = SCPreferencesCreate(NULL, CFSTR("scutil"), NULL); + if (!prefs) { + SCPrint(TRUE, + stdout, + CFSTR("SCPreferencesCreate() failed: %s\n"), + SCErrorString(SCError())); + exit (1); + } + + return prefs; +} + + +static void +_save(SCPreferencesRef prefs) +{ + if (!SCPreferencesCommitChanges(prefs)) { + switch (SCError()) { + case kSCStatusAccessError : + SCPrint(TRUE, stderr, CFSTR("Permission denied.\n")); + break; + default : + SCPrint(TRUE, + stdout, + CFSTR("SCPreferencesCommitChanges() failed: %s\n"), + SCErrorString(SCError())); + break; + } + exit (1); + } + + if (!SCPreferencesApplyChanges(prefs)) { + SCPrint(TRUE, + stdout, + CFSTR("SCPreferencesApplyChanges() failed: %s\n"), + SCErrorString(SCError())); + exit (1); + } + + return; +} + + +static CFStringRef +_copyStringFromSTDIN() +{ + char buf[1024]; + size_t len; + CFStringRef utf8; + + if (fgets(buf, sizeof(buf), stdin) == NULL) { + return NULL; + } + + len = strlen(buf); + if (buf[len-1] == '\n') { + buf[--len] = '\0'; + } + + utf8 = CFStringCreateWithBytes(NULL, buf, len, kCFStringEncodingUTF8, TRUE); + return utf8; +} + + +static void +get_ComputerName(int argc, char **argv) +{ + CFStringEncoding encoding; + CFStringRef hostname; + CFDataRef utf8; + + hostname = SCDynamicStoreCopyComputerName(NULL, &encoding); + if (!hostname) { + int sc_status = SCError(); + + switch (sc_status) { + case kSCStatusNoKey : + SCPrint(TRUE, + stderr, + CFSTR("ComputerName: not set\n")); + break; + default : + SCPrint(TRUE, + stderr, + CFSTR("SCDynamicStoreCopyComputerName() failed: %s\n"), + SCErrorString(SCError())); + break; + } + exit (1); + } + + utf8 = CFStringCreateExternalRepresentation(NULL, hostname, kCFStringEncodingUTF8, 0); + if (!utf8) { + SCPrint(TRUE, + stderr, + CFSTR("ComputerName: could not convert to external representation\n")); + exit(1); + } + SCPrint(TRUE, stdout, CFSTR("%.*s\n"), CFDataGetLength(utf8), CFDataGetBytePtr(utf8)); + + CFRelease(utf8); + CFRelease(hostname); + exit(0); +} + + +static void +set_ComputerName(int argc, char **argv) +{ + CFStringEncoding encoding; + CFStringRef hostname; + SCPreferencesRef prefs; + + if (argc == 0) { + hostname = _copyStringFromSTDIN(); + encoding = kCFStringEncodingUTF8; + } else { + hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingASCII); + encoding = kCFStringEncodingASCII; + } + + prefs = _open(); + if (!SCPreferencesSetComputerName(prefs, hostname, encoding)) { + SCPrint(TRUE, + stdout, + CFSTR("SCPreferencesSetComputerName() failed: %s\n"), + SCErrorString(SCError())); + exit (1); + } + _save(prefs); + CFRelease(prefs); + CFRelease(hostname); + exit(0); +} + + +static void +get_LocalHostName(int argc, char **argv) +{ + CFStringRef hostname; + + hostname = SCDynamicStoreCopyLocalHostName(NULL); + if (!hostname) { + int sc_status = SCError(); + + switch (sc_status) { + case kSCStatusNoKey : + SCPrint(TRUE, + stderr, + CFSTR("LocalHostName: not set\n")); + break; + default : + SCPrint(TRUE, + stderr, + CFSTR("SCDynamicStoreCopyLocalHostName() failed: %s\n"), + SCErrorString(SCError())); + break; + } + exit (1); + } + + SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname); + CFRelease(hostname); + exit(0); +} + + +static void +set_LocalHostName(int argc, char **argv) +{ + CFStringRef hostname = NULL; + SCPreferencesRef prefs; + + if (argc == 0) { + hostname = _copyStringFromSTDIN(); + } else { + hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingASCII); + } + + prefs = _open(); + if (!SCPreferencesSetLocalHostName(prefs, hostname)) { + SCPrint(TRUE, + stderr, + CFSTR("SCPreferencesSetLocalHostName() failed: %s\n"), + SCErrorString(SCError())); + exit (1); + } + _save(prefs); + CFRelease(prefs); + CFRelease(hostname); + exit(0); +} + + +typedef void (*pref_func) (int argc, char **argv); + +static struct { + char *pref; + pref_func get; + pref_func set; +} prefs[] = { + { "ComputerName", get_ComputerName, set_ComputerName }, + { "LocalHostName", get_LocalHostName, set_LocalHostName } +}; +#define N_PREFS (sizeof(prefs) / sizeof(prefs[0])) + + +int +findPref(char *pref) +{ + int i; + + for (i = 0; i < (int)N_PREFS; i++) { + if (strcmp(pref, prefs[i].pref) == 0) { + return i; + } + } + + return -1; +} + + +void +do_getPref(char *pref, int argc, char **argv) +{ + int i; + + i = findPref(pref); + if (i >= 0) { + (*prefs[i].get)(argc, argv); + } + return; +} + + +void +do_setPref(char *pref, int argc, char **argv) +{ + int i; + + i = findPref(pref); + if (i >= 0) { + (*prefs[i].set)(argc, argv); + } + return; +} diff --git a/scutil.tproj/prefs.h b/scutil.tproj/prefs.h new file mode 100644 index 0000000..49c8f82 --- /dev/null +++ b/scutil.tproj/prefs.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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, QUIET ENJOYMENT 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 29, 2003 Allan Nathanson + * - initial revision + */ + +#ifndef _PREFS_H +#define _PREFS_H + +#include + +__BEGIN_DECLS + +int findPref (char *pref); +void do_getPref (char *pref, int argc, char **argv); +void do_setPref (char *pref, int argc, char **argv); + +__END_DECLS + +#endif /* !_PREFS_H */ diff --git a/scutil.tproj/scutil.c b/scutil.tproj/scutil.c index 69cc760..ecea776 100644 --- a/scutil.tproj/scutil.c +++ b/scutil.tproj/scutil.c @@ -1,28 +1,34 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ /* * Modification History * + * September 25, 2002 Allan Nathanson + * - added command line history & editing + * * July 9, 2001 Allan Nathanson * - added "-r" option for checking network reachability * - added "-w" option to check/wait for the presence of a @@ -36,9 +42,11 @@ */ #include +#include #include #include #include +#include #include #include @@ -51,8 +59,8 @@ #include "commands.h" #include "dictionary.h" #include "tests.h" +#include "prefs.h" -#include #include "SCDynamicStoreInternal.h" @@ -60,29 +68,61 @@ int nesting = 0; +CFRunLoopRef notifyRl = NULL; CFRunLoopSourceRef notifyRls = NULL; -CFMutableArrayRef sources = NULL; SCDynamicStoreRef store = NULL; CFPropertyListRef value = NULL; +CFMutableArrayRef watchedKeys = NULL; +CFMutableArrayRef watchedPatterns = NULL; + +static struct option longopts[] = { +// { "debug", no_argument, NULL, 'd' }, +// { "verbose", no_argument, NULL, 'v' }, +// { "SPI", no_argument, NULL, 'p' }, +// { "check-reachability", required_argument, NULL, 'r' }, +// { "timeout", required_argument, NULL, 't' }, +// { "wait-key", required_argument, NULL, 'w' }, + { "get", required_argument, NULL, 0 }, + { "help", no_argument, NULL, '?' }, + { "set", required_argument, NULL, 0 }, + { NULL, 0, NULL, 0 } +}; static char * -getLine(char *buf, int len, FILE *fp) +getLine(char *buf, int len, InputRef src) { - int x; + int n; - if (fgets(buf, len, fp) == NULL) - return NULL; + if (src->el) { + int count; + const char *line; - x = strlen(buf); - if (buf[x-1] == '\n') { - /* the entire line fit in the buffer, remove the newline */ - buf[x-1] = '\0'; + line = el_gets(src->el, &count); + if (line == NULL) + return NULL; + + strncpy(buf, line, len); } else { + if (fgets(buf, len, src->fp) == NULL) + return NULL; + } + + n = strlen(buf); + if (buf[n-1] == '\n') { + /* the entire line fit in the buffer, remove the newline */ + buf[n-1] = '\0'; + } else if (!src->el) { /* eat the remainder of the line */ do { - x = fgetc(fp); - } while ((x != '\n') && (x != EOF)); + n = fgetc(src->fp); + } while ((n != '\n') && (n != EOF)); + } + + if (src->h) { + HistEvent ev; + + history(src->h, &ev, H_ENTER, buf); } return buf; @@ -141,13 +181,13 @@ getString(char **line) Boolean -process_line(FILE *fp) +process_line(InputRef src) { char line[LINE_LENGTH], *s, *arg, **argv = NULL; int i, argc; /* if end-of-file, exit */ - if (getLine(line, sizeof(line), fp) == NULL) + if (getLine(line, sizeof(line), src) == NULL) return FALSE; if (nesting > 0) { @@ -186,81 +226,57 @@ process_line(FILE *fp) } -void -runLoopProcessInput(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) -{ - FILE *fp = info; - - if (process_line(fp) == FALSE) { - /* we don't want any more input from this stream, stop listening */ - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), - (CFRunLoopSourceRef)CFArrayGetValueAtIndex(sources, 0), - kCFRunLoopDefaultMode); - - /* we no longer need the fd (socket) */ - CFSocketInvalidate(s); - - /* we no longer need to track this source */ - CFArrayRemoveValueAtIndex(sources, 0); - - if (CFArrayGetCount(sources) > 0) { - /* add the previous input source to the run loop */ - CFRunLoopAddSource(CFRunLoopGetCurrent(), - (CFRunLoopSourceRef)CFArrayGetValueAtIndex(sources, 0), - kCFRunLoopDefaultMode); - } else { - /* no more input sources, we're done! */ - exit (EX_OK); - } - - /* decrement the nesting level */ - nesting--; - } - - /* debug information, diagnostics */ - __showMachPortStatus(); - - /* 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("\tinteractive access to the dynamic store.\n")); + SCPrint(TRUE, stderr, CFSTR("\n")); + SCPrint(TRUE, stderr, CFSTR(" or: %s -r nodename\n"), command); + SCPrint(TRUE, stderr, CFSTR(" or: %s -r address\n"), command); + SCPrint(TRUE, stderr, CFSTR(" or: %s -r local-address remote-address\n"), command); + SCPrint(TRUE, stderr, CFSTR("\tcheck reachability of node, address, or address pair.\n")); + SCPrint(TRUE, stderr, CFSTR("\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")); + SCPrint(TRUE, stderr, CFSTR(" or: %s --get pref\n"), command); + SCPrint(TRUE, stderr, CFSTR(" or: %s --set pref [newval]\n"), command); + SCPrint(TRUE, stderr, CFSTR("\tpref\tdisplay (or set) the specified preference. Valid preferences\n")); + SCPrint(TRUE, stderr, CFSTR("\t\tinclude:\n")); + SCPrint(TRUE, stderr, CFSTR("\t\t\tComputerName, LocalHostName\n")); + SCPrint(TRUE, stderr, CFSTR("\tnewval\tNew preference value to be set. If not specified,\n")); + SCPrint(TRUE, stderr, CFSTR("\t\tthe new value will be read from standard input.\n")); exit (EX_USAGE); } +static char * +prompt(EditLine *el) +{ + return "> "; +} + + int main(int argc, char * const argv[]) { - CFSocketContext context = { 0, stdin, NULL, NULL, NULL }; - char *dest = NULL; - CFSocketRef in; + char *get = NULL; extern int optind; int opt; + int opti; const char *prog = argv[0]; - CFRunLoopSourceRef rls; + Boolean reach = FALSE; + char *set = NULL; + InputRef src; int timeout = 15; /* default timeout (in seconds) */ char *wait = NULL; + int xStore = 0; /* non dynamic store command line options */ /* process any arguments */ - while ((opt = getopt(argc, argv, "dvpr:t:w:")) != -1) + while ((opt = getopt_long(argc, argv, "dvprt:w:", longopts, &opti)) != -1) switch(opt) { case 'd': _sc_debug = TRUE; @@ -274,13 +290,24 @@ main(int argc, char * const argv[]) enablePrivateAPI = TRUE; break; case 'r': - dest = optarg; + reach = TRUE; + xStore++; break; case 't': timeout = atoi(optarg); break; case 'w': wait = optarg; + xStore++; + break; + case 0: + if (strcmp(longopts[opti].name, "get") == 0) { + get = optarg; + xStore++; + } else if (strcmp(longopts[opti].name, "set") == 0) { + set = optarg; + xStore++; + } break; case '?': default : @@ -289,13 +316,17 @@ main(int argc, char * const argv[]) argc -= optind; argv += optind; - if (dest && wait) { + if (xStore > 1) { + // if we are attempting to process more than one type of request usage(prog); } /* are we checking the reachability of a host/address */ - if (dest) { - do_checkReachability(dest); + if (reach) { + if ((argc < 1) || (argc > 2)) { + usage(prog); + } + do_checkReachability(argc, (char **)argv); /* NOT REACHED */ } @@ -305,38 +336,78 @@ main(int argc, char * const argv[]) /* NOT REACHED */ } + /* are we looking up a preference value */ + if (get) { + if (findPref(get) < 0) { + usage(prog); + } + do_getPref(get, argc, (char **)argv); + /* NOT REACHED */ + } + + /* are we changing a preference value */ + if (set) { + if (findPref(set) < 0) { + usage(prog); + } + do_setPref(set, argc, (char **)argv); + /* NOT REACHED */ + } + /* start with an empty dictionary */ do_dictInit(0, NULL); - /* create a "socket" reference with the file descriptor associated with stdin */ - in = CFSocketCreateWithNative(NULL, - STDIN_FILENO, - kCFSocketReadCallBack, - runLoopProcessInput, - &context); + /* allocate command input stream */ + src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0); + src->fp = stdin; + src->el = NULL; + src->h = NULL; + + if (isatty(fileno(src->fp))) { + int editmode = 1; + HistEvent ev; + struct termios t; + + if (tcgetattr(fileno(src->fp), &t) != -1) { + if ((t.c_lflag & ECHO) == 0) { + editmode = 0; + } + } + src->el = el_init(prog, src->fp, stdout, stderr); + src->h = history_init(); + + (void)history(src->h, &ev, H_SETSIZE, INT_MAX); + el_set(src->el, EL_HIST, history, src->h); - /* Create a run loop source for the (stdin) file descriptor */ - rls = CFSocketCreateRunLoopSource(NULL, in, nesting); + if (!editmode) { + el_set(src->el, EL_EDITMODE, 0); + } - /* keep track of input file sources */ - sources = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(sources, rls); + el_set(src->el, EL_EDITOR, "emacs"); + el_set(src->el, EL_PROMPT, prompt); - /* add this source to the run loop */ - CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); - CFRelease(rls); - CFRelease(in); + el_source(src->el, NULL); - /* show (initial) debug information, diagnostics */ - __showMachPortStatus(); + if ((el_get(src->el, EL_EDITMODE, &editmode) != -1) && editmode != 0) { + el_set(src->el, EL_SIGNAL, 1); + } else { + history_end(src->h); + src->h = NULL; + el_end(src->el); + src->el = NULL; + } + } - /* issue (initial) prompt */ - if (isatty(STDIN_FILENO)) { - printf("> "); - fflush(stdout); + while (process_line(src) == TRUE) { + /* debug information, diagnostics */ + __showMachPortStatus(); } - CFRunLoopRun(); /* process input, process events */ + /* close the socket, free resources */ + if (src->h) history_end(src->h); + if (src->el) el_end(src->el); + (void)fclose(src->fp); + CFAllocatorDeallocate(NULL, src); 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 c853556..98be196 100644 --- a/scutil.tproj/scutil.h +++ b/scutil.tproj/scutil.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -34,28 +37,32 @@ #define _SC_H #include +#include #include #include #include +typedef struct { + FILE *fp; + EditLine *el; + History *h; +} Input, *InputRef; + + extern int nesting; +extern CFRunLoopRef notifyRl; extern CFRunLoopSourceRef notifyRls; -extern CFMutableArrayRef sources; extern SCDynamicStoreRef store; extern CFPropertyListRef value; +extern CFMutableArrayRef watchedKeys; +extern CFMutableArrayRef watchedPatterns; __BEGIN_DECLS -Boolean process_line (FILE *fp); - -void runLoopProcessInput (CFSocketRef s, - CFSocketCallBackType type, - CFDataRef address, - const void *data, - void *info); +Boolean process_line (InputRef src); __END_DECLS diff --git a/scutil.tproj/session.c b/scutil.tproj/session.c index 82a6f43..246e917 100644 --- a/scutil.tproj/session.c +++ b/scutil.tproj/session.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -31,12 +34,17 @@ */ #include "scutil.h" +#include "session.h" #include "notify.h" void do_open(int argc, char **argv) { - if (store) CFRelease(store); + if (store) { + CFRelease(store); + CFRelease(watchedKeys); + CFRelease(watchedPatterns); + } store = SCDynamicStoreCreate(NULL, CFSTR("scutil"), storeCallback, NULL); if (!store) { @@ -44,6 +52,9 @@ do_open(int argc, char **argv) return; } + watchedKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + watchedPatterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + return; } @@ -57,9 +68,18 @@ do_close(int argc, char **argv) notifyRls = NULL; } + if (notifyRl) { + CFRunLoopStop(notifyRl); + notifyRl = NULL; + } + if (store) { CFRelease(store); store = NULL; + CFRelease(watchedKeys); + watchedKeys = NULL; + CFRelease(watchedPatterns); + watchedPatterns = NULL; } return; } diff --git a/scutil.tproj/session.h b/scutil.tproj/session.h index 211ddb7..ed80b8e 100644 --- a/scutil.tproj/session.h +++ b/scutil.tproj/session.h @@ -2,21 +2,24 @@ * 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/scutil.tproj/tests.c b/scutil.tproj/tests.c index e6d9ed0..3afd472 100644 --- a/scutil.tproj/tests.c +++ b/scutil.tproj/tests.c @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -36,40 +39,77 @@ */ #include "scutil.h" +#include "tests.h" -#include #include +#include #include #include void -do_checkReachability(char *node) +do_checkReachability(int argc, char **argv) { SCNetworkConnectionFlags flags = 0; - Boolean ok = FALSE; + SCNetworkReachabilityRef target = NULL; - if (isdigit(node[0])) { + if (argc == 1) { struct sockaddr_in sin; + struct sockaddr_in6 sin6; 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); + + bzero(&sin6, sizeof(sin6)); + sin6.sin6_len = sizeof(sin6); + sin6.sin6_family = AF_INET6; + + if (inet_aton(argv[0], &sin.sin_addr) == 1) { + target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin); + } else if (inet_pton(AF_INET6, argv[0], &sin6.sin6_addr) == 1) { + char *p; + + p = strchr(argv[0], '%'); + if (p != NULL) { + sin6.sin6_scope_id = if_nametoindex(p+1); + } + + target = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&sin6); + } else { + target = SCNetworkReachabilityCreateWithName(NULL, argv[0]); + } + } else /* if (argc == 2) */ { + struct sockaddr_in l_sin; + struct sockaddr_in r_sin; + + bzero(&l_sin, sizeof(l_sin)); + l_sin.sin_len = sizeof(l_sin); + l_sin.sin_family = AF_INET; + if (inet_aton(argv[0], &l_sin.sin_addr) == 0) { + SCPrint(TRUE, stderr, CFSTR("Could not interpret address \"%s\"\n"), argv[0]); exit(1); } - ok = SCNetworkCheckReachabilityByAddress((struct sockaddr *)&sin, - sizeof(sin), - &flags); - } else { - ok = SCNetworkCheckReachabilityByName(node, - &flags); + bzero(&r_sin, sizeof(r_sin)); + r_sin.sin_len = sizeof(r_sin); + r_sin.sin_family = AF_INET; + if (inet_aton(argv[1], &r_sin.sin_addr) == 0) { + SCPrint(TRUE, stderr, CFSTR("Could not interpret address \"%s\"\n"), argv[1]); + exit(1); + } + + target = SCNetworkReachabilityCreateWithAddressPair(NULL, + (struct sockaddr *)&l_sin, + (struct sockaddr *)&r_sin); + } + + if (!target) { + SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError())); + exit(1); } - if (!ok) { + if (!SCNetworkReachabilityGetFlags(target, &flags)) { SCPrint(TRUE, stderr, CFSTR(" Could not determine status: %s\n"), SCErrorString(SCError())); exit(1); } @@ -102,6 +142,16 @@ do_checkReachability(char *node) flags &= ~kSCNetworkFlagsInterventionRequired; SCPrint(flags != 0, stdout, CFSTR(",")); } + if (flags & kSCNetworkFlagsIsLocalAddress) { + SCPrint(TRUE, stdout, CFSTR("Local Address")); + flags &= ~kSCNetworkFlagsIsLocalAddress; + SCPrint(flags != 0, stdout, CFSTR(",")); + } + if (flags & kSCNetworkFlagsIsDirect) { + SCPrint(TRUE, stdout, CFSTR("Directly Reachable Address")); + flags &= ~kSCNetworkFlagsIsDirect; + SCPrint(flags != 0, stdout, CFSTR(",")); + } SCPrint(_sc_debug, stdout, CFSTR(")")); } else { SCPrint(_sc_debug, stdout, CFSTR(" (")); diff --git a/scutil.tproj/tests.h b/scutil.tproj/tests.h index 0d28080..867f2c8 100644 --- a/scutil.tproj/tests.h +++ b/scutil.tproj/tests.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 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 + * + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ */ @@ -39,7 +42,7 @@ __BEGIN_DECLS -void do_checkReachability (char *node); +void do_checkReachability (int argc, char **argv); void do_snapshot (int argc, char **argv); void do_wait (char *waitKey, int timeout); -- 2.47.2