#include <unistd.h> #include <stdbool.h> #include <CoreFoundation/CoreFoundation.h> static void CFQRelease(CFTypeRef cf) // A version of CFRelease that's tolerant of NULL. { if (cf != NULL) { CFRelease(cf); } } static int GetPathToSelf(char **pathToSelfPtr) // A drop-in replacement for GetPathToSelf() from MoreAuthSample's MoreSecurity.c, // implemented using CoreFoundation. From CocoaDev.com { int err = 0; assert( pathToSelfPtr != NULL); assert(*pathToSelfPtr == NULL); CFBundleRef mainBundle = CFBundleGetMainBundle(); CFURLRef executableURL = NULL; CFStringRef pathStringRef = NULL; char *path = NULL; if (mainBundle != NULL) { executableURL = CFBundleCopyExecutableURL(mainBundle); if (executableURL != NULL) { pathStringRef = CFURLCopyFileSystemPath(executableURL, kCFURLPOSIXPathStyle); if (pathStringRef != NULL) { CFIndex pathSize = CFStringGetLength(pathStringRef) + 1; path = (char *)calloc(pathSize,1); if (path != NULL) { Boolean gotCString = CFStringGetCString(pathStringRef, path, pathSize, kCFStringEncodingUTF8); if (!gotCString) { free(path); path = NULL; } } } } } *pathToSelfPtr = path; // Do the CF memory management. CFQRelease(executableURL); CFQRelease(pathStringRef); assert(*pathToSelfPtr != NULL); if (*pathToSelfPtr == NULL) { err = -1; } return err; } static bool openfireIsRunning() { FILE *ps; char buff[1024]; if((ps=popen("/bin/ps auxww | fgrep -v 'fgrep' | fgrep openfire/lib/startup.jar", "r")) == NULL) { return false; } else { bool running = false; if(fgets(buff, 1024, ps)) { running = true; } pclose(ps); return running; } } static void toggleStartOpenfireAtBoot() { CFURLRef propFile = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/Library/LaunchDaemons/org.jivesoftware.openfire.plist"), kCFURLPOSIXPathStyle, false); CFDataRef xmlData; CFURLCreateDataAndPropertiesFromResource (kCFAllocatorDefault, propFile, &xmlData, NULL, NULL, NULL); CFPropertyListRef props = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, xmlData, kCFPropertyListMutableContainersAndLeaves, NULL); if(CFGetTypeID(props) == CFDictionaryGetTypeID()) { CFMutableDictionaryRef propsDict = (CFMutableDictionaryRef)props; CFBooleanRef currentValue = CFDictionaryGetValue(propsDict,CFSTR("RunAtLoad")); CFDictionaryReplaceValue(propsDict, CFSTR("RunAtLoad"), ((currentValue == kCFBooleanTrue) ? kCFBooleanFalse : kCFBooleanTrue)); CFQRelease(xmlData); xmlData = CFPropertyListCreateXMLData(kCFAllocatorDefault,(CFPropertyListRef)propsDict); CFURLWriteDataAndPropertiesToResource(propFile,xmlData,NULL,NULL); } CFQRelease(props); CFQRelease(xmlData); CFQRelease(propFile); } static void toggleOpenfire() { char *args[4]; args[0] = "launchctl"; if(openfireIsRunning()) args[1] = "unload"; else args[1] = "load"; args[2] = "/Library/LaunchDaemons/org.jivesoftware.openfire.plist"; args[3] = NULL; execv("/bin/launchctl", args); } int main(int inArgsCount, char * const inArgs[]) { char* selfPath = NULL; int err = GetPathToSelf(&selfPath); const char* correctPath = "/Library/PreferencePanes/Openfire.prefPane/Contents/MacOS/HelperTool"; if(err == 0 && strncmp(correctPath, selfPath, strlen(correctPath)) == 0) { //if setuid somehow fails, it's unsafe to continue if(setuid(0) != 0) return; if(inArgs[1] && strlen(inArgs[1]) == strlen("boot") && strncmp("boot", inArgs[1], strlen("boot")) == 0) { toggleStartOpenfireAtBoot(); } else { toggleOpenfire(); } } return 1; }