**
* Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 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 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.
- *
- * 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.
- *
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
**/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/sysctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>
#define kRunSuccess CFSTR("success")
#define kRunFailure CFSTR("failure")
-typedef enum {
- kPriorityLast = 1,
- kPriorityLate = 2,
- kPriorityNone = 3,
- kPriorityEarly = 4,
- kPriorityFirst = 5,
- kPriorityNetwork = 10,
- kPriorityLocal = 20,
-} Priority;
-
-static Priority
-priorityFromString(CFStringRef aPriority)
-{
- if (aPriority) {
- if (CFEqual(aPriority, CFSTR("Last")))
- return kPriorityLast;
- else if (CFEqual(aPriority, CFSTR("Late")))
- return kPriorityLate;
- else if (CFEqual(aPriority, CFSTR("None")))
- return kPriorityNone;
- else if (CFEqual(aPriority, CFSTR("Early")))
- return kPriorityEarly;
- else if (CFEqual(aPriority, CFSTR("First")))
- return kPriorityFirst;
- }
- return kPriorityNone;
-}
-
-static const char *
-argumentForAction(Action anAction)
+static const char *argumentForAction(Action anAction)
{
switch (anAction) {
- case kActionStart:return "start";
+ case kActionStart:
+ return "start";
case kActionStop:
return "stop";
case kActionRestart:
return FALSE; \
}
-static int
-StartupItemValidate(CFDictionaryRef aConfig)
+static int StartupItemValidate(CFDictionaryRef aConfig)
{
if (aConfig && CFGetTypeID(aConfig) == CFDictionaryGetTypeID()) {
checkTypeOfValue(kProvidesKey, CFArrayGetTypeID());
/*
* remove item from waiting list
*/
-void
-RemoveItemFromWaitingList(StartupContext aStartupContext, CFMutableDictionaryRef anItem)
+void RemoveItemFromWaitingList(StartupContext aStartupContext, CFMutableDictionaryRef anItem)
{
/* Remove the item from the waiting list. */
if (aStartupContext && anItem && aStartupContext->aWaitingList) {
- CFRange aRange = {0, CFArrayGetCount(aStartupContext->aWaitingList)};
- CFIndex anIndex = CFArrayGetFirstIndexOfValue(aStartupContext->aWaitingList, aRange, anItem);
+ CFRange aRange = { 0, CFArrayGetCount(aStartupContext->aWaitingList) };
+ CFIndex anIndex = CFArrayGetFirstIndexOfValue(aStartupContext->aWaitingList, aRange, anItem);
if (anIndex >= 0) {
CFArrayRemoveValueAtIndex(aStartupContext->aWaitingList, anIndex);
* add item to failed list, create list if it doesn't exist
* return and fail quietly if it can't create list
*/
-void
-AddItemToFailedList(StartupContext aStartupContext, CFMutableDictionaryRef anItem)
+void AddItemToFailedList(StartupContext aStartupContext, CFMutableDictionaryRef anItem)
{
if (aStartupContext && anItem) {
/* create the failed list if it doesn't exist */
}
}
-
/**
- * startupItemListGetMatches returns an array of items which contain the string aService in the key aKey
+ * startupItemListCopyMatches returns an array of items which contain the string aService in the key aKey
**/
-static CFMutableArrayRef
-startupItemListGetMatches(CFArrayRef anItemList, CFStringRef aKey, CFStringRef aService)
+static CFMutableArrayRef startupItemListCopyMatches(CFArrayRef anItemList, CFStringRef aKey, CFStringRef aService)
{
CFMutableArrayRef aResult = NULL;
if (anItemList && aKey && aService) {
- CFIndex anItemCount = CFArrayGetCount(anItemList);
- CFIndex anItemIndex = 0;
+ CFIndex anItemCount = CFArrayGetCount(anItemList);
+ CFIndex anItemIndex = 0;
aResult = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
for (anItemIndex = 0; anItemIndex < anItemCount; ++anItemIndex) {
CFMutableDictionaryRef anItem = (CFMutableDictionaryRef) CFArrayGetValueAtIndex(anItemList, anItemIndex);
- CFArrayRef aList = CFDictionaryGetValue(anItem, aKey);
+ CFArrayRef aList = CFDictionaryGetValue(anItem, aKey);
if (aList) {
if (CFArrayContainsValue(aList, CFRangeMake(0, CFArrayGetCount(aList)), aService) &&
return aResult;
}
-static void
-SpecialCasesStartupItemHandler(CFMutableDictionaryRef aConfig)
+static void SpecialCasesStartupItemHandler(CFMutableDictionaryRef aConfig)
{
static const CFStringRef stubitems[] = {
CFSTR("Accounting"),
CFSTR("mDNSResponder"),
CFSTR("Cron"),
CFSTR("Core Graphics"),
+ CFSTR("Core Services"),
CFSTR("Network"),
+ CFSTR("TIM"),
+ CFSTR("Disks"),
+ CFSTR("NIS"),
NULL
};
CFMutableArrayRef aList, aNewList;
- CFIndex i, aCount;
+ CFIndex i, aCount;
CFStringRef ci, type = kRequiresKey;
const CFStringRef *c;
-again:
+ again:
aList = (CFMutableArrayRef) CFDictionaryGetValue(aConfig, type);
if (aList) {
aCount = CFArrayGetCount(aList);
}
CFDictionaryReplaceValue(aConfig, type, aNewList);
+ CFRelease(aNewList);
}
if (type == kUsesKey)
return;
goto again;
}
-CFIndex
-StartupItemListCountServices(CFArrayRef anItemList)
+CFIndex StartupItemListCountServices(CFArrayRef anItemList)
{
- CFIndex aResult = 0;
+ CFIndex aResult = 0;
if (anItemList) {
- CFIndex anItemCount = CFArrayGetCount(anItemList);
- CFIndex anItemIndex = 0;
+ CFIndex anItemCount = CFArrayGetCount(anItemList);
+ CFIndex anItemIndex = 0;
for (anItemIndex = 0; anItemIndex < anItemCount; ++anItemIndex) {
CFDictionaryRef anItem = CFArrayGetValueAtIndex(anItemList, anItemIndex);
- CFArrayRef aProvidesList = CFDictionaryGetValue(anItem, kProvidesKey);
+ CFArrayRef aProvidesList = CFDictionaryGetValue(anItem, kProvidesKey);
if (aProvidesList)
aResult += CFArrayGetCount(aProvidesList);
return aResult;
}
-static bool
-StartupItemSecurityCheck(const char *aPath)
+bool StartupItemSecurityCheck(const char *aPath)
{
+ static struct timeval boot_time;
struct stat aStatBuf;
bool r = true;
+ if (boot_time.tv_sec == 0) {
+ int mib[] = { CTL_KERN, KERN_BOOTTIME };
+ size_t boot_time_sz = sizeof(boot_time);
+ int rv;
+
+ rv = sysctl(mib, sizeof(mib) / sizeof(mib[0]), &boot_time, &boot_time_sz, NULL, 0);
+
+ assert(rv != -1);
+ assert(boot_time_sz == sizeof(boot_time));
+ }
+
/* should use lstatx_np() on Tiger? */
if (lstat(aPath, &aStatBuf) == -1) {
if (errno != ENOENT)
syslog(LOG_ERR, "lstat(\"%s\"): %m", aPath);
return false;
}
+ /*
+ * We check the boot time because of 5409386.
+ * We ignore the boot time if PPID != 1 because of 5503536.
+ */
+ if ((aStatBuf.st_ctimespec.tv_sec > boot_time.tv_sec) && (getppid() == 1)) {
+ syslog(LOG_WARNING, "\"%s\" failed sanity check: path was created after boot up", aPath);
+ return false;
+ }
if (!(S_ISREG(aStatBuf.st_mode) || S_ISDIR(aStatBuf.st_mode))) {
syslog(LOG_WARNING, "\"%s\" failed security check: not a directory or regular file", aPath);
r = false;
}
- if ((aStatBuf.st_mode & ALLPERMS) & ~(S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
- syslog(LOG_WARNING, "\"%s\" failed security check: permissions", aPath);
+ if (aStatBuf.st_mode & S_IWOTH) {
+ syslog(LOG_WARNING, "\"%s\" failed security check: world writable", aPath);
+ r = false;
+ }
+ if (aStatBuf.st_mode & S_IWGRP) {
+ syslog(LOG_WARNING, "\"%s\" failed security check: group writable", aPath);
r = false;
}
if (aStatBuf.st_uid != 0) {
}
if (r == false) {
mkdir(kFixerDir, ACCESSPERMS);
- close(open(kFixerPath, O_RDWR|O_CREAT, DEFFILEMODE));
+ close(open(kFixerPath, O_RDWR|O_CREAT|O_NOCTTY, DEFFILEMODE));
}
return r;
}
-CFMutableArrayRef
-StartupItemListCreateWithMask(NSSearchPathDomainMask aMask)
+CFMutableArrayRef StartupItemListCreateWithMask(NSSearchPathDomainMask aMask)
{
CFMutableArrayRef anItemList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- char aPath[PATH_MAX];
- CFIndex aDomainIndex = 0;
+ char aPath[PATH_MAX];
+ CFIndex aDomainIndex = 0;
NSSearchPathEnumerationState aState = NSStartSearchPathEnumeration(NSLibraryDirectory, aMask);
while ((aState = NSGetNextSearchPathEnumeration(aState, aPath))) {
- DIR *aDirectory;
+ DIR *aDirectory;
- strcpy(aPath + strlen(aPath), kStartupItemsPath);
+ strlcat(aPath, kStartupItemsPath, sizeof(aPath));
++aDomainIndex;
+ /* 5485016
+ *
+ * Just in case...
+ */
+ mkdir(aPath, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+
if (!StartupItemSecurityCheck(aPath))
continue;
if ((aDirectory = opendir(aPath))) {
- struct dirent *aBundle;
+ struct dirent *aBundle;
while ((aBundle = readdir(aDirectory))) {
struct stat aStatBuf;
syslog(LOG_DEBUG, "Found item: %s", aBundleName);
- sprintf(aBundlePath, "%s/%s", aPath, aBundleName);
+ sprintf(aBundlePath, "%s/%s", aPath, aBundleName);
sprintf(aBundleExecutablePath, "%s/%s", aBundlePath, aBundleName);
- sprintf(aConfigFile, "%s/%s", aBundlePath, kParametersFile);
- sprintf(aDisabledFile, "%s/%s", aBundlePath, kDisabledFile);
+ sprintf(aConfigFile, "%s/%s", aBundlePath, kParametersFile);
+ sprintf(aDisabledFile, "%s/%s", aBundlePath, kDisabledFile);
if (lstat(aDisabledFile, &aStatBuf) == 0) {
syslog(LOG_NOTICE, "Skipping disabled StartupItem: %s", aBundlePath);
/* Stow away the plist data for each bundle */
{
- int aConfigFileDescriptor;
+ int aConfigFileDescriptor;
- if ((aConfigFileDescriptor = open(aConfigFile, O_RDONLY, (mode_t) 0)) != -1) {
- struct stat aConfigFileStatBuffer;
+ if ((aConfigFileDescriptor = open(aConfigFile, O_RDONLY|O_NOCTTY, (mode_t) 0)) != -1) {
+ struct stat aConfigFileStatBuffer;
if (stat(aConfigFile, &aConfigFileStatBuffer) != -1) {
- off_t aConfigFileContentsSize = aConfigFileStatBuffer.st_size;
- char *aConfigFileContentsBuffer;
+ off_t aConfigFileContentsSize = aConfigFileStatBuffer.st_size;
+ char *aConfigFileContentsBuffer;
if ((aConfigFileContentsBuffer =
mmap((caddr_t) 0, aConfigFileContentsSize,
PROT_READ, MAP_FILE | MAP_PRIVATE,
aConfigFileDescriptor, (off_t) 0)) != (caddr_t) - 1) {
- CFDataRef aConfigData = NULL;
+ CFDataRef aConfigData = NULL;
CFMutableDictionaryRef aConfig = NULL;
aConfigData =
CFDataCreateWithBytesNoCopy(NULL,
- aConfigFileContentsBuffer,
+ (const UInt8 *)aConfigFileContentsBuffer,
aConfigFileContentsSize,
kCFAllocatorNull);
if (aConfigData) {
aConfig = (CFMutableDictionaryRef)
- CFPropertyListCreateFromXMLData(NULL, aConfigData,
- kCFPropertyListMutableContainers, NULL);
+ CFPropertyListCreateFromXMLData(NULL, aConfigData,
+ kCFPropertyListMutableContainers,
+ NULL);
}
if (StartupItemValidate(aConfig)) {
- CFStringRef aBundlePathString =
- CFStringCreateWithCString(NULL, aBundlePath, kCFStringEncodingUTF8);
+ CFStringRef aBundlePathString =
+ CFStringCreateWithCString(NULL, aBundlePath,
+ kCFStringEncodingUTF8);
- CFNumberRef aDomainNumber =
- CFNumberCreate(NULL, kCFNumberCFIndexType, &aDomainIndex);
+ CFNumberRef aDomainNumber =
+ CFNumberCreate(NULL, kCFNumberCFIndexType,
+ &aDomainIndex);
- CFDictionarySetValue(aConfig, kBundlePathKey, aBundlePathString);
+ CFDictionarySetValue(aConfig, kBundlePathKey,
+ aBundlePathString);
CFDictionarySetValue(aConfig, kDomainKey, aDomainNumber);
CFRelease(aDomainNumber);
SpecialCasesStartupItemHandler(aConfig);
CFRelease(aBundlePathString);
} else {
- syslog(LOG_ERR, "Malformatted parameters file: %s", aConfigFile);
+ syslog(LOG_ERR, "Malformatted parameters file: %s",
+ aConfigFile);
}
if (aConfig)
if (aConfigData)
CFRelease(aConfigData);
- if (munmap(aConfigFileContentsBuffer, aConfigFileContentsSize) == -1) {
- syslog(LOG_WARNING, "Unable to unmap parameters file %s for item %s: %m", aConfigFile, aBundleName);
+ if (munmap(aConfigFileContentsBuffer, aConfigFileContentsSize) ==
+ -1) {
+ syslog(LOG_WARNING,
+ "Unable to unmap parameters file %s for item %s: %m",
+ aConfigFile, aBundleName);
}
} else {
- syslog(LOG_ERR, "Unable to map parameters file %s for item %s: %m", aConfigFile, aBundleName);
+ syslog(LOG_ERR,
+ "Unable to map parameters file %s for item %s: %m",
+ aConfigFile, aBundleName);
}
} else {
- syslog(LOG_ERR, "Unable to stat parameters file %s for item %s: %m", aConfigFile, aBundleName);
+ syslog(LOG_ERR, "Unable to stat parameters file %s for item %s: %m",
+ aConfigFile, aBundleName);
}
if (close(aConfigFileDescriptor) == -1) {
- syslog(LOG_ERR, "Unable to close parameters file %s for item %s: %m", aConfigFile, aBundleName);
+ syslog(LOG_ERR, "Unable to close parameters file %s for item %s: %m",
+ aConfigFile, aBundleName);
}
} else {
- syslog(LOG_ERR, "Unable to open parameters file %s for item %s: %m", aConfigFile, aBundleName);
+ syslog(LOG_ERR, "Unable to open parameters file %s for item %s: %m", aConfigFile,
+ aBundleName);
}
}
}
return anItemList;
}
-CFMutableDictionaryRef
-StartupItemListGetProvider(CFArrayRef anItemList, CFStringRef aService)
+CFMutableDictionaryRef StartupItemListGetProvider(CFArrayRef anItemList, CFStringRef aService)
{
CFMutableDictionaryRef aResult = NULL;
- CFMutableArrayRef aList = startupItemListGetMatches(anItemList, kProvidesKey, aService);
+ CFMutableArrayRef aList = startupItemListCopyMatches(anItemList, kProvidesKey, aService);
if (aList && CFArrayGetCount(aList) > 0)
aResult = (CFMutableDictionaryRef) CFArrayGetValueAtIndex(aList, 0);
+ if (aList) CFRelease(aList);
+
return aResult;
}
-CFArrayRef
-StartupItemListGetRunning(CFArrayRef anItemList)
+CFArrayRef StartupItemListGetRunning(CFArrayRef anItemList)
{
CFMutableArrayRef aResult = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
if (aResult) {
- CFIndex anIndex, aCount = CFArrayGetCount(anItemList);
+ CFIndex anIndex, aCount = CFArrayGetCount(anItemList);
for (anIndex = 0; anIndex < aCount; ++anIndex) {
CFDictionaryRef anItem = CFArrayGetValueAtIndex(anItemList, anIndex);
if (anItem) {
- CFNumberRef aPID = CFDictionaryGetValue(anItem, kPIDKey);
+ CFNumberRef aPID = CFDictionaryGetValue(anItem, kPIDKey);
if (aPID)
CFArrayAppendValue(aResult, anItem);
}
* If anAction is kActionStop, dependent items are those which provide
* any service required by aParentItem.
*/
-static void
-appendDependents(CFMutableArrayRef aDependents,
- CFArrayRef anItemList, CFDictionaryRef aParentItem,
- Action anAction)
+static void appendDependents(CFMutableArrayRef aDependents, CFArrayRef anItemList, CFDictionaryRef aParentItem, Action anAction)
{
- CFStringRef anInnerKey, anOuterKey;
- CFArrayRef anOuterList;
+ CFStringRef anInnerKey, anOuterKey;
+ CFArrayRef anOuterList;
/* Append the parent item to the list (avoiding duplicates) */
if (!CFArrayContainsValue(aDependents, CFRangeMake(0, CFArrayGetCount(aDependents)), aParentItem))
anOuterList = CFDictionaryGetValue(aParentItem, anOuterKey);
if (anOuterList) {
- CFIndex anOuterCount = CFArrayGetCount(anOuterList);
- CFIndex anOuterIndex;
+ CFIndex anOuterCount = CFArrayGetCount(anOuterList);
+ CFIndex anOuterIndex;
for (anOuterIndex = 0; anOuterIndex < anOuterCount; anOuterIndex++) {
- CFStringRef anOuterElement = CFArrayGetValueAtIndex(anOuterList, anOuterIndex);
- CFIndex anItemCount = CFArrayGetCount(anItemList);
- CFIndex anItemIndex;
+ CFStringRef anOuterElement = CFArrayGetValueAtIndex(anOuterList, anOuterIndex);
+ CFIndex anItemCount = CFArrayGetCount(anItemList);
+ CFIndex anItemIndex;
for (anItemIndex = 0; anItemIndex < anItemCount; anItemIndex++) {
CFDictionaryRef anItem = CFArrayGetValueAtIndex(anItemList, anItemIndex);
- CFArrayRef anInnerList = CFDictionaryGetValue(anItem, anInnerKey);
+ CFArrayRef anInnerList = CFDictionaryGetValue(anItem, anInnerKey);
if (anInnerList &&
- CFArrayContainsValue(anInnerList, CFRangeMake(0, CFArrayGetCount(anInnerList)), anOuterElement) &&
- !CFArrayContainsValue(aDependents, CFRangeMake(0, CFArrayGetCount(aDependents)), anItem))
+ CFArrayContainsValue(anInnerList, CFRangeMake(0, CFArrayGetCount(anInnerList)),
+ anOuterElement)
+ && !CFArrayContainsValue(aDependents, CFRangeMake(0, CFArrayGetCount(aDependents)), anItem))
appendDependents(aDependents, anItemList, anItem, anAction);
}
}
}
}
-CFMutableArrayRef
-StartupItemListCreateDependentsList(CFMutableArrayRef anItemList, CFStringRef aService, Action anAction)
+CFMutableArrayRef StartupItemListCreateDependentsList(CFMutableArrayRef anItemList, CFStringRef aService, Action anAction)
{
CFMutableArrayRef aDependents = NULL;
CFMutableDictionaryRef anItem = NULL;
* countUnmetRequirements counts the number of items in anItemList
* which are pending in aStatusDict.
**/
-static int
-countUnmetRequirements(CFDictionaryRef aStatusDict, CFArrayRef anItemList)
+static int countUnmetRequirements(CFDictionaryRef aStatusDict, CFArrayRef anItemList)
{
- int aCount = 0;
- CFIndex anItemCount = CFArrayGetCount(anItemList);
- CFIndex anItemIndex;
+ int aCount = 0;
+ CFIndex anItemCount = CFArrayGetCount(anItemList);
+ CFIndex anItemIndex;
for (anItemIndex = 0; anItemIndex < anItemCount; anItemIndex++) {
- CFStringRef anItem = CFArrayGetValueAtIndex(anItemList, anItemIndex);
- CFStringRef aStatus = CFDictionaryGetValue(aStatusDict, anItem);
+ CFStringRef anItem = CFArrayGetValueAtIndex(anItemList, anItemIndex);
+ CFStringRef aStatus = CFDictionaryGetValue(aStatusDict, anItem);
if (!aStatus || !CFEqual(aStatus, kRunSuccess)) {
CF_syslog(LOG_DEBUG, CFSTR("\tFailed requirement/uses: %@"), anItem);
* countDependantsPresent counts the number of items in aWaitingList
* which depend on items in anItemList.
**/
-static int
-countDependantsPresent(CFArrayRef aWaitingList, CFArrayRef anItemList, CFStringRef aKey)
+static int countDependantsPresent(CFArrayRef aWaitingList, CFArrayRef anItemList, CFStringRef aKey)
{
- int aCount = 0;
- CFIndex anItemCount = CFArrayGetCount(anItemList);
- CFIndex anItemIndex;
+ int aCount = 0;
+ CFIndex anItemCount = CFArrayGetCount(anItemList);
+ CFIndex anItemIndex;
for (anItemIndex = 0; anItemIndex < anItemCount; anItemIndex++) {
- CFStringRef anItem = CFArrayGetValueAtIndex(anItemList, anItemIndex);
- CFArrayRef aMatchesList = startupItemListGetMatches(aWaitingList, aKey, anItem);
+ CFStringRef anItem = CFArrayGetValueAtIndex(anItemList, anItemIndex);
+ CFArrayRef aMatchesList = startupItemListCopyMatches(aWaitingList, aKey, anItem);
if (aMatchesList) {
aCount = aCount + CFArrayGetCount(aMatchesList);
* pendingAntecedents returns TRUE if any antecedents of this item
* are currently running, have not yet run, or none exist.
**/
-static Boolean
+static Boolean
pendingAntecedents(CFArrayRef aWaitingList, CFDictionaryRef aStatusDict, CFArrayRef anAntecedentList, Action anAction)
{
- int aPendingFlag = FALSE;
+ int aPendingFlag = FALSE;
- CFIndex anAntecedentCount = CFArrayGetCount(anAntecedentList);
- CFIndex anAntecedentIndex;
+ CFIndex anAntecedentCount = CFArrayGetCount(anAntecedentList);
+ CFIndex anAntecedentIndex;
for (anAntecedentIndex = 0; anAntecedentIndex < anAntecedentCount; ++anAntecedentIndex) {
- CFStringRef anAntecedent = CFArrayGetValueAtIndex(anAntecedentList, anAntecedentIndex);
- CFStringRef aKey = (anAction == kActionStart) ? kProvidesKey : kUsesKey;
- CFArrayRef aMatchesList = startupItemListGetMatches(aWaitingList, aKey, anAntecedent);
+ CFStringRef anAntecedent = CFArrayGetValueAtIndex(anAntecedentList, anAntecedentIndex);
+ CFStringRef aKey = (anAction == kActionStart) ? kProvidesKey : kUsesKey;
+ CFArrayRef aMatchesList = startupItemListCopyMatches(aWaitingList, aKey, anAntecedent);
if (aMatchesList) {
- CFIndex aMatchesListCount = CFArrayGetCount(aMatchesList);
- CFIndex aMatchesListIndex;
+ CFIndex aMatchesListCount = CFArrayGetCount(aMatchesList);
+ CFIndex aMatchesListIndex;
for (aMatchesListIndex = 0; aMatchesListIndex < aMatchesListCount; ++aMatchesListIndex) {
CFDictionaryRef anItem = CFArrayGetValueAtIndex(aMatchesList, aMatchesListIndex);
if (!anItem ||
- !CFDictionaryGetValue(anItem, kPIDKey) ||
- !CFDictionaryGetValue(aStatusDict, anAntecedent)) {
+ !CFDictionaryGetValue(anItem, kPIDKey) || !CFDictionaryGetValue(aStatusDict, anAntecedent)) {
aPendingFlag = TRUE;
break;
}
* checkForDuplicates returns TRUE if an item provides the same service as a
* pending item, or an item that already succeeded.
**/
-static Boolean
-checkForDuplicates(CFArrayRef aWaitingList, CFDictionaryRef aStatusDict, CFDictionaryRef anItem)
+static Boolean checkForDuplicates(CFArrayRef aWaitingList, CFDictionaryRef aStatusDict, CFDictionaryRef anItem)
{
- int aDuplicateFlag = FALSE;
+ int aDuplicateFlag = FALSE;
- CFArrayRef aProvidesList = CFDictionaryGetValue(anItem, kProvidesKey);
- CFIndex aProvidesCount = aProvidesList ? CFArrayGetCount(aProvidesList) : 0;
- CFIndex aProvidesIndex;
+ CFArrayRef aProvidesList = CFDictionaryGetValue(anItem, kProvidesKey);
+ CFIndex aProvidesCount = aProvidesList ? CFArrayGetCount(aProvidesList) : 0;
+ CFIndex aProvidesIndex;
for (aProvidesIndex = 0; aProvidesIndex < aProvidesCount; ++aProvidesIndex) {
- CFStringRef aProvides = CFArrayGetValueAtIndex(aProvidesList, aProvidesIndex);
+ CFStringRef aProvides = CFArrayGetValueAtIndex(aProvidesList, aProvidesIndex);
/* If the service succeeded, return true. */
- CFStringRef aStatus = CFDictionaryGetValue(aStatusDict, aProvides);
+ CFStringRef aStatus = CFDictionaryGetValue(aStatusDict, aProvides);
if (aStatus && CFEqual(aStatus, kRunSuccess)) {
aDuplicateFlag = TRUE;
break;
* might provide that service.
*/
else {
- CFArrayRef aMatchesList = startupItemListGetMatches(aWaitingList, kProvidesKey, aProvides);
+ CFArrayRef aMatchesList = startupItemListCopyMatches(aWaitingList, kProvidesKey, aProvides);
if (aMatchesList) {
- CFIndex aMatchesListCount = CFArrayGetCount(aMatchesList);
- CFIndex aMatchesListIndex;
+ CFIndex aMatchesListCount = CFArrayGetCount(aMatchesList);
+ CFIndex aMatchesListIndex;
for (aMatchesListIndex = 0; aMatchesListIndex < aMatchesListCount; ++aMatchesListIndex) {
CFDictionaryRef anDupItem = CFArrayGetValueAtIndex(aMatchesList, aMatchesListIndex);
aDuplicateFlag = TRUE;
break;
} else {
- CFNumberRef anItemDomain = CFDictionaryGetValue(anItem, kDomainKey);
- CFNumberRef anotherItemDomain = CFDictionaryGetValue(anDupItem, kDomainKey);
+ CFNumberRef anItemDomain = CFDictionaryGetValue(anItem, kDomainKey);
+ CFNumberRef anotherItemDomain = CFDictionaryGetValue(anDupItem, kDomainKey);
/*
* If anItem was found later
* than aDupItem, stall
*/
if (anItemDomain &&
anotherItemDomain &&
- CFNumberCompare(anItemDomain, anotherItemDomain, NULL) == kCFCompareGreaterThan) {
+ CFNumberCompare(anItemDomain, anotherItemDomain,
+ NULL) == kCFCompareGreaterThan) {
/*
* Item not running,
* but takes
return (aDuplicateFlag);
}
-CFMutableDictionaryRef
-StartupItemListGetNext(CFArrayRef aWaitingList, CFDictionaryRef aStatusDict, Action anAction)
+CFMutableDictionaryRef StartupItemListGetNext(CFArrayRef aWaitingList, CFDictionaryRef aStatusDict, Action anAction)
{
CFMutableDictionaryRef aNextItem = NULL;
- CFIndex aWaitingCount = CFArrayGetCount(aWaitingList);
+ CFIndex aWaitingCount = CFArrayGetCount(aWaitingList);
+ int aMinFailedAntecedents = INT_MAX;
+ CFIndex aWaitingIndex;
switch (anAction) {
case kActionStart:
return NULL;
}
- if (aWaitingList && aStatusDict && aWaitingCount > 0) {
- Priority aMaxPriority = kPriorityLast;
- int aMinFailedAntecedents = INT_MAX;
- CFIndex aWaitingIndex;
-
- /**
- * Iterate through the items in aWaitingList and look for an optimally ready item.
- **/
- for (aWaitingIndex = 0; aWaitingIndex < aWaitingCount; aWaitingIndex++) {
- CFMutableDictionaryRef anItem = (CFMutableDictionaryRef) CFArrayGetValueAtIndex(aWaitingList, aWaitingIndex);
- CFArrayRef anAntecedentList;
+ if (!aWaitingList || !aStatusDict || aWaitingCount <= 0)
+ return NULL;
- /* Filter out running items. */
- if (CFDictionaryGetValue(anItem, kPIDKey))
- goto next_item;
+ /**
+ * Iterate through the items in aWaitingList and look for an optimally ready item.
+ **/
+ for (aWaitingIndex = 0; aWaitingIndex < aWaitingCount; aWaitingIndex++) {
+ CFMutableDictionaryRef anItem = (CFMutableDictionaryRef) CFArrayGetValueAtIndex(aWaitingList, aWaitingIndex);
+ CFArrayRef anAntecedentList;
+ int aFailedAntecedentsCount = 0; /* Number of unmet soft
+ * depenancies */
+ Boolean aBestPick = FALSE; /* Is this the best pick
+ * so far? */
+
+ /* Filter out running items. */
+ if (CFDictionaryGetValue(anItem, kPIDKey))
+ continue;
- /*
- * Filter out dupilicate services; if someone has
- * provided what we provide, we don't run.
- */
- if (checkForDuplicates(aWaitingList, aStatusDict, anItem)) {
- CF_syslog(LOG_DEBUG, CFSTR("Skipping %@ because of duplicate service."), CFDictionaryGetValue(anItem, kDescriptionKey));
- goto next_item;
- }
- /*
- * Dependencies don't matter when restarting an item;
- * stop here.
- */
- if (anAction == kActionRestart) {
- aNextItem = anItem;
- break;
- }
- anAntecedentList = CFDictionaryGetValue(anItem, ((anAction == kActionStart) ? kRequiresKey : kProvidesKey));
+ /*
+ * Filter out dupilicate services; if someone has
+ * provided what we provide, we don't run.
+ */
+ if (checkForDuplicates(aWaitingList, aStatusDict, anItem)) {
+ CF_syslog(LOG_DEBUG, CFSTR("Skipping %@ because of duplicate service."),
+ CFDictionaryGetValue(anItem, kDescriptionKey));
+ continue;
+ }
+ /*
+ * Dependencies don't matter when restarting an item;
+ * stop here.
+ */
+ if (anAction == kActionRestart) {
+ aNextItem = anItem;
+ break;
+ }
+ anAntecedentList = CFDictionaryGetValue(anItem, ((anAction == kActionStart) ? kRequiresKey : kProvidesKey));
- CF_syslog(LOG_DEBUG, CFSTR("Checking %@"), CFDictionaryGetValue(anItem, kDescriptionKey));
+ CF_syslog(LOG_DEBUG, CFSTR("Checking %@"), CFDictionaryGetValue(anItem, kDescriptionKey));
- if (anAntecedentList)
- CF_syslog(LOG_DEBUG, CFSTR("Antecedents: %@"), anAntecedentList);
- else
- syslog(LOG_DEBUG, "No antecedents");
+ if (anAntecedentList)
+ CF_syslog(LOG_DEBUG, CFSTR("Antecedents: %@"), anAntecedentList);
+ else
+ syslog(LOG_DEBUG, "No antecedents");
/**
* Filter out the items which have unsatisfied antecedents.
**/
- if (anAntecedentList &&
- ((anAction == kActionStart) ?
- countUnmetRequirements(aStatusDict, anAntecedentList) :
- countDependantsPresent(aWaitingList, anAntecedentList, kRequiresKey)))
- goto next_item;
+ if (anAntecedentList &&
+ ((anAction == kActionStart) ?
+ countUnmetRequirements(aStatusDict, anAntecedentList) :
+ countDependantsPresent(aWaitingList, anAntecedentList, kRequiresKey)))
+ continue;
/**
* anItem has all hard dependancies met; check for soft dependancies.
* We'll favor the item with the fewest unmet soft dependancies here.
**/
- {
- int aFailedAntecedentsCount = 0; /* Number of unmet soft
- * depenancies */
- Boolean aBestPick = FALSE; /* Is this the best pick
- * so far? */
+ anAntecedentList = CFDictionaryGetValue(anItem, ((anAction == kActionStart) ? kUsesKey : kProvidesKey));
- anAntecedentList = CFDictionaryGetValue(anItem, ((anAction == kActionStart) ?
- kUsesKey : kProvidesKey));
+ if (anAntecedentList)
+ CF_syslog(LOG_DEBUG, CFSTR("Soft dependancies: %@"), anAntecedentList);
+ else
+ syslog(LOG_DEBUG, "No soft dependancies");
- if (anAntecedentList)
- CF_syslog(LOG_DEBUG, CFSTR("Soft dependancies: %@"), anAntecedentList);
- else
- syslog(LOG_DEBUG, "No soft dependancies");
-
- if (anAntecedentList) {
- aFailedAntecedentsCount =
- ((anAction == kActionStart) ?
- countUnmetRequirements(aStatusDict, anAntecedentList) :
- countDependantsPresent(aWaitingList, anAntecedentList, kUsesKey));
- } else {
- if (aMinFailedAntecedents > 0)
- aBestPick = TRUE;
- }
+ if (anAntecedentList) {
+ aFailedAntecedentsCount =
+ ((anAction == kActionStart) ?
+ countUnmetRequirements(aStatusDict, anAntecedentList) :
+ countDependantsPresent(aWaitingList, anAntecedentList, kUsesKey));
+ } else {
+ if (aMinFailedAntecedents > 0)
+ aBestPick = TRUE;
+ }
- /*
- * anItem has unmet dependencies that will
- * likely be met in the future, so delay it
- */
- if (aFailedAntecedentsCount > 0 &&
- pendingAntecedents(aWaitingList, aStatusDict, anAntecedentList, anAction)) {
- goto next_item;
- }
- if (aFailedAntecedentsCount > 0)
- syslog(LOG_DEBUG, "Total: %d", aFailedAntecedentsCount);
+ /*
+ * anItem has unmet dependencies that will
+ * likely be met in the future, so delay it
+ */
+ if (aFailedAntecedentsCount > 0 && pendingAntecedents(aWaitingList, aStatusDict, anAntecedentList, anAction)) {
+ continue;
+ }
+ if (aFailedAntecedentsCount > 0)
+ syslog(LOG_DEBUG, "Total: %d", aFailedAntecedentsCount);
- if (aFailedAntecedentsCount > aMinFailedAntecedents)
- goto next_item; /* Another item already
- * won out */
- if (aFailedAntecedentsCount < aMinFailedAntecedents)
- aBestPick = TRUE;
+ if (aFailedAntecedentsCount > aMinFailedAntecedents)
+ continue; /* Another item already won out */
- {
- Priority aPriority = priorityFromString(CFDictionaryGetValue(anItem, kPriorityKey));
+ if (aFailedAntecedentsCount < aMinFailedAntecedents)
+ aBestPick = TRUE;
- if (aBestPick) {
- /*
- * anItem has less unmet
- * dependancies than any
- * other item so far, so it
- * wins.
- */
- syslog(LOG_DEBUG, "Best pick so far, based on failed dependancies (%d->%d)",
- aMinFailedAntecedents, aFailedAntecedentsCount);
- } else if ((anAction == kActionStart) ?
- (aPriority >= aMaxPriority) :
- (aPriority <= aMaxPriority)) {
- /*
- * anItem has a best
- * priority, so it wins.
- */
- syslog(LOG_DEBUG, "Best pick so far, based on Priority (%d->%d)",
- aMaxPriority, aPriority);
- } else
- goto next_item; /* No soup for you! */
-
- /*
- * We have a winner! Update success
- * parameters to match anItem.
- */
- aMinFailedAntecedents = aFailedAntecedentsCount;
- aMaxPriority = aPriority;
- aNextItem = anItem;
- }
+ if (!aBestPick)
+ continue;
- } /* End of uses section. */
+ /*
+ * anItem has less unmet
+ * dependancies than any
+ * other item so far, so it
+ * wins.
+ */
+ syslog(LOG_DEBUG, "Best pick so far, based on failed dependancies (%d->%d)",
+ aMinFailedAntecedents, aFailedAntecedentsCount);
- next_item:
- continue;
+ /*
+ * We have a winner! Update success
+ * parameters to match anItem.
+ */
+ aMinFailedAntecedents = aFailedAntecedentsCount;
+ aNextItem = anItem;
- } /* End of waiting list loop. */
+ } /* End of waiting list loop. */
- } /* if (aWaitingList && aWaitingCount > 0) */
return aNextItem;
}
-CFStringRef
-StartupItemGetDescription(CFMutableDictionaryRef anItem)
+CFStringRef StartupItemGetDescription(CFMutableDictionaryRef anItem)
{
- CFStringRef aString = NULL;
+ CFStringRef aString = NULL;
if (anItem)
aString = CFDictionaryGetValue(anItem, kDescriptionKey);
return aString;
}
-pid_t
-StartupItemGetPID(CFDictionaryRef anItem)
+pid_t StartupItemGetPID(CFDictionaryRef anItem)
{
- CFIndex anItemPID = 0;
- CFNumberRef aPIDNumber = anItem ? CFDictionaryGetValue(anItem, kPIDKey) : NULL;
+ CFIndex anItemPID = 0;
+ CFNumberRef aPIDNumber = anItem ? CFDictionaryGetValue(anItem, kPIDKey) : NULL;
if (aPIDNumber && CFNumberGetValue(aPIDNumber, kCFNumberCFIndexType, &anItemPID))
return (pid_t) anItemPID;
else
return 0;
}
-CFMutableDictionaryRef
-StartupItemWithPID(CFArrayRef anItemList, pid_t aPID)
+CFMutableDictionaryRef StartupItemWithPID(CFArrayRef anItemList, pid_t aPID)
{
- CFIndex anItemCount = CFArrayGetCount(anItemList);
- CFIndex anItemIndex;
+ CFIndex anItemCount = CFArrayGetCount(anItemList);
+ CFIndex anItemIndex;
for (anItemIndex = 0; anItemIndex < anItemCount; anItemIndex++) {
CFMutableDictionaryRef anItem = (CFMutableDictionaryRef) CFArrayGetValueAtIndex(anItemList, anItemIndex);
- CFNumberRef aPIDNumber = CFDictionaryGetValue(anItem, kPIDKey);
- CFIndex anItemPID;
+ CFNumberRef aPIDNumber = CFDictionaryGetValue(anItem, kPIDKey);
+ CFIndex anItemPID;
if (aPIDNumber) {
CFNumberGetValue(aPIDNumber, kCFNumberCFIndexType, &anItemPID);
return NULL;
}
-int
-StartupItemRun(CFMutableDictionaryRef aStatusDict, CFMutableDictionaryRef anItem, Action anAction)
+int StartupItemRun(CFMutableDictionaryRef aStatusDict, CFMutableDictionaryRef anItem, Action anAction)
{
int anError = -1;
CFArrayRef aProvidesList = CFDictionaryGetValue(anItem, kProvidesKey);
StartupItemExit(aStatusDict, anItem, TRUE);
anError = 0;
} else {
- CFStringRef aBundlePathString = CFDictionaryGetValue(anItem, kBundlePathKey);
- size_t aBundlePathCLength =
- CFStringGetMaximumSizeForEncoding(CFStringGetLength(aBundlePathString), kCFStringEncodingUTF8) + 1;
- char *aBundlePath = (char *) malloc(aBundlePathCLength);
- char anExecutable[PATH_MAX] = "";
-
- if (!aBundlePath) {
- syslog(LOG_EMERG, "malloc() failed; out of memory while running item %s", aBundlePathString);
- return (anError);
- }
- if (!CFStringGetCString(aBundlePathString, aBundlePath, aBundlePathCLength, kCFStringEncodingUTF8)) {
+ CFStringRef aBundlePathString = CFDictionaryGetValue(anItem, kBundlePathKey);
+ char aBundlePath[PATH_MAX];
+ char anExecutable[PATH_MAX];
+ char *tmp;
+
+ if (!CFStringGetCString(aBundlePathString, aBundlePath, sizeof(aBundlePath), kCFStringEncodingUTF8)) {
CF_syslog(LOG_EMERG, CFSTR("Internal error while running item %@"), aBundlePathString);
return (anError);
}
/* Compute path to excecutable */
- {
- char *tmp;
- strcpy(anExecutable, aBundlePath); /* .../foo */
- tmp = rindex(anExecutable, '/'); /* /foo */
- strncat(anExecutable, tmp, strlen(tmp)); /* .../foo/foo */
- }
-
- free(aBundlePath);
+ tmp = rindex(aBundlePath, '/');
+ snprintf(anExecutable, sizeof(anExecutable), "%s%s", aBundlePath, tmp);
/**
* Run the bundle
* Add PID key so that this item is marked as having
* been run.
*/
- CFIndex aPID = -1;
- CFNumberRef aProcessNumber = CFNumberCreate(NULL, kCFNumberCFIndexType, &aPID);
+ CFIndex aPID = -1;
+ CFNumberRef aProcessNumber = CFNumberCreate(NULL, kCFNumberCFIndexType, &aPID);
CFDictionarySetValue(anItem, kPIDKey, aProcessNumber);
CFRelease(aProcessNumber);
StartupItemExit(aStatusDict, anItem, FALSE);
syslog(LOG_ERR, "No executable file %s", anExecutable);
} else {
- pid_t aProccessID = fork();
+ pid_t aProccessID = fork();
switch (aProccessID) {
case -1: /* SystemStarter (fork failed) */
CFDictionarySetValue(anItem, kErrorKey, kErrorFork);
StartupItemExit(aStatusDict, anItem, FALSE);
- CF_syslog(LOG_ERR, CFSTR("Failed to fork for item %@: %s"),
- aBundlePathString, strerror(errno));
+ CF_syslog(LOG_ERR, CFSTR("Failed to fork for item %@: %s"), aBundlePathString, strerror(errno));
break;
default: /* SystemStarter (fork succeeded) */
{
- CFIndex aPID = (CFIndex) aProccessID;
- CFNumberRef aProcessNumber = CFNumberCreate(NULL, kCFNumberCFIndexType, &aPID);
+ CFIndex aPID = (CFIndex) aProccessID;
+ CFNumberRef aProcessNumber = CFNumberCreate(NULL, kCFNumberCFIndexType, &aPID);
CFDictionarySetValue(anItem, kPIDKey, aProcessNumber);
CFRelease(aProcessNumber);
}
break;
- case 0:/* Child */
+ case 0: /* Child */
{
- setpriority(PRIO_PROCESS, 0, 0);
if (setsid() == -1)
syslog(LOG_WARNING, "Unable to create session for item %s: %m", anExecutable);
return (anError);
}
-void
-StartupItemSetStatus(CFMutableDictionaryRef aStatusDict, CFMutableDictionaryRef anItem, CFStringRef aServiceName, Boolean aSuccess, Boolean aReplaceFlag)
+void
+StartupItemSetStatus(CFMutableDictionaryRef aStatusDict, CFMutableDictionaryRef anItem, CFStringRef aServiceName,
+ Boolean aSuccess, Boolean aReplaceFlag)
{
- void (*anAction) (CFMutableDictionaryRef, const void *, const void *) = aReplaceFlag ?
- CFDictionarySetValue : CFDictionaryAddValue;
+ void (*anAction) (CFMutableDictionaryRef, const void *, const void *) = aReplaceFlag ?
+ CFDictionarySetValue : CFDictionaryAddValue;
if (aStatusDict && anItem) {
- CFArrayRef aProvidesList = CFDictionaryGetValue(anItem, kProvidesKey);
+ CFArrayRef aProvidesList = CFDictionaryGetValue(anItem, kProvidesKey);
if (aProvidesList) {
- CFIndex aProvidesCount = CFArrayGetCount(aProvidesList);
- CFIndex aProvidesIndex;
+ CFIndex aProvidesCount = CFArrayGetCount(aProvidesList);
+ CFIndex aProvidesIndex;
/*
* If a service name was specified, and it is valid,
* use only it.
*/
if (aServiceName && CFArrayContainsValue(aProvidesList, CFRangeMake(0, aProvidesCount), aServiceName)) {
- aProvidesList = CFArrayCreate(NULL, (const void **) &aServiceName, 1, &kCFTypeArrayCallBacks);
+ aProvidesList = CFArrayCreate(NULL, (const void **)&aServiceName, 1, &kCFTypeArrayCallBacks);
aProvidesCount = 1;
} else {
CFRetain(aProvidesList);
}
for (aProvidesIndex = 0; aProvidesIndex < aProvidesCount; aProvidesIndex++) {
- CFStringRef aService = CFArrayGetValueAtIndex(aProvidesList, aProvidesIndex);
+ CFStringRef aService = CFArrayGetValueAtIndex(aProvidesList, aProvidesIndex);
if (aSuccess)
anAction(aStatusDict, aService, kRunSuccess);
}
}
-void
-StartupItemExit(CFMutableDictionaryRef aStatusDict, CFMutableDictionaryRef anItem, Boolean aSuccess)
+void StartupItemExit(CFMutableDictionaryRef aStatusDict, CFMutableDictionaryRef anItem, Boolean aSuccess)
{
StartupItemSetStatus(aStatusDict, anItem, NULL, aSuccess, FALSE);
}