#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "PMSettings.h" #include "SetActive.h" #include "powermanagementServer.h" #define kIOPMAppName "Power Management configd plugin" #define kIOPMPrefsPath "com.apple.PowerManagement.xml" #define kAssertionsArraySize 5 #define kIOPMTaskPortKey CFSTR("task") #define kIOPMAssertionsKey CFSTR("assertions") #define kIOPMNumAssertionTypes 2 #define kHighPerfIndex 0 #define kPreventIdleIndex 1 static int callerIsRoot(int uid, int gid); static int callerIsAdmin(int uid, int gid); static int callerIsConsole(int uid, int gid); extern CFMachPortRef serverMachPort; // external __private_extern__ void mig_server_callback(CFMachPortRef port, void *msg, CFIndex size, void *info); // forward __private_extern__ void cleanupAssertions(mach_port_t dead_port); static void evaluateAssertions(void); static void calculateAggregates(void); // globals static CFMutableDictionaryRef assertionsDict = NULL; static int aggregate_assertions[kIOPMNumAssertionTypes]; static CFStringRef assertion_types_arr[kIOPMNumAssertionTypes]; /*********************************** * Static Profiles ***********************************/ static void calculateAggregates(void) { CFDictionaryRef *process_assertions = NULL; int process_count = 0; int i, j; // Clear out the aggregate assertion values. We are about to re-calculate // these values in the big nasty loop below. for(i=0; ipw_name, pw->pw_gid, group_list, &ngroups); adminGroup = getgrnam("admin"); if (adminGroup != NULL) { gid_t adminGid = adminGroup->gr_gid; for(i=0; i= kAssertionsArraySize)) { *return_code = kIOReturnBadArgument; goto exit; } cf_port_for_task = CFMachPortCreateWithPort(0, task, mig_server_callback, 0, 0); if(!cf_port_for_task) { *return_code = kIOReturnNoMemory; goto exit; } calling_task = CFDictionaryGetValue(assertionsDict, cf_port_for_task); if(!calling_task) { *return_code = kIOReturnNotFound; goto exit; } // Retrieve assertions array for the calling task assertions = (CFMutableArrayRef)CFDictionaryGetValue(calling_task, kIOPMAssertionsKey); if(!assertions) { *return_code = kIOReturnInternalError; goto exit; } // Look up assertion at assertion_id and make sure it exists assertion_to_release = CFArrayGetValueAtIndex(assertions, assertion_id); if(!assertion_to_release || !isA_CFDictionary(assertion_to_release)) { *return_code = kIOReturnNotFound; goto exit; } // Release it CFArraySetValueAtIndex(assertions, assertion_id, kCFBooleanFalse); evaluateAssertions(); *return_code = kIOReturnSuccess; exit: if(cf_port_for_task) CFRelease(cf_port_for_task); return KERN_SUCCESS; } // Returns a CFDictionary of PM Assertions // * The keys of which are CFNumber (IntType) process ids (pids) // * The values are CFArrays of assertions created by that process // - Each entry in the array is a CFDictionary with: // - key = CFSTR("assert_type"); value = CFStringRef // - key = CFSTR("assert_value"); value = CFNumberRef kern_return_t _io_pm_copy_active_assertions ( mach_port_t server, vm_offset_t *profiles, mach_msg_type_number_t *profilesCnt ) { CFDataRef serialized_object = NULL; CFMachPortRef *task_id_arr = NULL; CFDictionaryRef *task_assertion_dict_arr = NULL; CFMutableDictionaryRef ret_dict = 0; int dict_count; int i; *profiles = 0; *profilesCnt = 0; if(!assertionsDict) goto exit; dict_count = CFDictionaryGetCount(assertionsDict); if(0 == dict_count) goto exit; ret_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // Iterate our master list of assertions and map them to pids task_id_arr = (CFMachPortRef *)malloc(sizeof(CFMachPortRef)*dict_count); task_assertion_dict_arr = (CFDictionaryRef *)malloc(sizeof(CFDictionaryRef)*dict_count); if(!task_id_arr || !task_assertion_dict_arr) goto exit; CFDictionaryGetKeysAndValues(assertionsDict, (const void **)task_id_arr, (const void **)task_assertion_dict_arr); for(i=0; i