1/*
2 * Copyright (c) 2010 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <CoreFoundation/CoreFoundation.h>
25#include <CoreFoundation/CFDateFormatter.h>
26
27#include <SystemConfiguration/SystemConfiguration.h>
28#include <SystemConfiguration/SCValidation.h>
29
30#include <IOKit/IOMessage.h>
31#include <IOKit/pwr_mgt/IOPM.h>
32#include <IOKit/pwr_mgt/IOPMLib.h>
33#include <IOKit/pwr_mgt/IOPMPrivate.h>
34#include <IOKit/pwr_mgt/IOPMLibPrivate.h>
35#include <IOKit/pwr_mgt/IOPMUPSPrivate.h>
36#include <IOKit/ps/IOPSKeys.h>
37#include <IOKit/ps/IOPowerSources.h>
38#include <IOKit/ps/IOPowerSourcesPrivate.h>
39#include <IOKit/IOCFSerialize.h>
40
41#if TARGET_OS_EMBEDDED
42    #define PLATFORM_HAS_DISPLAYSERVICES    0
43#else
44    #define PLATFORM_HAS_DISPLAYSERVICES    1
45    // ResentAmbientLightAll is defined in <DisplayServices/DisplayServices.h>
46    // and implemented by DisplayServices.framework
47    IOReturn DisplayServicesResetAmbientLightAll( void );
48#endif
49
50#include "../pmconfigd/PrivateLib.h"
51
52// dynamically mig generated
53#include "powermanagement.h"
54
55#include <IOKit/IOHibernatePrivate.h>
56#include <IOKit/IOReportTypes.h>
57#include <IOReport.h>
58
59#include <servers/bootstrap.h>
60#include <bootstrap_priv.h>
61#include <mach/mach_port.h>
62#include <string.h>
63#include <ctype.h>
64#include <unistd.h>
65#include <notify.h>
66#include <asl.h>
67#include <dirent.h>
68#include <sysexits.h>
69#include <libproc.h>
70
71/*
72 * This is the command line interface to Energy Saver Preferences in
73 * /Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist
74 *
75 * pmset does many things, but here are a few of them:
76 *
77 Usage: pmset [-b | -c | -a] <action> <minutes> [[<opts>] <action> <minutes> ...]
78       -c adjust settings used while connected to a charger
79       -b adjust settings used when running off a battery
80       -a (default) adjust settings for both
81       <action> is one of: dim, sleep, spindown, slower, womp* (* flag = 1/0)
82       eg. pmset womp 1 -c dim 5 sleep 15 -b dim 3 spindown 5 sleep 8
83 */
84
85// Settings options
86#define ARG_DIM             "dim"
87#define ARG_DISPLAYSLEEP    "displaysleep"
88#define ARG_SLEEP           "sleep"
89#define ARG_SPINDOWN        "spindown"
90#define ARG_DISKSLEEP       "disksleep"
91#define ARG_WOMP            "womp"
92#define ARG_LIDWAKE         "lidwake"
93
94#define ARG_HIBERNATEMODE      "hibernatemode"
95#define ARG_HIBERNATEFILE      "hibernatefile"
96#define ARG_HIBERNATEFREERATIO "hibernatefreeratio"
97#define ARG_HIBERNATEFREETIME  "hibernatefreetime"
98#define ARG_AUTOPOWEROFF       "autopoweroff"
99#define ARG_AUTOPOWEROFFDELAY  "autopoweroffdelay"
100
101#define ARG_RING            "ring"
102#define ARG_AUTORESTART     "autorestart"
103#define ARG_WAKEONACCHANGE  "acwake"
104#define ARG_REDUCEBRIGHT    "lessbright"
105#define ARG_SLEEPUSESDIM    "halfdim"
106#define ARG_MOTIONSENSOR    "sms"
107#define ARG_MOTIONSENSOR2   "ams"
108#define ARG_TTYKEEPAWAKE    "ttyskeepawake"
109#define ARG_GPU             "gpuswitch"
110#define ARG_NETAVAILABLE    "networkoversleep"
111#define ARG_DEEPSLEEP       "standby"
112#define ARG_DEEPSLEEPDELAY  "standbydelay"
113#define ARG_DARKWAKES       "darkwakes"
114#define ARG_RESTOREDEFAULTS "restoredefaults"
115
116
117// Scheduling options
118#define ARG_SCHEDULE        "schedule"
119#define ARG_SCHED           "sched"
120#define ARG_REPEAT          "repeat"
121#define ARG_CANCEL          "cancel"
122#define ARG_RELATIVE        "relative"
123//#define ARG_SLEEP         "sleep"
124#define ARG_SHUTDOWN        "shutdown"
125#define ARG_RESTART         "restart"
126#define ARG_WAKE            "wake"
127#define ARG_POWERON         "poweron"
128#define ARG_WAKEORPOWERON   "wakeorpoweron"
129
130// UPS options
131#define ARG_HALTLEVEL       "haltlevel"
132#define ARG_HALTAFTER       "haltafter"
133#define ARG_HALTREMAIN      "haltremain"
134
135// get options
136#define ARG_CAP             "cap"
137#define ARG_DISK            "disk"
138#define ARG_CUSTOM          "custom"
139#define ARG_LIVE            "live"
140#define ARG_SCHED           "sched"
141#define ARG_UPS             "ups"
142#define ARG_SYS_PROFILES    "profiles"
143#define ARG_ADAPTER_AC      "ac"
144#define ARG_ADAPTER         "adapter"
145#define ARG_BATT            "batt"
146#define ARG_PS              "ps"
147#define ARG_PSLOG           "pslog"
148#define ARG_TRCOLUMNS       "trcolumns"
149#define ARG_BATTRAW         "rawbatt"
150#define ARG_PSRAW           "rawlog"
151#define ARG_THERM           "therm"
152#define ARG_THERMLOG        "thermlog"
153#define ARG_ASSERTIONS      "assertions"
154#define ARG_ASSERTIONSLOG   "assertionslog"
155#define ARG_SYSLOAD         "sysload"
156#define ARG_SYSLOADLOG      "sysloadlog"
157#define ARG_USERACTIVITYLOG "useractivitylog"
158#define ARG_USERACTIVITY    "useractivity"
159#define ARG_LOG             "log"
160#define ARG_LISTEN          "listen"
161#define ARG_HISTORY         "history"
162#define ARG_HISTORY_DETAILED "historydetailed"
163#define ARG_HID_NULL        "hidnull"
164#define ARG_BOOKMARK        "bookmark"
165#define ARG_CLEAR_HISTORY   "clearpmhistory"
166#define ARG_SEARCH          "searchforuuid"
167#define ARG_USERCLIENTS     "userclients"
168#define ARG_UUID            "uuid"
169#define ARG_UUID_LOG        "uuidlog"
170#define ARG_EVERYTHING      "everything"
171#define ARG_PRINT_GETTERS   "getters"
172#define ARG_POWERSTATE      "powerstate"
173#define ARG_POWERSTATELOG   "powerstatelog"
174#define ARG_RDSTATS         "stats"
175#define ARG_SYSSTATE        "systemstate"
176#define ARG_SLEEPBLOCKERS   "sleepblockers"
177#define ARG_FBA             "fba"
178
179// special
180#define ARG_BOOT            "boot"
181#define ARG_UNBOOT          "unboot"
182#define ARG_POLLBOOT        "readboot"
183#define ARG_POLLALL         "readall"
184#define ARG_POLLUSER        "readuser"
185#define ARG_FORCE           "force"
186#define ARG_TOUCH           "touch"
187#define ARG_NOIDLE          "noidle"
188#define ARG_SLEEPNOW        "sleepnow"
189#define ARG_DISPLAYSLEEPNOW "displaysleepnow"
190#define ARG_DEBUGTRIG       "debugTrig"
191#define ARG_RESETDISPLAYAMBIENTPARAMS       "resetdisplayambientparams"
192#define ARG_DISABLEASSERTION                "disableassertion"
193#define ARG_ENABLEASSERTION                 "enableassertion"
194#define ARG_RDAP            "rdap"
195#define ARG_DEBUGFLAGS      "debugflags"
196#define ARG_BTINTERVAL      "btinterval"
197#define ARG_DWLINTERVAL     "dwlinterval"
198#define ARG_MT2BOOK         "mt2book"
199#define ARG_SETSAAFLAGS     "saaflags"
200#define ARG_NOPOLL          "nopoll"
201
202// special system
203#define ARG_DISABLESLEEP    "disablesleep"
204#define ARG_DISABLEFDEKEYSTORE  "destroyfvkeyonstandby"
205
206#define kProcNameBufLen                 (2*MAXCOMLEN)
207
208// return values for parseArgs
209#define kParseSuccess                   0       // success
210#define kParseBadArgs                   -1      // error
211#define kParseInternalError             -2      // error
212
213// bitfield for tracking what's been modified in parseArgs()
214#define kModSettings                    (1<<0)
215#define kModProfiles                    (1<<1)
216#define kModUPSThresholds               (1<<2)
217#define kModSched                       (1<<3)
218#define kModRepeat                      (1<<4)
219#define kModSystemSettings              (1<<5)
220
221// return values for idleSettingsNotConsistent
222#define kInconsistentDisplaySetting     1
223#define kInconsistentDiskSetting        2
224#define kConsistentSleepSettings        0
225
226// day-of-week constants for repeating power events
227#define daily_mask      ( kIOPMMonday | kIOPMTuesday | kIOPMWednesday \
228                        | kIOPMThursday | kIOPMFriday | kIOPMSaturday \
229                        | kIOPMSunday)
230#define weekday_mask    ( kIOPMMonday | kIOPMTuesday | kIOPMWednesday \
231                        | kIOPMThursday | kIOPMFriday )
232#define weekend_mask    ( kIOPMSaturday | kIOPMSunday )
233
234#define kDateAndTimeFormat      "MM/dd/yy HH:mm:ss"
235#define kTimeFormat             "HH:mm:ss"
236
237#define kMaxLongStringLength        255
238
239static const size_t kMaxArgStringLength = 49;
240
241#define kUSecPerSec 1000000.0
242
243
244#ifndef kPMPowerStatesChID
245#define kPMPowerStatesChID  IOREPORT_MAKEID('P','M','S','t','H','i','s','t')
246#endif
247
248#ifndef kPMCurrStateChID
249#define kPMCurrStateChID  IOREPORT_MAKEID('P','M','C','u','r','S','t','\0' )
250#endif
251
252/* RootDomain IOReporting channels */
253#define kSleepCntChID IOREPORT_MAKEID('S','l','e','e','p','C','n','t')
254#define kDarkWkCntChID IOREPORT_MAKEID('G','U','I','W','k','C','n','t')
255#define kUserWkCntChID IOREPORT_MAKEID('D','r','k','W','k','C','n','t')
256
257typedef struct {
258    const char *name;
259    const char *displayAs;
260} PMFeature;
261
262/* list of all features */
263PMFeature all_features[] =
264{
265    { kIOPMDisplaySleepKey,         ARG_DISPLAYSLEEP },
266    { kIOPMDiskSleepKey,            ARG_DISKSLEEP },
267    { kIOPMSystemSleepKey,          ARG_SLEEP },
268    { kIOPMWakeOnLANKey,            ARG_WOMP },
269    { kIOPMWakeOnRingKey,           ARG_RING },
270    { kIOPMWakeOnACChangeKey,       ARG_WAKEONACCHANGE },
271    { kIOPMRestartOnPowerLossKey,   ARG_AUTORESTART },
272    { kIOPMWakeOnClamshellKey,      ARG_LIDWAKE },
273    { kIOPMReduceBrightnessKey,     ARG_REDUCEBRIGHT },
274    { kIOPMDisplaySleepUsesDimKey,  ARG_SLEEPUSESDIM },
275    { kIOPMMobileMotionModuleKey,   ARG_MOTIONSENSOR },
276    { kIOPMGPUSwitchKey,            ARG_GPU },
277    { kIOPMDeepSleepEnabledKey,     ARG_DEEPSLEEP },
278    { kIOPMDeepSleepDelayKey,       ARG_DEEPSLEEPDELAY },
279    { kIOPMDarkWakeBackgroundTaskKey, ARG_DARKWAKES },
280    { kIOPMTTYSPreventSleepKey,     ARG_TTYKEEPAWAKE },
281    { kIOHibernateModeKey,          ARG_HIBERNATEMODE },
282    { kIOHibernateFileKey,          ARG_HIBERNATEFILE },
283    { kIOPMAutoPowerOffEnabledKey,  ARG_AUTOPOWEROFF },
284    { kIOPMAutoPowerOffDelayKey,    ARG_AUTOPOWEROFFDELAY }
285};
286
287#define kNUM_PM_FEATURES    (sizeof(all_features)/sizeof(PMFeature))
288
289enum ArgumentType {
290    kApplyToBattery = 1,
291    kApplyToCharger = 2,
292    kApplyToUPS     = 4,
293    kShowColumns    = 8
294};
295
296enum AssertionBitField {
297    kAssertionCPU = 1,
298    kAssertionInflow = 2,
299    kAssertionCharge = 4,
300    kAssertionIdle = 8
301};
302
303// ack port for sleep/wake callback
304static io_connect_t gPMAckPort = MACH_PORT_NULL;
305
306
307enum SleepCallbackBehavior {
308    kLogSleepEvents = (1<<0),
309    kCancelSleepEvents = (1<<1)
310};
311
312/* pmset commands */
313enum PMCommandType {
314    kPMCommandSleepNow = 1,
315    kPMCommandTouch,
316    kPMCommandNoIdle,
317    kPMCommandDisplaySleepNow,
318    kPMCommandDebugTrig
319};
320
321/* check and set int value multiplier */
322enum {
323    kNoMultiplier = 0,
324    kMillisecondsMultiplier = 1000
325};
326
327typedef struct {
328    CFStringRef         who;
329    CFDateRef           when;
330    CFStringRef         which;
331} ScheduledEventReturnType;
332
333
334#define RING_SIZE 100
335typedef struct {
336   asl_object_t msgRing[RING_SIZE];
337   uint32_t readIdx;
338   uint32_t writeIdx;
339} MsgCache;
340
341MsgCache *msgCache = NULL;
342
343// function declarations
344static void usage(void);
345static IOReturn setRootDomainProperty(CFStringRef key, CFTypeRef val);
346static io_registry_entry_t copyRootDomainRef(void);
347static IOReturn _pm_connect(mach_port_t *newConnection);
348static IOReturn _pm_disconnect(mach_port_t connection);
349
350static void show_pm_settings_dict(
351        CFDictionaryRef d,
352        int indent,
353        bool log_overrides,
354        bool prune_unsupported);
355static void show_system_power_settings(void);
356static void show_supported_pm_features(void);
357static void show_custom_pm_settings(void);
358static void show_live_pm_settings(void);
359static void show_ups_settings(void);
360static void show_active_profiles(void);
361static void show_system_profiles(void);
362static void show_scheduled_events(void);
363static void show_active_assertions(uint32_t which);
364static void show_power_sources(int which);
365static bool prevent_idle_sleep(void);
366static void show_assertions(const char *);
367static void log_assertions(void);
368static void show_systemload(void);
369static void log_systemload(void);
370
371static const bool kRunOnce = true;
372static const bool kRunLoop = false;
373static void log_useractivity_presentActive(bool runOnce);
374static void log_useractivity_level(bool runOnce);
375static void show_useractivity_level(uint64_t lev, uint64_t msb);
376
377static void show_log(void);
378static void show_uuid(bool keep_running);
379static void listen_for_everything(void);
380static bool is_display_dim_captured(void);
381static void show_power_adapter(void);
382static void show_getters(void);
383static void show_power_state(char **argv);
384static void show_power_statelog(char **argv);
385static void show_rdStats(char **argv);
386static void show_sysstate(char **argv);
387static void show_sleep_blockers(char **argv);
388#if !TARGET_OS_EMBEDDED
389static void print_fba(char **argv);
390static void show_NULL_HID_events(void);
391#endif
392static void show_everything(char **);
393
394static void show_power_event_history(void);
395static void show_power_event_history_detailed(void);
396static void set_new_power_bookmark(void);
397static void set_debugFlags(char **argv);
398static void set_btInterval(char **argv);
399static void set_dwlInterval(char **argv);
400static void set_saaFlags(char **argv);
401static void show_details_for_UUID(char **UUID_string);
402static void show_root_domain_user_clients(void);
403static void mt2bookmark(void);
404static bool isBatteryPollingStopped(void);
405static void set_nopoll(void);
406
407static void print_pretty_date(CFAbsoluteTime t, bool newline);
408static void print_short_date(CFAbsoluteTime t, bool newline);
409static void print_date_with_style(const char *, CFDateFormatterStyle dayStyle, CFDateFormatterStyle timeStyle, CFAbsoluteTime t, bool newline);
410
411static void sleepWakeCallback(
412        void *refcon,
413        io_service_t y __unused,
414        natural_t messageType,
415        void * messageArgument);
416
417static void install_listen_for_notify_system_power(void);
418static void install_listen_PM_connection(void);
419static void install_listen_IORegisterForSystemPower(void);
420static void install_listen_com_apple_powermanagement_sleepservices_notify(void);
421
422static void log_ps_change_handler(void *);
423static int install_listen_for_power_sources(uintptr_t which);
424static int log_raw_power_source_changes(void);
425static void log_raw_battery_interest(
426        void *refcon,
427        io_service_t batt,
428        natural_t messageType,
429        void *messageArgument);
430static void log_raw_battery_match(
431        void *refcon,
432        io_iterator_t b_iter);
433
434static void log_thermal_events(void);
435static void show_systempower_notify(void);
436static void show_thermal_warning_level(void);
437static void show_thermal_cpu_power_level(void);
438
439static void print_raw_battery_state(io_registry_entry_t b_reg);
440static void print_setting_value(CFTypeRef a, int divider);
441static void print_override_pids(int assertion_type);
442static void print_time_of_day_to_buf(int m, char *buf, int buflen);
443static void print_days_to_buf(int d, char *buf, int buflen);
444static void print_repeating_report(CFDictionaryRef repeat);
445static void print_scheduled_report(CFArrayRef events);
446
447static CFDictionaryRef getPowerEvent(int type, CFDictionaryRef events);
448static int getRepeatingDictionaryMinutes(CFDictionaryRef event);
449static int getRepeatingDictionaryDayMask(CFDictionaryRef event);
450static CFStringRef getRepeatingDictionaryType(CFDictionaryRef event);
451static int arePowerSourceSettingsInconsistent(CFDictionaryRef set);
452static void checkSettingConsistency(CFDictionaryRef profiles);
453static ScheduledEventReturnType *scheduled_event_struct_create(void);
454static void scheduled_event_struct_destroy(ScheduledEventReturnType *);
455static void string_tolower(char *lower_me, char *dst);
456static void string_toupper(char *upper_me, char *dst);
457static int checkAndSetIntValue(
458        char *valstr,
459        CFStringRef settingKey,
460        int apply,
461        int isOnOffSetting,
462        int multiplier,
463        CFMutableDictionaryRef ac,
464        CFMutableDictionaryRef batt,
465        CFMutableDictionaryRef ups);
466static int setUPSValue(
467        char *valstr,
468        CFStringRef    whichUPS,
469        CFStringRef settingKey,
470        int apply,
471        CFMutableDictionaryRef thresholds);
472static int parseScheduledEvent(
473        char                        **argv,
474        int                         *num_args_parsed,
475        ScheduledEventReturnType    *local_scheduled_event,
476        bool                        *cancel_scheduled_event,
477        bool                        is_relative_event);
478static int parseRepeatingEvent(
479        char                        **argv,
480        int                         *num_args_parsed,
481        CFMutableDictionaryRef      local_repeating_event,
482        bool                        *local_cancel_repeating);
483static int parseArgs(
484        int argc,
485        char* argv[],
486        CFDictionaryRef             *settings,
487        int                         *modified_power_sources,
488        bool                        *force_activate_settings,
489        CFDictionaryRef             *active_profiles,
490        CFDictionaryRef             *system_power_settings,
491        CFDictionaryRef             *ups_thresholds,
492        ScheduledEventReturnType    **scheduled_event,
493        bool                        *cancel_scheduled_event,
494        CFDictionaryRef             *repeating_event,
495        bool                        *cancel_repeating_event,
496        uint32_t                    *pmCmd);
497static void displaySleepNow();
498static void swd_debugTrig();
499
500static const char *getCanonicalArgForSynonym(char *pass)
501{
502    if (!pass || 0 == strlen(pass))
503        return ARG_LIVE;
504    if (!strncmp(ARG_DISK, pass, kMaxArgStringLength))
505        return ARG_CUSTOM;
506    if (!strncmp(ARG_ADAPTER_AC, pass, kMaxArgStringLength))
507        return ARG_ADAPTER;
508    if (!strncmp(ARG_BATT, pass, kMaxArgStringLength))
509        return ARG_PS;
510    return pass;
511}
512
513typedef enum {
514    kActionGetOnceNoArgs,
515    kActionGetLog,
516    kActionNotForEverything
517} CommandActionType;
518
519typedef struct {
520    CommandActionType       actionType;
521	const char              *arg;
522	void                    (^action)(char **);
523} CommandAndAction;
524
525static CommandAndAction the_getters[] =
526	{
527		{kActionGetOnceNoArgs,  ARG_LIVE,           ^(char **arg){ show_system_power_settings(); show_active_profiles(); show_live_pm_settings();}},
528		{kActionGetOnceNoArgs,  ARG_CUSTOM,         ^(char **arg){ show_custom_pm_settings(); }},
529        {kActionGetOnceNoArgs,  ARG_CAP,            ^(char **arg){ show_supported_pm_features(); }},
530        {kActionGetOnceNoArgs,  ARG_SCHED,          ^(char **arg){ show_scheduled_events(); }},
531        {kActionGetOnceNoArgs,  ARG_UPS,            ^(char **arg){ show_ups_settings(); }},
532        {kActionGetOnceNoArgs,  ARG_SYS_PROFILES,   ^(char **arg){ show_active_profiles(); show_system_profiles(); }},
533    	{kActionGetOnceNoArgs,  ARG_ADAPTER,        ^(char **arg){ show_power_adapter(); }},
534    	{kActionGetOnceNoArgs,  ARG_PS,             ^(char **arg){ show_power_sources(kApplyToBattery | kApplyToUPS); }},
535    	{kActionGetLog,         ARG_PSLOG,          ^(char **arg){ install_listen_IORegisterForSystemPower();
536                                                        install_listen_for_power_sources(kApplyToBattery | kApplyToUPS);
537                                                        CFRunLoopRun(); }},
538    	{kActionGetLog,         ARG_TRCOLUMNS,      ^(char **arg){ install_listen_IORegisterForSystemPower();
539                                                        install_listen_for_power_sources(kShowColumns);
540                                                        CFRunLoopRun(); }},
541    	{kActionGetLog,         ARG_PSRAW,          ^(char **arg){ log_raw_power_source_changes(); }},
542        {kActionGetOnceNoArgs,  ARG_BATTRAW,        ^(char **arg){ print_raw_battery_state(IO_OBJECT_NULL); }},
543        {kActionGetOnceNoArgs,  ARG_THERM,          ^(char **arg){ show_thermal_warning_level(); show_thermal_cpu_power_level(); }},
544    	{kActionGetLog,         ARG_THERMLOG,       ^(char **arg){ log_thermal_events(); }},
545    	{kActionGetOnceNoArgs,  ARG_ASSERTIONS,     ^(char **arg){ show_assertions(NULL); }},
546    	{kActionGetLog,         ARG_ASSERTIONSLOG,  ^(char **arg){ log_assertions(); }},
547    	{kActionGetOnceNoArgs,  ARG_SYSLOAD,        ^(char **arg){ show_systemload(); }},
548    	{kActionGetLog,         ARG_SYSLOADLOG,     ^(char **arg){ log_systemload(); }},
549    	{kActionGetLog,         ARG_USERACTIVITYLOG,^(char **arg){ log_useractivity_presentActive(kRunLoop); }},
550    	{kActionGetOnceNoArgs,  ARG_USERACTIVITY   ,^(char **arg){ log_useractivity_presentActive(kRunOnce); }},
551    	{kActionGetOnceNoArgs,  ARG_LOG,            ^(char **arg){ show_log(); }},
552    	{kActionGetLog,         ARG_LISTEN,         ^(char **arg){ listen_for_everything(); }},
553    	{kActionGetOnceNoArgs,  ARG_HISTORY,        ^(char **arg){ show_power_event_history(); }},
554    	{kActionGetOnceNoArgs,  ARG_HISTORY_DETAILED, ^(char **arg){ show_power_event_history_detailed(); }},
555#if !TARGET_OS_EMBEDDED
556    	{kActionGetOnceNoArgs,  ARG_HID_NULL,       ^(char **arg){ show_NULL_HID_events(); }},
557        {kActionNotForEverything, ARG_FBA,          ^(char **arg){print_fba(arg); }},
558#endif
559    	{kActionGetOnceNoArgs,  ARG_USERCLIENTS,    ^(char **arg){ show_root_domain_user_clients(); }},
560        {kActionGetOnceNoArgs,  ARG_UUID,           ^(char **arg){ show_uuid(kActionGetOnceNoArgs); }},
561    	{kActionGetLog,         ARG_UUID_LOG,       ^(char **arg){ show_uuid(kActionGetLog); }},
562        {kActionGetOnceNoArgs,  ARG_PRINT_GETTERS,  ^(char **arg){ show_getters(); }},
563        {kActionGetLog,         ARG_SEARCH,         ^(char **arg){show_details_for_UUID(arg); }},
564        {kActionGetOnceNoArgs,  ARG_POWERSTATE,     ^(char **arg){show_power_state(arg); }},
565        {kActionGetLog,         ARG_POWERSTATELOG,  ^(char **arg){show_power_statelog(arg); }},
566        {kActionGetOnceNoArgs,  ARG_RDSTATS,        ^(char **arg){show_rdStats(arg); }},
567        {kActionGetOnceNoArgs,  ARG_SYSSTATE,       ^(char **arg){show_sysstate(arg); }},
568        {kActionGetLog,         ARG_SLEEPBLOCKERS,  ^(char **arg){show_sleep_blockers(arg); }},
569        {kActionNotForEverything,   ARG_EVERYTHING, ^(char **arg){show_everything(arg); }}
570	};
571
572
573static const int the_getters_count = (sizeof(the_getters) / sizeof(CommandAndAction));
574
575
576//****************************
577//****************************
578//****************************
579
580static void usage(void)
581{
582    printf("Usage: pmset <options>\n");
583    printf("See pmset(1) for details: \'man pmset\'\n");
584}
585
586
587
588int main(int argc, char *argv[]) {
589    IOReturn                        ret, ret1, err;
590    io_connect_t                    fb;
591    CFDictionaryRef                 es_custom_settings = 0;
592    int                             modified_power_sources = 0;
593    bool                            force_it = 0;
594    CFDictionaryRef                 ups_thresholds = 0;
595    CFDictionaryRef                 system_power_settings = 0;
596    CFDictionaryRef                 active_profiles = 0;
597    ScheduledEventReturnType        *scheduled_event_return = 0;
598    bool                            cancel_scheduled_event = 0;
599    CFDictionaryRef                 repeating_event_return = 0;
600    bool                            cancel_repeating_event = 0;
601    uint32_t                        pmCommand = 0;
602
603    ret = parseArgs(argc, argv,
604        &es_custom_settings, &modified_power_sources, &force_it,
605        &active_profiles,
606        &system_power_settings,
607        &ups_thresholds,
608        &scheduled_event_return, &cancel_scheduled_event,
609        &repeating_event_return, &cancel_repeating_event,
610        &pmCommand);
611
612    if(ret == kParseBadArgs)
613    {
614        //printf("pmset: error in parseArgs!\n");
615        usage();
616        exit(1);
617    }
618
619    if(ret == kParseInternalError)
620    {
621        fprintf(stderr, "%s: internal error!\n", argv[0]); fflush(stdout);
622        exit(1);
623    }
624
625    switch ( pmCommand )
626    {
627        /*************** Sleep now *************************************/
628        case kPMCommandSleepNow:
629            fb = IOPMFindPowerManagement(MACH_PORT_NULL);
630            if ( MACH_PORT_NULL != fb ) {
631                err = IOPMSleepSystem ( fb );
632
633                if( kIOReturnNotPrivileged == err )
634                {
635                    printf("Sleep error 0x%08x; You must run this as root.\n", err);
636                    exit(EX_NOPERM);
637                } else if ( (MACH_PORT_NULL == fb) || (kIOReturnSuccess != err) )
638                {
639                    printf("Unable to sleep system: error 0x%08x\n", err);
640                    exit(EX_OSERR);
641                } else {
642                    printf("Sleeping now...\n");
643                }
644            }
645
646            return 0;
647
648        /*************** Display Sleep now *************************************/
649        case kPMCommandDisplaySleepNow:
650            displaySleepNow();
651            break;
652
653        case kPMCommandDebugTrig:
654            swd_debugTrig();
655            break;
656
657        /*************** Touch settings *************************************/
658        case kPMCommandTouch:
659            printf("touching prefs file on disk...\n");
660
661            ret = IOPMSetPMPreferences(NULL);
662            if(kIOReturnSuccess != ret)
663            {
664                printf("\'%s\' must be run as root...\n", argv[0]);
665            }
666
667            return 0;
668
669        /*************** Prevent idle sleep **********************************/
670        case kPMCommandNoIdle:
671            if(!prevent_idle_sleep())
672            {
673                printf("Error preventing idle sleep\n");
674            }
675            return 1;
676
677        default:
678            // If no command is specified, execution continues with processing
679            // other command-line arguments
680            break;
681    }
682
683    if(force_it && es_custom_settings)
684    {
685
686        mach_port_t             pm_server = MACH_PORT_NULL;
687        CFDataRef               settings_data;
688        int32_t                 return_code;
689        kern_return_t           kern_result;
690
691        /*
692         * Step 1 - send these forced settings over to powerd.
693         *
694         */
695        err = _pm_connect(&pm_server);
696        if (kIOReturnSuccess == err) {
697            settings_data = IOCFSerialize(es_custom_settings, 0);
698
699            if (settings_data)
700            {
701                kern_result = io_pm_force_active_settings(
702                        pm_server,
703                        (vm_offset_t)CFDataGetBytePtr(settings_data),
704                        (mach_msg_type_number_t)CFDataGetLength(settings_data),
705                        &return_code);
706
707                if( KERN_SUCCESS != kern_result ) {
708                    printf("exit kern_result = 0x%08x\n", kern_result);
709                }
710                if( kIOReturnSuccess != return_code ) {
711                    printf("exit return_code = 0x%08x\n", return_code);
712                }
713
714                CFRelease(settings_data);
715
716                if (KERN_SUCCESS != kern_result || kIOReturnSuccess != return_code) {
717                    exit(1);
718                }
719            }
720            _pm_disconnect(pm_server);
721        }
722
723        /*
724         * Step 2 - this code might be running in a partilially uninitialized OS,
725         * and powerd might not be running. e.g. at Installer context.
726         * Since powerd may not be running, we also activate these settings directly
727         * to the controlling drivers in the kernel.
728         *
729         */
730        CFTypeRef       powersources = IOPSCopyPowerSourcesInfo();
731        CFStringRef     activePowerSource = NULL;
732        CFDictionaryRef useSettings = NULL;
733        if (powersources) {
734            activePowerSource = IOPSGetProvidingPowerSourceType(powersources);
735            if (!activePowerSource) {
736                activePowerSource = CFSTR(kIOPMACPowerKey);
737            }
738            useSettings = CFDictionaryGetValue(es_custom_settings, activePowerSource);
739            if (useSettings) {
740                ActivatePMSettings(useSettings, true);
741            }
742            CFRelease(powersources);
743        }
744
745        // Return here. If this is a 'force' call we do _not_ want
746        // to attempt to write any settings to the disk, or to try anything
747        // else at all, as our environment may be unwritable / diskless
748        // (booted from install CD)
749        return 0;
750    }
751
752    if(es_custom_settings)
753    {
754        CFNumberRef             neg1 = NULL;
755        int                     tmp_int = -1;
756        CFDictionaryRef         tmp_dict = NULL;
757        CFMutableDictionaryRef  customize_active_profiles = NULL;
758
759        // Send pmset changes out to disk
760        if(kIOReturnSuccess != (ret1 = IOPMSetPMPreferences(es_custom_settings)))
761        {
762            if(ret1 == kIOReturnNotPrivileged)
763            {
764                printf("\'%s\' must be run as root...\n", argv[0]);
765            } else {
766                printf("Error 0x%08x writing Energy Saver preferences to disk\n", ret1);
767            }
768            exit(1);
769        }
770
771        // Also need to change the active profile to -1 (Custom)
772        // We assume the user intended to activate these new custom settings.
773        neg1 = CFNumberCreate(0, kCFNumberIntType, &tmp_int);
774        tmp_dict = IOPMCopyActivePowerProfiles();
775        if(!tmp_dict) {
776            printf("Custom profile set; unable to update active profile to -1.\n");
777            exit(1);
778        }
779        customize_active_profiles = CFDictionaryCreateMutableCopy(0, 0, tmp_dict);
780        if(!customize_active_profiles) {
781            printf("Internal error\n");
782            exit(1);
783        }
784        // For each power source we modified settings for, flip that
785        // source's profile to -1
786        if(modified_power_sources & kApplyToCharger) {
787            CFDictionarySetValue( customize_active_profiles,
788                                    CFSTR(kIOPMACPowerKey), neg1);
789        }
790        if(modified_power_sources & kApplyToBattery) {
791            CFDictionarySetValue( customize_active_profiles,
792                                    CFSTR(kIOPMBatteryPowerKey), neg1);
793        }
794        if(modified_power_sources & kApplyToUPS) {
795            CFDictionarySetValue( customize_active_profiles,
796                                    CFSTR(kIOPMUPSPowerKey), neg1);
797        }
798
799        ret = IOPMSetActivePowerProfiles(customize_active_profiles);
800        if(kIOReturnSuccess != ret) {
801            printf("Error 0x%08x writing customized power profiles to disk\n", ret);
802            exit(1);
803        }
804        CFRelease(neg1);
805        CFRelease(tmp_dict);
806        CFRelease(customize_active_profiles);
807
808
809        // Print a warning to stderr if idle sleep settings won't
810        // produce expected result; i.e. sleep < (display | dim)
811        checkSettingConsistency(es_custom_settings);
812        CFRelease(es_custom_settings);
813    }
814
815    if(active_profiles)
816    {
817        ret = IOPMSetActivePowerProfiles(active_profiles);
818        if(kIOReturnSuccess != ret) {
819            printf("Error 0x%08x writing active power profiles to disk\n", ret);
820            exit(1);
821        }
822
823        CFRelease(active_profiles);
824    }
825
826    if(system_power_settings)
827    {
828        int             iii;
829        CFIndex         sys_setting_count = 0;
830
831        if( isA_CFDictionary(system_power_settings)) {
832            sys_setting_count = CFDictionaryGetCount(system_power_settings);
833        }
834
835        if (0 != sys_setting_count)
836        {
837            CFStringRef     *keys = malloc(sizeof(CFStringRef) * sys_setting_count);
838            CFTypeRef       *vals = malloc(sizeof(CFTypeRef) * sys_setting_count);
839
840            if(keys && vals)
841            {
842                CFDictionaryGetKeysAndValues( system_power_settings,
843                                          (const void **)keys, (const void **)vals);
844
845                for(iii=0; iii<sys_setting_count; iii++)
846                {
847                    // We write the settings to disk here; PM configd picks them up and
848                    // sends them to xnu from configd space.
849                    ret = IOPMSetSystemPowerSetting(keys[iii], vals[iii]);
850                    if(kIOReturnNotPrivileged == ret)
851                    {
852                        printf("\'%s\' must be run as root...\n", argv[0]);
853                    }
854                    else if (kIOReturnSuccess != ret)
855                    {
856                        printf("\'%s\' failed to set the value.\n", argv[0]);
857                    }
858                }
859            }
860
861            if (keys) free (keys);
862            if (vals) free (vals);
863        }
864
865        CFRelease(system_power_settings);
866    }
867
868    // Did the user change UPS settings too?
869    if(ups_thresholds)
870    {
871        // Only write out UPS settings if thresholds were changed.
872        //      * UPS sleep timers & energy settings have already been
873        //        written with IOPMSetPMPreferences() regardless.
874        ret1 = IOPMSetUPSShutdownLevels(
875                            CFSTR(kIOPMDefaultUPSThresholds),
876                            ups_thresholds);
877        if(kIOReturnSuccess != ret1)
878        {
879            if(ret1 == kIOReturnNotPrivileged)
880                printf("\'%s\' must be run as root...\n", argv[0]);
881            if(ret1 == kIOReturnError
882                || ret1 == kIOReturnBadArgument)
883                printf("Error writing UPS preferences to disk\n");
884            exit(1);
885        }
886        CFRelease(ups_thresholds);
887    }
888
889
890    if(scheduled_event_return)
891    {
892        if(cancel_scheduled_event)
893        {
894            // cancel the event described by scheduled_event_return
895            ret = IOPMCancelScheduledPowerEvent(
896                    scheduled_event_return->when,
897                    scheduled_event_return->who,
898                    scheduled_event_return->which);
899        } else {
900            ret = IOPMSchedulePowerEvent(
901                    scheduled_event_return->when,
902                    scheduled_event_return->who,
903                    scheduled_event_return->which);
904        }
905
906        if(kIOReturnNotPrivileged == ret) {
907            fprintf(stderr, "%s: This operation must be run as root\n", argv[0]);
908            fflush(stderr);
909            exit(1);
910        }
911        if(kIOReturnSuccess != ret) {
912            fprintf(stderr, "%s: Error in scheduling operation\n", argv[0]);
913            fflush(stderr);
914            exit(1);
915        }
916
917        // free individual members
918        scheduled_event_struct_destroy(scheduled_event_return);
919    }
920
921    if(cancel_repeating_event)
922    {
923        ret = IOPMCancelAllRepeatingPowerEvents();
924        if(kIOReturnSuccess != ret) {
925            if(kIOReturnNotPrivileged == ret) {
926                fprintf(stderr, "pmset: Must be run as root to modify settings\n");
927            } else {
928                fprintf(stderr, "pmset: Error 0x%08x cancelling repeating events\n", ret);
929            }
930            fflush(stderr);
931            exit(1);
932        }
933    }
934
935    if(repeating_event_return)
936    {
937        ret = IOPMScheduleRepeatingPowerEvent(repeating_event_return);
938        if(kIOReturnSuccess != ret) {
939            if(kIOReturnNotPrivileged == ret) {
940                fprintf(stderr, "pmset: Must be run as root to modify settings\n");
941            } else {
942                fprintf(stderr, "pmset: Error 0x%08x scheduling repeating events\n", ret);
943            }
944            fflush(stderr);
945            exit(1);
946        }
947        CFRelease(repeating_event_return);
948    }
949
950
951    return 0;
952}
953
954//****************************
955//****************************
956//****************************
957
958
959io_registry_entry_t _getRootDomain(void)
960{
961    static io_registry_entry_t gRoot = MACH_PORT_NULL;
962
963    if (MACH_PORT_NULL == gRoot)
964        gRoot = IORegistryEntryFromPath( kIOMasterPortDefault,
965                kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain");
966
967    return gRoot;
968}
969
970
971static void swd_debugTrig()
972{
973    io_service_t                rootDomainService = IO_OBJECT_NULL;
974    io_connect_t                gRootDomainConnect = IO_OBJECT_NULL;
975    kern_return_t               kr = 0;
976    IOReturn                    ret;
977
978    // Find it
979    rootDomainService = _getRootDomain();
980    if (IO_OBJECT_NULL == rootDomainService) {
981        goto exit;
982    }
983
984    // Open it
985    kr = IOServiceOpen(rootDomainService, mach_task_self(), 0, &gRootDomainConnect);
986    if (KERN_SUCCESS != kr) {
987        printf("Failed to connect to rootDomain. rc=0x%x\n", kr);
988        goto exit;
989    }
990
991    ret = IOConnectCallMethod(gRootDomainConnect, kPMSleepWakeDebugTrig,
992                    NULL, 0,
993                    NULL, 0, NULL,
994                    NULL, NULL, NULL);
995
996    if (kIOReturnSuccess != ret)
997    {
998        printf("Failed to trigger a sleep wake kernel log collection. rc=0x%x\n", ret);
999        goto exit;
1000    }
1001
1002exit:
1003    if (IO_OBJECT_NULL != gRootDomainConnect)
1004        IOServiceClose(gRootDomainConnect);
1005    return;
1006
1007}
1008
1009
1010static void displaySleepNow()
1011{
1012    io_registry_entry_t disp_wrangler = IO_OBJECT_NULL;
1013    kern_return_t kr;
1014
1015    disp_wrangler = IORegistryEntryFromPath(
1016                            kIOMasterPortDefault,
1017                            kIOServicePlane ":/IOResources/IODisplayWrangler");
1018    if(disp_wrangler == IO_OBJECT_NULL)
1019        return ;
1020
1021    kr = IORegistryEntrySetCFProperty( disp_wrangler, CFSTR("IORequestIdle"),kCFBooleanTrue);
1022
1023    if(kr)
1024        fprintf(stderr, "pmset: Failed to set the display to sleep(err:0x%x)\n", kr);
1025
1026    IOObjectRelease(disp_wrangler);
1027
1028    return ;
1029
1030}
1031
1032static CFTypeRef copyRootDomainProperty(CFStringRef key)
1033{
1034    static io_object_t      rd = IO_OBJECT_NULL;
1035
1036    if (IO_OBJECT_NULL == rd) {
1037        rd = copyRootDomainRef();
1038    }
1039
1040    return IORegistryEntryCreateCFProperty(rd, key, 0, 0);
1041}
1042
1043static IOReturn setRootDomainProperty(CFStringRef key, CFTypeRef val)
1044{
1045    io_registry_entry_t         root_domain = copyRootDomainRef();
1046    IOReturn                    ret;
1047
1048    if(!root_domain) return kIOReturnError;
1049
1050    ret = IORegistryEntrySetCFProperty(root_domain, key, val);
1051
1052    IOObjectRelease(root_domain);
1053    return ret;
1054}
1055
1056static io_registry_entry_t copyRootDomainRef(void)
1057{
1058    return (io_registry_entry_t)IOServiceGetMatchingService(
1059                    MACH_PORT_NULL, IOServiceNameMatching("IOPMrootDomain"));
1060 }
1061
1062static void print_setting_value(CFTypeRef a, int divider)
1063{
1064    int n;
1065
1066    if(isA_CFNumber(a))
1067    {
1068        CFNumberGetValue(a, kCFNumberIntType, (void *)&n);
1069
1070        if( 0 != divider ) n/=divider;
1071
1072        printf("%d", n);
1073    } else if(isA_CFBoolean(a))
1074    {
1075        printf("%d", CFBooleanGetValue(a));
1076    } else if(isA_CFString(a))
1077    {
1078        char buf[100];
1079        if(CFStringGetCString(a, buf, 100, kCFStringEncodingUTF8))
1080        {
1081            printf("%s", buf);
1082        }
1083    } else printf("oops - print_setting_value unknown data type\n");
1084}
1085
1086// Arguments to print_override_pids
1087enum {
1088    _kIOPMAssertionDisplayOn = 5,
1089    _kIOPMAssertionSystemOn = 6
1090};
1091
1092static void show_pm_settings_dict(
1093    CFDictionaryRef d,
1094    int indent,
1095    bool show_overrides,
1096    bool prune_unsupported)
1097{
1098    CFIndex                 count;
1099    int                     i;
1100    int                     j;
1101    int                     divider = 0;
1102    char                    ps[kMaxArgStringLength];
1103    CFStringRef             *keys;
1104    CFTypeRef               *vals;
1105    CFTypeRef               ps_blob;
1106    CFStringRef             activeps = NULL;
1107    int                     show_override_type = 0;
1108    bool                    show_display_dim = false;
1109
1110    ps_blob = IOPSCopyPowerSourcesInfo();
1111    if(ps_blob) {
1112        activeps = IOPSGetProvidingPowerSourceType(ps_blob);
1113    }
1114    if(!activeps) activeps = CFSTR(kIOPMACPowerKey);
1115    if(activeps) CFRetain(activeps);
1116
1117    count = CFDictionaryGetCount(d);
1118    keys = (CFStringRef *)malloc(count * sizeof(CFStringRef));
1119    vals = (CFTypeRef *)malloc(count * sizeof(CFTypeRef));
1120    if(!keys || !vals)
1121        goto exit;
1122    CFDictionaryGetKeysAndValues(d, (const void **)keys, (const void **)vals);
1123
1124    for(i=0; i<count; i++)
1125    {
1126        show_override_type = 0;
1127
1128        if (!CFStringGetCString(keys[i], ps, sizeof(ps), kCFStringEncodingMacRoman))
1129            continue;
1130
1131        if( prune_unsupported
1132            && !IOPMFeatureIsAvailable(keys[i], CFSTR(kIOPMACPowerKey)) )
1133        {
1134            // unsupported setting for the current power source!
1135            // do not show it!
1136            continue;
1137        }
1138
1139        for(j=0; j<indent;j++) printf(" ");
1140
1141        divider = 0;
1142
1143		if (strcmp(ps, kIOPMPrioritizeNetworkReachabilityOverSleepKey) == 0)
1144		{
1145            printf(" %-20s ", ARG_NETAVAILABLE);
1146		} else if (strcmp(ps, kIOPMDisplaySleepKey) == 0) {
1147	        printf(" %-20s ", "displaysleep");
1148	        if(show_overrides) {
1149	            show_override_type = _kIOPMAssertionDisplayOn;
1150		}
1151	        show_display_dim = true;
1152		} else if (strcmp(ps, kIOPMSystemSleepKey) == 0) {
1153			printf(" %-20s ", "sleep");
1154            if(show_overrides) {
1155                show_override_type = _kIOPMAssertionSystemOn;
1156			}
1157  		} else {
1158	        for(j=0; j<kNUM_PM_FEATURES; j++) {
1159	            if (!strncmp(ps, all_features[j].name, kMaxArgStringLength)) {
1160	                printf(" %-20s ", all_features[j].displayAs);
1161                    break;
1162	            }
1163	        }
1164            if (j==kNUM_PM_FEATURES)
1165                printf(" %-20s ",ps);
1166		}
1167
1168        print_setting_value(vals[i], divider);
1169
1170        if(show_override_type)
1171            print_override_pids(show_override_type);
1172        if(show_display_dim) {
1173            if( is_display_dim_captured() )
1174                printf(" (Graphics dim captured)");
1175            show_display_dim = false;
1176        }
1177        printf("\n");
1178    }
1179
1180exit:
1181    if (ps_blob) CFRelease(ps_blob);
1182    if (activeps) CFRelease(activeps);
1183    free(keys);
1184    free(vals);
1185}
1186
1187static void show_system_power_settings(void)
1188{
1189    CFDictionaryRef     system_power_settings = NULL;
1190    CFBooleanRef        b;
1191
1192    system_power_settings = IOPMCopySystemPowerSettings();
1193    if(!isA_CFDictionary(system_power_settings)) {
1194        goto exit;
1195    }
1196
1197    printf("System-wide power settings:\n");
1198
1199    if((b = CFDictionaryGetValue(system_power_settings, kIOPMSleepDisabledKey)))
1200    {
1201        printf(" SleepDisabled\t\t%d\n", (b==kCFBooleanTrue) ? 1:0);
1202    }
1203
1204    if((b = CFDictionaryGetValue(system_power_settings, CFSTR(kIOPMDestroyFVKeyOnStandbyKey))))
1205    {
1206        printf(" DestroyFVKeyOnStandby\t\t%d\n", (b==kCFBooleanTrue) ? 1:0);
1207    }
1208exit:
1209    if (system_power_settings)
1210        CFRelease(system_power_settings);
1211}
1212
1213
1214
1215static void print_override_pids(int assertionType)
1216{
1217    CFDictionaryRef         assertions_pids = NULL;
1218    CFDictionaryRef         assertions_state = NULL;
1219    CFNumberRef             assertion_value;
1220    IOReturn                ret;
1221    char                    display_string[kMaxLongStringLength] = "\0";
1222    size_t                  length = 0;
1223    int                     bgTaskLevel = 0, pushTaskLevel = 0, preventSleepLevel = 0;
1224    int                     proxyLevel = 0;
1225
1226    /*
1227     * Early pre-screening - don't dive into the assertions data
1228     * unless we know that there's an active assertion somewhere in there.
1229     */
1230
1231    ret = IOPMCopyAssertionsStatus(&assertions_state);
1232    if( (kIOReturnSuccess != ret) || !isA_CFDictionary(assertions_state)) {
1233        goto bail;
1234    }
1235
1236    if (_kIOPMAssertionDisplayOn == assertionType)
1237    {
1238        int userIdleLevel = 0;
1239        int noDisplayLevel = 0;
1240        int displayWake = 0;
1241
1242        assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypePreventUserIdleDisplaySleep);
1243        if(assertion_value)
1244            CFNumberGetValue(assertion_value, kCFNumberIntType, &userIdleLevel);
1245
1246        assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypeNoDisplaySleep);
1247        if(assertion_value)
1248            CFNumberGetValue(assertion_value, kCFNumberIntType, &noDisplayLevel);
1249
1250        assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertDisplayWake);
1251        if(assertion_value)
1252            CFNumberGetValue(assertion_value, kCFNumberIntType, &displayWake);
1253
1254        if ((kIOPMAssertionLevelOff == userIdleLevel)
1255            && (kIOPMAssertionLevelOff == noDisplayLevel)
1256            && (kIOPMAssertionLevelOff == displayWake))
1257        {
1258            goto bail;
1259        }
1260       snprintf(display_string, kMaxLongStringLength, " (display sleep prevented by ");
1261       length = strlen(display_string);
1262    }
1263
1264
1265    if (_kIOPMAssertionSystemOn == assertionType)
1266    {
1267        int noIdleLevel = 0;
1268        int userIdleLevel = 0;
1269
1270        assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypeNoIdleSleep);
1271        if(assertion_value)
1272            CFNumberGetValue(assertion_value, kCFNumberIntType, &noIdleLevel);
1273
1274        assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypePreventSystemSleep);
1275        if(assertion_value)
1276            CFNumberGetValue(assertion_value, kCFNumberIntType, &preventSleepLevel);
1277
1278        assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypePreventUserIdleSystemSleep);
1279        if(assertion_value)
1280            CFNumberGetValue(assertion_value, kCFNumberIntType, &userIdleLevel);
1281
1282        assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypeBackgroundTask);
1283        if(assertion_value)
1284            CFNumberGetValue(assertion_value, kCFNumberIntType, &bgTaskLevel);
1285
1286        assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertInternalPreventSleep);
1287        if(assertion_value)
1288            CFNumberGetValue(assertion_value, kCFNumberIntType, &proxyLevel);
1289
1290        assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypeApplePushServiceTask);
1291        if(assertion_value)
1292            CFNumberGetValue(assertion_value, kCFNumberIntType, &pushTaskLevel);
1293        if ((kIOPMAssertionLevelOff == noIdleLevel)
1294            && (kIOPMAssertionLevelOff == preventSleepLevel)
1295            && (kIOPMAssertionLevelOff == bgTaskLevel)
1296            && (kIOPMAssertionLevelOff == pushTaskLevel)
1297            && (kIOPMAssertionLevelOff == userIdleLevel))
1298        {
1299            goto bail;
1300        }
1301
1302       snprintf(display_string, kMaxLongStringLength, " (sleep prevented by ");
1303       length = strlen(display_string);
1304    }
1305
1306
1307    /*
1308     * Find out which pids have asserted this and print 'em out
1309     * We conclude that at least one pid is forcing a relevant assertion.
1310     */
1311    CFNumberRef             *pids = NULL;
1312    CFArrayRef              *assertions = NULL;
1313    CFIndex                 process_count;
1314    int                     this_is_the_first = 1;
1315    int                     i;
1316
1317
1318    ret = IOPMCopyAssertionsByProcess(&assertions_pids);
1319    if( (kIOReturnSuccess != ret) || !isA_CFDictionary(assertions_pids) ) {
1320        goto bail;
1321    }
1322
1323
1324    process_count = CFDictionaryGetCount(assertions_pids);
1325    pids = malloc(sizeof(CFNumberRef)*process_count);
1326    assertions = malloc(sizeof(CFArrayRef)*process_count);
1327    CFDictionaryGetKeysAndValues(assertions_pids,
1328                        (const void **)pids,
1329                        (const void **)assertions);
1330    for(i=0; i<process_count; i++)
1331    {
1332        int         j;
1333
1334        for(j=0; j<CFArrayGetCount(assertions[i]); j++)
1335        {
1336            CFDictionaryRef     tmp_assertion = NULL;
1337            CFNumberRef         tmp_level = NULL;
1338            CFStringRef         tmp_type = NULL;
1339            CFStringRef         process_name = NULL;
1340            char                pnameBuf[kProcNameBufLen];
1341            int                 level = kIOPMAssertionLevelOff;
1342            bool                print_this_pid = false;
1343
1344            tmp_assertion = CFArrayGetValueAtIndex(assertions[i], j);
1345
1346            if (!tmp_assertion || (kCFBooleanFalse == (CFBooleanRef)tmp_assertion))
1347            {
1348                continue;
1349            }
1350
1351            if ( (tmp_type = CFDictionaryGetValue(tmp_assertion, kIOPMAssertionTrueTypeKey)) == NULL)
1352                tmp_type = CFDictionaryGetValue(tmp_assertion, kIOPMAssertionTypeKey);
1353            tmp_level = CFDictionaryGetValue(tmp_assertion, kIOPMAssertionLevelKey);
1354            process_name = CFDictionaryGetValue(tmp_assertion, CFSTR("Process Name"));
1355
1356            level = kIOPMAssertionLevelOff;
1357            if (tmp_level) {
1358                CFNumberGetValue(tmp_level, kCFNumberIntType, &level);
1359            }
1360
1361            if (level != kIOPMAssertionLevelOn) continue;
1362
1363            if (_kIOPMAssertionSystemOn == assertionType) {
1364                if (CFEqual(tmp_type, kIOPMAssertionTypePreventUserIdleSystemSleep)) {
1365                    /* Found an assertion that keeps the system on */
1366                    print_this_pid = true;
1367                }
1368                else if ( (preventSleepLevel) &&
1369                          (CFEqual(tmp_type, kIOPMAssertionTypePreventSystemSleep)) ) {
1370                    print_this_pid = true;
1371                }
1372                else if ( (bgTaskLevel) &&
1373                          (CFEqual(tmp_type, kIOPMAssertionTypeBackgroundTask)) )
1374                {
1375                    print_this_pid = true;
1376                }
1377                else if ( (pushTaskLevel) &&
1378                          (CFEqual(tmp_type, kIOPMAssertionTypeApplePushServiceTask)) )
1379                {
1380                    print_this_pid = true;
1381                }
1382                else if ( (proxyLevel) &&
1383                          (CFEqual(tmp_type, kIOPMAssertInternalPreventSleep )) )
1384                {
1385                    print_this_pid = true;
1386                }
1387            }
1388            else if ((_kIOPMAssertionDisplayOn == assertionType)
1389                    && CFEqual(tmp_type, kIOPMAssertionTypePreventUserIdleDisplaySleep) )
1390            {
1391                /* Found an assertion that keeps the display on */
1392                print_this_pid = true;
1393            }
1394            else if ((_kIOPMAssertionDisplayOn == assertionType)
1395                    && CFEqual(tmp_type, kIOPMAssertDisplayWake) )
1396            {
1397                /* Found an assertion that keeps the display on */
1398                print_this_pid = true;
1399            }
1400            if (print_this_pid)
1401            {
1402                if (this_is_the_first) {
1403                    this_is_the_first = 0;
1404                } else {
1405                    strncat(display_string, ", ", kMaxLongStringLength-length-1);
1406                    length = strlen(display_string);
1407                }
1408
1409                if (process_name && CFStringGetCString(process_name, pnameBuf, sizeof(pnameBuf), kCFStringEncodingUTF8))
1410                {
1411                    strncat(display_string, pnameBuf, kMaxLongStringLength-length-1);
1412                    length = strlen(display_string);
1413                }
1414            }
1415        }
1416    }
1417
1418    strncat(display_string, ")", sizeof(display_string)-strlen(display_string)-1);
1419
1420    printf("%s", display_string);
1421
1422    free(pids);
1423    free(assertions);
1424
1425bail:
1426    if(assertions_state) CFRelease(assertions_state);
1427    if(assertions_pids) CFRelease(assertions_pids);
1428    return;
1429}
1430
1431static void show_supported_pm_features(void)
1432{
1433    CFStringRef 		feature;
1434    CFTypeRef           ps_info = IOPSCopyPowerSourcesInfo();
1435    CFStringRef 		source;
1436    char         	    ps_buf[40];
1437    int 				i;
1438
1439    if(!ps_info) {
1440        source = CFSTR(kIOPMACPowerKey);
1441    } else {
1442        source = IOPSGetProvidingPowerSourceType(ps_info);
1443    }
1444    if(!isA_CFString(source) ||
1445       !CFStringGetCString(source, ps_buf, 40, kCFStringEncodingMacRoman)) {
1446        printf("internal supported features string error!\n");
1447    }
1448
1449    printf("Capabilities for %s:\n", ps_buf);
1450    // iterate the list of all features
1451    for(i=0; i<kNUM_PM_FEATURES; i++)
1452    {
1453        feature = CFStringCreateWithCStringNoCopy(NULL, all_features[i].name,
1454                                                  kCFStringEncodingMacRoman, kCFAllocatorNull);
1455        if (feature)
1456 		{
1457	        if (IOPMFeatureIsAvailable(feature, source))
1458			{
1459                printf(" %s\n", all_features[i].displayAs);
1460	        }
1461	        CFRelease(feature);
1462		}
1463    }
1464    if(ps_info) {
1465		CFRelease(ps_info);
1466	}
1467}
1468
1469static void show_power_profile(
1470    CFDictionaryRef     es,
1471    int                 indent)
1472{
1473    CFIndex             num_profiles;
1474    int                 i, j;
1475    char                ps[kMaxArgStringLength];
1476    CFStringRef         *keys;
1477    CFDictionaryRef     *values;
1478
1479    if(indent<0 || indent>30) indent=0;
1480
1481    num_profiles = CFDictionaryGetCount(es);
1482    keys = (CFStringRef *)malloc(num_profiles * sizeof(CFStringRef));
1483    values = (CFDictionaryRef *)malloc(num_profiles * sizeof(CFDictionaryRef));
1484    if(keys && values)
1485    {
1486        CFDictionaryGetKeysAndValues(es, (const void **)keys, (const void **)values);
1487
1488        for(i=0; i<num_profiles; i++)
1489        {
1490            if(!isA_CFDictionary(values[i]))
1491                continue;
1492
1493            if(!CFStringGetCString(keys[i], ps, sizeof(ps), kCFStringEncodingMacRoman))
1494                continue; // with for loop
1495
1496            for(j=0; j<indent; j++) {
1497                printf(" ");
1498            }
1499            printf("%s:\n", ps);
1500            show_pm_settings_dict(values[i], indent, 0, false);
1501        }
1502    }
1503    if (keys) free(keys);
1504    if (values) free(values);
1505}
1506
1507static void show_custom_pm_settings(void)
1508{
1509    CFDictionaryRef     es = NULL;
1510
1511    // read settings file from /Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist
1512    es = IOPMCopyPMPreferences();
1513    if(!es)
1514        return;
1515    show_power_profile(es, 0);
1516    CFRelease(es);
1517}
1518
1519static void show_live_pm_settings(void)
1520{
1521    SCDynamicStoreRef        ds;
1522    CFDictionaryRef        live;
1523
1524    ds = SCDynamicStoreCreate(NULL, CFSTR("pmset"), NULL, NULL);
1525
1526    // read current settings from SCDynamicStore key
1527    live = SCDynamicStoreCopyValue(ds, CFSTR(kIOPMDynamicStoreSettingsKey));
1528    if(!live)
1529        return;
1530    printf("Currently in use:\n");
1531    show_pm_settings_dict(live, 0, true, true);
1532
1533    CFRelease(live);
1534    CFRelease(ds);
1535}
1536
1537static void show_ups_settings(void)
1538{
1539    CFDictionaryRef     thresholds;
1540    CFDictionaryRef     d;
1541    CFNumberRef         n_val;
1542    int                 val;
1543    CFBooleanRef        b;
1544
1545    thresholds = IOPMCopyUPSShutdownLevels(CFSTR(kIOPMDefaultUPSThresholds));
1546    if(!thresholds)
1547        return;
1548
1549    printf("UPS settings:\n");
1550
1551    if((d = CFDictionaryGetValue(thresholds, CFSTR(kIOUPSShutdownAtLevelKey))))
1552    {
1553        b = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelEnabledKey));
1554        n_val = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelValueKey));
1555        CFNumberGetValue(n_val, kCFNumberIntType, &val);
1556        printf("  %s\t%s\t%d\n", ARG_HALTLEVEL, (kCFBooleanTrue==b)?"on":"off", val);
1557    }
1558    if((d = CFDictionaryGetValue(thresholds, CFSTR(kIOUPSShutdownAfterMinutesOn))))
1559    {
1560        b = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelEnabledKey));
1561        n_val = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelValueKey));
1562        CFNumberGetValue(n_val, kCFNumberIntType, &val);
1563        printf("  %s\t%s\t%d\n", ARG_HALTAFTER, (kCFBooleanTrue==b)?"on":"off", val);
1564    }
1565    if((d = CFDictionaryGetValue(thresholds, CFSTR(kIOUPSShutdownAtMinutesLeft))))
1566    {
1567        b = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelEnabledKey));
1568        n_val = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelValueKey));
1569        CFNumberGetValue(n_val, kCFNumberIntType, &val);
1570        printf("  %s\t%s\t%d\n", ARG_HALTREMAIN, (kCFBooleanTrue==b)?"on":"off", val);
1571    }
1572    CFRelease(thresholds);
1573}
1574
1575static void
1576show_active_profiles(void)
1577{
1578    CFDictionaryRef             active_prof = 0;
1579    int                         i;
1580    CFIndex                     count;
1581    int                         val;
1582    CFNumberRef                 *prof_val = 0;
1583    CFStringRef                 *ps = NULL;
1584    char                        ps_str[40];
1585
1586    CFTypeRef                   ps_info = 0;
1587    CFStringRef                 current_ps = 0;
1588
1589    ps_info = IOPSCopyPowerSourcesInfo();
1590    if(ps_info) current_ps = IOPSGetProvidingPowerSourceType(ps_info);
1591    if(!ps_info || !current_ps) current_ps = CFSTR(kIOPMACPowerKey);
1592
1593    active_prof = IOPMCopyActivePowerProfiles();
1594    if(!active_prof) {
1595        printf("PM system error - no active profiles found\n");
1596        goto exit;
1597    }
1598
1599    count = CFDictionaryGetCount(active_prof);
1600    prof_val = (CFNumberRef *)malloc(sizeof(CFNumberRef)*count);
1601    ps = (CFStringRef *)malloc(sizeof(CFStringRef)*count);
1602    if(!prof_val || !ps) goto exit;
1603
1604    printf("Active Profiles:\n");
1605
1606    CFDictionaryGetKeysAndValues(active_prof, (const void **)ps, (const void **)prof_val);
1607    for(i=0; i<count; i++)
1608    {
1609        if( CFStringGetCString(ps[i], ps_str, 40, kCFStringEncodingMacRoman)
1610          && CFNumberGetValue(prof_val[i], kCFNumberIntType, &val)) {
1611            printf("%s\t\t%d", ps_str, val);
1612
1613            // Put a * next to the currently active power supply
1614            if( current_ps && (kCFCompareEqualTo == CFStringCompare(ps[i], current_ps, 0))) {
1615                printf("*");
1616            }
1617
1618            printf("\n");
1619        }
1620    }
1621
1622exit:
1623    if(active_prof) CFRelease(active_prof);
1624    if(ps_info) CFRelease(ps_info);
1625    if(prof_val) free(prof_val);
1626    if(ps) free(ps);
1627}
1628
1629static void
1630show_system_profiles(void)
1631{
1632    CFArrayRef                  sys_prof;
1633    CFIndex                     prof_count;
1634    int                         i;
1635
1636    sys_prof = IOPMCopyPowerProfiles();
1637    if(!sys_prof) {
1638        printf("No system profiles found\n");
1639        return;
1640    }
1641
1642    prof_count = CFArrayGetCount(sys_prof);
1643    for(i=0; i<prof_count;i++)
1644    {
1645        printf("=== Profile %d ===\n", i);
1646        show_power_profile( CFArrayGetValueAtIndex(sys_prof, i), 0 );
1647        if(i!=(prof_count-1)) printf("\n");
1648    }
1649
1650    CFRelease(sys_prof);
1651}
1652
1653static CFDictionaryRef
1654getPowerEvent(int type, CFDictionaryRef     events)
1655{
1656    if(type)
1657        return (CFDictionaryRef)isA_CFDictionary(CFDictionaryGetValue(events, CFSTR(kIOPMRepeatingPowerOnKey)));
1658    else
1659        return (CFDictionaryRef)isA_CFDictionary(CFDictionaryGetValue(events, CFSTR(kIOPMRepeatingPowerOffKey)));
1660}
1661static int
1662getRepeatingDictionaryMinutes(CFDictionaryRef event)
1663{
1664    int val;
1665    CFNumberRef tmp_num;
1666    tmp_num = (CFNumberRef)CFDictionaryGetValue(event, CFSTR(kIOPMPowerEventTimeKey));
1667    CFNumberGetValue(tmp_num, kCFNumberIntType, &val);
1668    return val;
1669}
1670static int
1671getRepeatingDictionaryDayMask(CFDictionaryRef event)
1672{
1673    int val;
1674    CFNumberRef tmp_num;
1675    tmp_num = (CFNumberRef)CFDictionaryGetValue(event, CFSTR(kIOPMDaysOfWeekKey));
1676    CFNumberGetValue(tmp_num, kCFNumberIntType, &val);
1677    return val;
1678}
1679static CFStringRef
1680getRepeatingDictionaryType(CFDictionaryRef event)
1681{
1682    return (CFStringRef)CFDictionaryGetValue(event, CFSTR(kIOPMPowerEventTypeKey));
1683}
1684
1685static void
1686print_time_of_day_to_buf(int m, char *buf, int buflen)
1687{
1688    int hours, minutes, afternoon;
1689
1690    hours = m/60;
1691    minutes = m%60;
1692    afternoon = 0;
1693    if(hours >= 12) afternoon = 1;
1694    if(hours > 12) hours-=12;
1695
1696    snprintf(buf, buflen, "%d:%d%d%cM", hours,
1697            minutes/10, minutes%10,
1698            (afternoon? 'P':'A'));
1699}
1700
1701static void
1702print_days_to_buf(int d, char *buf, int buflen)
1703{
1704    switch(d) {
1705        case daily_mask:
1706            snprintf(buf, buflen, "every day");
1707            break;
1708
1709        case weekday_mask:
1710            snprintf(buf, buflen, "weekdays only");
1711            break;
1712
1713        case weekend_mask:
1714            snprintf(buf, buflen, "weekends only");
1715            break;
1716
1717        case  0x01 :
1718            snprintf(buf, buflen, "Monday");
1719            break;
1720
1721        case  0x02 :
1722            snprintf(buf, buflen, "Tuesday");
1723            break;
1724
1725        case 0x04 :
1726            snprintf(buf, buflen, "Wednesday");
1727            break;
1728
1729        case  0x08 :
1730            snprintf(buf, buflen, "Thursday");
1731            break;
1732
1733        case 0x10 :
1734            snprintf(buf, buflen, "Friday");
1735            break;
1736
1737        case 0x20 :
1738            snprintf(buf, buflen, "Saturday");
1739            break;
1740
1741        case  0x40 :
1742            snprintf(buf, buflen, "Sunday");
1743            break;
1744
1745        default:
1746            snprintf(buf, buflen, "Some days");
1747            break;
1748    }
1749}
1750
1751#define kMaxDaysOfWeekLength     20
1752static void print_repeating_report(CFDictionaryRef repeat)
1753{
1754    CFDictionaryRef     on, off;
1755    char                time_buf[kMaxDaysOfWeekLength];
1756    char                day_buf[kMaxDaysOfWeekLength];
1757    CFStringRef         type_str = NULL;
1758    char                type_buf[kMaxArgStringLength];
1759
1760    // assumes validly formatted dictionary - doesn't do any error checking
1761    on = getPowerEvent(1, repeat);
1762    off = getPowerEvent(0, repeat);
1763
1764    if(on || off)
1765    {
1766        printf("Repeating power events:\n");
1767        if(on)
1768        {
1769            print_time_of_day_to_buf(getRepeatingDictionaryMinutes(on), time_buf, kMaxDaysOfWeekLength);
1770            print_days_to_buf(getRepeatingDictionaryDayMask(on), day_buf, kMaxDaysOfWeekLength);
1771
1772            type_str = getRepeatingDictionaryType(on);
1773            if (type_str) {
1774                CFStringGetCString(type_str, type_buf, sizeof(type_buf),  kCFStringEncodingMacRoman);
1775            } else {
1776                snprintf(type_buf, sizeof(type_buf), "?type?");
1777            }
1778
1779            printf("  %s at %s %s\n", type_buf, time_buf, day_buf);
1780        }
1781
1782        if(off)
1783        {
1784            print_time_of_day_to_buf(getRepeatingDictionaryMinutes(off), time_buf, kMaxDaysOfWeekLength);
1785            print_days_to_buf(getRepeatingDictionaryDayMask(off), day_buf, kMaxDaysOfWeekLength);
1786
1787            type_str = getRepeatingDictionaryType(off);
1788            if (type_str) {
1789                CFStringGetCString(type_str, type_buf, sizeof(type_buf),  kCFStringEncodingMacRoman);
1790            } else {
1791                snprintf(type_buf, sizeof(type_buf), "?type?");
1792            }
1793
1794            printf("  %s at %s %s\n", type_buf, time_buf, day_buf);
1795        }
1796        fflush(stdout);
1797    }
1798}
1799
1800static void
1801print_scheduled_report(CFArrayRef events)
1802{
1803    CFDictionaryRef     ev;
1804    CFIndex             count, i;
1805    char                date_buf[40];
1806    char                name_buf[255];
1807    char                type_buf[40];
1808    char                *type_ptr = NULL;
1809    CFStringRef         type = NULL;
1810    CFStringRef         author = NULL;
1811    CFDateFormatterRef  formatter = NULL;
1812    CFStringRef         cf_str_date = NULL;
1813
1814    if(!events || !(count = CFArrayGetCount(events))) return;
1815
1816    formatter = CFDateFormatterCreate(kCFAllocatorDefault, CFLocaleGetSystem(),
1817                                      kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle);
1818    CFDateFormatterSetFormat(formatter, CFSTR(kDateAndTimeFormat));
1819
1820    printf("Scheduled power events:\n");
1821    for(i=0; i<count; i++)
1822    {
1823        ev = (CFDictionaryRef)CFArrayGetValueAtIndex(events, i);
1824
1825        cf_str_date = CFDateFormatterCreateStringWithDate(kCFAllocatorDefault,
1826                formatter, CFDictionaryGetValue(ev, CFSTR(kIOPMPowerEventTimeKey)));
1827        date_buf[0] = 0;
1828        if(cf_str_date) {
1829            CFStringGetCString(cf_str_date, date_buf, 40, kCFStringEncodingMacRoman);
1830            CFRelease(cf_str_date);
1831        }
1832
1833        author = CFDictionaryGetValue(ev, CFSTR(kIOPMPowerEventAppNameKey));
1834        name_buf[0] = 0;
1835        if(isA_CFString(author))
1836            CFStringGetCString(author, name_buf, 255, kCFStringEncodingMacRoman);
1837
1838        type = CFDictionaryGetValue(ev, CFSTR(kIOPMPowerEventTypeKey));
1839        type_buf[0] = 0;
1840        if(isA_CFString(type))
1841            CFStringGetCString(type, type_buf, 40, kCFStringEncodingMacRoman);
1842
1843        // rename "wakepoweron" to "wakeorpoweron" to make things consistent between
1844        // "pmset -g" and "pmset sched"
1845        if(!strcmp(type_buf, kIOPMAutoWakeOrPowerOn))
1846            type_ptr = ARG_WAKEORPOWERON;
1847        else
1848            type_ptr = type_buf;
1849
1850        printf(" [%ld]  %s at %s", i, type_ptr, date_buf);
1851        if(name_buf[0]) printf(" by %s", name_buf);
1852        printf("\n");
1853    }
1854
1855    if (formatter)
1856        CFRelease(formatter);
1857}
1858
1859static void show_scheduled_events(void)
1860{
1861    CFDictionaryRef     repeatingEvents;
1862    CFArrayRef          scheduledEvents;
1863
1864    repeatingEvents = IOPMCopyRepeatingPowerEvents();
1865    scheduledEvents = IOPMCopyScheduledPowerEvents();
1866
1867    if(!repeatingEvents && !scheduledEvents) {
1868        printf("No scheduled events.\n"); fflush(stdout);
1869        return;
1870    }
1871
1872    if(repeatingEvents) {
1873        print_repeating_report(repeatingEvents);
1874        CFRelease(repeatingEvents);
1875    }
1876
1877    if(scheduledEvents) {
1878        print_scheduled_report(scheduledEvents);
1879        CFRelease(scheduledEvents);
1880    }
1881}
1882
1883static bool matchingAssertion(CFDictionaryRef asst_dict, CFStringRef asst)
1884{
1885    if(!asst_dict || (kCFBooleanFalse == (CFTypeRef)asst_dict)) return false;
1886
1887    return CFEqual(asst,
1888                   CFDictionaryGetValue(asst_dict, kIOPMAssertionTypeKey));
1889}
1890
1891
1892static void show_active_assertions(uint32_t which)
1893{
1894    // Print active DisableInflow or ChargeInhibit assertions on the
1895    // following line
1896    CFDictionaryRef         assertions_status = NULL;
1897    CFDictionaryRef         assertions_by_pid = NULL;
1898    CFStringRef             *assertionNames = NULL;
1899    CFNumberRef             *assertionValues = NULL;
1900    CFNumberRef             *pids = NULL;
1901    CFArrayRef              *pidAssertions = NULL;
1902    char                    name[50];
1903    int                     val;
1904    CFIndex                 total_assertion_count;
1905    CFIndex                 pid_count;
1906    IOReturn                ret;
1907    int                     i, j, k;
1908
1909    if(0 == which) return;
1910
1911    ret = IOPMCopyAssertionsStatus(&assertions_status);
1912    if(kIOReturnSuccess != ret || !assertions_status)
1913        return;
1914
1915    ret = IOPMCopyAssertionsByProcess(&assertions_by_pid);
1916    if(kIOReturnSuccess != ret || !assertions_by_pid)
1917        return;
1918
1919    // Grab out the total/aggregate sate of the assertions
1920    total_assertion_count = CFDictionaryGetCount(assertions_status);
1921    if(0 == total_assertion_count)
1922        return;
1923
1924    assertionNames = (CFStringRef *)malloc(
1925                                sizeof(CFStringRef) * total_assertion_count);
1926    assertionValues = (CFNumberRef *)malloc(
1927                                sizeof(CFNumberRef) * total_assertion_count);
1928    CFDictionaryGetKeysAndValues(assertions_status,
1929                                (const void **)assertionNames,
1930                                (const void **)assertionValues);
1931
1932    // Grab the list of activated assertions per-process
1933    pid_count = CFDictionaryGetCount(assertions_by_pid);
1934    if(0 == pid_count)
1935        return;
1936
1937    pids = malloc(sizeof(CFNumberRef) * pid_count);
1938    pidAssertions = malloc(sizeof(CFArrayRef) * pid_count);
1939
1940    CFDictionaryGetKeysAndValues(assertions_by_pid,
1941                                (const void **)pids,
1942                                (const void **)pidAssertions);
1943
1944    if ( assertionNames && assertionValues && pidAssertions && pids)
1945    {
1946
1947        for(i=0; i<total_assertion_count; i++)
1948        {
1949            CFStringGetCString(assertionNames[i], name, 50, kCFStringEncodingMacRoman);
1950            CFNumberGetValue(assertionValues[i], kCFNumberIntType, &val);
1951
1952            // Determine if we want to display this assertion
1953            if( !( ( (which & kAssertionCPU) &&
1954                    CFEqual(assertionNames[i], kIOPMCPUBoundAssertion))
1955                || ( (which & kAssertionInflow) &&
1956                    CFEqual(assertionNames[i], kIOPMInflowDisableAssertion))
1957                || ( (which & kAssertionCharge) &&
1958                    CFEqual(assertionNames[i], kIOPMChargeInhibitAssertion))
1959                || ( (which & kAssertionIdle) &&
1960                    CFEqual(assertionNames[i], kIOPMAssertionTypeNoIdleSleep)) ) )
1961            {
1962                // If the caller wasn't interested is this assertion, we pass
1963                continue;
1964            }
1965
1966            if(val)
1967            {
1968                printf("\t'%s':\t", name);
1969                for(j=0; j<pid_count; j++)
1970                {
1971                    for(k=0; k<CFArrayGetCount(pidAssertions[j]); k++)
1972                    {
1973                        CFDictionaryRef     obj;
1974                        if( (obj = (CFDictionaryRef)CFArrayGetValueAtIndex(
1975                                            pidAssertions[j], k)))
1976                        {
1977                            if(matchingAssertion(obj, assertionNames[i]))
1978                            {
1979                                int pid_num = 0;
1980                                CFNumberGetValue(pids[j], kCFNumberIntType, &pid_num);
1981                                printf("%d ", pid_num);
1982                            }
1983                       }
1984                    }
1985                }
1986                printf("\n"); fflush(stdout);
1987            }
1988        }
1989    }
1990    if (assertionNames) free(assertionNames);
1991    if (assertionValues) free(assertionValues);
1992    if (pidAssertions) free(pidAssertions);
1993    if (pids) free(pids);
1994    if (assertions_status) CFRelease(assertions_status);
1995    if (assertions_by_pid) CFRelease(assertions_by_pid);
1996
1997    return;
1998}
1999
2000/******************************************************************************/
2001/*                                                                            */
2002/*      BLOCK IDLE SLEEP                                                      */
2003/*                                                                            */
2004/******************************************************************************/
2005
2006static bool prevent_idle_sleep(void)
2007{
2008    IOPMAssertionID         neverSleep;
2009
2010    if (kIOReturnSuccess !=
2011        IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep,
2012                            kIOPMAssertionLevelOn,
2013                            CFSTR("pmset prevent sleep"),
2014                            &neverSleep))
2015    {
2016        // Failure
2017        return false;
2018    }
2019
2020    printf("Preventing idle sleep (^C to exit)...\n");
2021
2022    // ctrl-c at command-line exits
2023    while(1) {
2024        sleep(100);
2025    }
2026
2027    return true;
2028}
2029enum {
2030    kPrintLotsOfThings  = 0,
2031    kJustPrintSleep     = 1,
2032    kJustPrintWake      = 2
2033};
2034
2035static void printSleepAndWakeReasons(int just_do_it)
2036{
2037    CFStringRef lastSleepReason     = copyRootDomainProperty(CFSTR("Last Sleep Reason"));
2038    CFStringRef wakeReason          = copyRootDomainProperty(CFSTR("Wake Reason"));
2039    CFStringRef wakeType            = copyRootDomainProperty(CFSTR("Wake Type"));
2040    char buf[100];
2041
2042    if (just_do_it != kJustPrintWake)
2043    {
2044        if (lastSleepReason) {
2045            CFStringGetCString(lastSleepReason, buf, sizeof(buf), kCFStringEncodingUTF8);
2046            printf("  Last Sleep Reason = %s\n", buf);
2047        }
2048    }
2049
2050    if (just_do_it != kJustPrintSleep)
2051    {
2052        if (wakeReason) {
2053            CFStringGetCString(wakeReason, buf, sizeof(buf), kCFStringEncodingUTF8);
2054            printf("  Wake Reason = %s\n", buf);
2055        }
2056        if (wakeType) {
2057            CFStringGetCString(wakeType, buf, sizeof(buf), kCFStringEncodingUTF8);
2058            printf("  wakeType = %s\n", buf);
2059        }
2060    }
2061
2062    if (lastSleepReason)        { CFRelease(lastSleepReason); }
2063    if (wakeReason)             { CFRelease(wakeReason); }
2064    if (wakeType)               { CFRelease(wakeType); }
2065
2066    return;
2067}
2068
2069
2070/* sleepWakeCallback
2071 *
2072 * Receives notifications on system sleep and system wake.
2073 */
2074static void
2075sleepWakeCallback(
2076    void *refcon,
2077    io_service_t y __unused,
2078    natural_t messageType,
2079    void * messageArgument)
2080{
2081    uint32_t behavior = (uint32_t)refcon;
2082
2083    switch ( messageType ) {
2084    case kIOMessageSystemWillSleep:
2085        if ( behavior & kLogSleepEvents )
2086        {
2087            printf("\n");
2088            print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
2089            printf("IORegisterForSystemPower: ...Sleeping...\n");
2090//            printSleepAndWakeReasons(kJustPrintSleep);
2091            fflush(stdout);
2092        }
2093
2094        IOAllowPowerChange(gPMAckPort, (long)messageArgument);
2095        break;
2096
2097    case kIOMessageCanSystemSleep:
2098        if( behavior & kCancelSleepEvents )
2099        {
2100            IOCancelPowerChange(gPMAckPort, (long)messageArgument);
2101            printf("\n");
2102            print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
2103            printf("IORegisterForSystemPower: ...Cancelling...\n");
2104//            printSleepAndWakeReasons(kJustPrintSleep);
2105        } else {
2106            IOAllowPowerChange(gPMAckPort, (long)messageArgument);
2107        }
2108        break;
2109
2110    case kIOMessageSystemHasPoweredOn:
2111        if ( behavior & kLogSleepEvents )
2112        {
2113            printf("\n");
2114            print_pretty_date(CFAbsoluteTimeGetCurrent(), false);   // false == no newline
2115            printf("IORegisterForSystemPower: ...HasPoweredOn...\n");
2116            printSleepAndWakeReasons(kJustPrintWake);
2117            fflush(stdout);
2118        }
2119        break;
2120    }
2121
2122    return;
2123}
2124
2125
2126
2127/******************************************************************************/
2128/*                                                                            */
2129/*     PS LOGGING                                                             */
2130/*                                                                            */
2131/******************************************************************************/
2132
2133#define kMaxHealthLength            10
2134#define kMaxNameLength              60
2135
2136static void show_power_sources(int which)
2137{
2138    CFTypeRef           ps_info = IOPSCopyPowerSourcesInfo();
2139    CFArrayRef          list = NULL;
2140    CFStringRef         ps_name = NULL;
2141    static CFStringRef  last_ps = NULL;
2142    static CFAbsoluteTime   invocationTime = 0.0;
2143    CFDictionaryRef     one_ps = NULL;
2144    char                strbuf[kMaxLongStringLength];
2145    CFIndex             count;
2146    int                 i;
2147    int                 show_time_estimate;
2148    CFNumberRef         remaining, charge, capacity;
2149    CFBooleanRef        charging;
2150    CFBooleanRef        charged;
2151    CFBooleanRef        finishingCharge;
2152    CFBooleanRef        present;
2153    CFStringRef         name;
2154    CFStringRef         state;
2155    CFStringRef         transport;
2156    CFStringRef         health;
2157    CFStringRef         confidence;
2158    CFStringRef         failure;
2159    char                _health[kMaxHealthLength];
2160    char                _confidence[kMaxHealthLength];
2161    char                _name[kMaxNameLength];
2162    char                _failure[kMaxLongStringLength];
2163    int                 _hours = 0;
2164    int                 _minutes = 0;
2165    int                 _charge = 0;
2166    int                 _FCCap = 0;
2167    bool                _charging = false;
2168    bool                _charged = false;
2169    bool                _finishingCharge = false;
2170    int                 _warningLevel = 0;
2171    CFArrayRef          permFailuresArray = NULL;
2172    CFStringRef         pfString = NULL;
2173
2174    if(!ps_info) {
2175        printf("No power source info available\n");
2176        return;
2177    }
2178
2179    if (isBatteryPollingStopped()) {
2180        printf("* Battery Polling is Stopped by \"pmset nopoll\" *\n");
2181    }
2182
2183    /* Output path for Time Remaining Columns
2184     *  - Only displays battery
2185     */
2186    if (kShowColumns & which)
2187    {
2188        CFTypeRef               one_ps_descriptor = NULL;
2189        CFAbsoluteTime          nowTime = CFAbsoluteTimeGetCurrent();
2190        uint32_t                minutesSinceInvocation = 0;
2191        int32_t                 estimatedMinutesRemaining = 0;
2192
2193        if (invocationTime == 0.0) {
2194            invocationTime = nowTime;
2195        }
2196
2197        // Note: We assume a one-battery system.
2198        one_ps_descriptor = IOPSGetActiveBattery(ps_info);
2199        if (one_ps_descriptor) {
2200            one_ps = IOPSGetPowerSourceDescription(ps_info, one_ps_descriptor);
2201        }
2202        if(!one_ps) {
2203            printf("Logging power sources: unable to locate battery.\n");
2204            goto exit;
2205        };
2206
2207        charging = CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsChargingKey));
2208        state = CFDictionaryGetValue(one_ps, CFSTR(kIOPSPowerSourceStateKey));
2209        if (CFEqual(state, CFSTR(kIOPSBatteryPowerValue)))
2210        {
2211            remaining = CFDictionaryGetValue(one_ps, CFSTR(kIOPSTimeToEmptyKey));
2212        } else {
2213            remaining = CFDictionaryGetValue(one_ps, CFSTR(kIOPSTimeToFullChargeKey));
2214        }
2215
2216        if (remaining) {
2217            CFNumberGetValue(remaining, kCFNumberIntType, &estimatedMinutesRemaining);
2218        } else {
2219            estimatedMinutesRemaining = -1;
2220        }
2221
2222        minutesSinceInvocation = (nowTime - invocationTime)/60;
2223
2224        charge = CFDictionaryGetValue(one_ps, CFSTR(kIOPSCurrentCapacityKey));
2225        if(charge) CFNumberGetValue(charge, kCFNumberIntType, &_charge);
2226
2227        //  "Elapsed", "TimeRemaining", "Percent""Charge", "Timestamp");
2228        printf("%10d\t%15d\t%10d%%\t%10s\t", minutesSinceInvocation, estimatedMinutesRemaining,
2229                    _charge, (kCFBooleanTrue == charging) ? "charge" : "discharge");
2230        print_pretty_date(CFAbsoluteTimeGetCurrent(), true);
2231
2232        goto exit;
2233    }
2234    /* Completed output path
2235     */
2236
2237    ps_name = IOPSGetProvidingPowerSourceType(ps_info);
2238    if(!ps_name || !CFStringGetCString(ps_name, strbuf, kMaxLongStringLength, kCFStringEncodingUTF8))
2239    {
2240        goto exit;
2241    }
2242    if(!last_ps || kCFCompareEqualTo != CFStringCompare(last_ps, ps_name, 0))
2243    {
2244        printf("Now drawing from '%s'\n", strbuf);
2245    }
2246    if(last_ps) CFRelease(last_ps);
2247    last_ps = CFStringCreateCopy(kCFAllocatorDefault, ps_name);
2248
2249    list = IOPSCopyPowerSourcesList(ps_info);
2250    if(!list) goto exit;
2251    count = CFArrayGetCount(list);
2252    for(i=0; i<count; i++)
2253    {
2254        bzero(_health, sizeof(_health));
2255        bzero(_confidence, sizeof(_confidence));
2256        bzero(_name, sizeof(_name));
2257        bzero(_failure, sizeof(_failure));
2258        _hours = _minutes = _charge = _FCCap = 0;
2259        _charging = _charged = _finishingCharge = false;
2260
2261        one_ps = IOPSGetPowerSourceDescription(ps_info, CFArrayGetValueAtIndex(list, i));
2262        if(!one_ps) break;
2263
2264        // Only display settings for power sources we want to show
2265        transport = CFDictionaryGetValue(one_ps, CFSTR(kIOPSTransportTypeKey));
2266        if(transport &&
2267           (kCFCompareEqualTo != CFStringCompare(transport, CFSTR(kIOPSInternalType), 0)))
2268        {
2269            // Internal transport means internal battery
2270            if(!(which & kApplyToBattery)) continue;
2271        } else {
2272            // Any specified non-Internal transport is a UPS
2273            if(!(which & kApplyToUPS)) continue;
2274        }
2275
2276        charging = CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsChargingKey));
2277        state = CFDictionaryGetValue(one_ps, CFSTR(kIOPSPowerSourceStateKey));
2278        if(state &&
2279           (kCFCompareEqualTo == CFStringCompare(state, CFSTR(kIOPSBatteryPowerValue), 0)))
2280        {
2281            remaining = CFDictionaryGetValue(one_ps, CFSTR(kIOPSTimeToEmptyKey));
2282        } else {
2283            remaining = CFDictionaryGetValue(one_ps, CFSTR(kIOPSTimeToFullChargeKey));
2284        }
2285        name = CFDictionaryGetValue(one_ps, CFSTR(kIOPSNameKey));
2286        charge = CFDictionaryGetValue(one_ps, CFSTR(kIOPSCurrentCapacityKey));
2287        capacity = CFDictionaryGetValue(one_ps, CFSTR(kIOPSMaxCapacityKey));
2288        present = CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsPresentKey));
2289        health = CFDictionaryGetValue(one_ps, CFSTR(kIOPSBatteryHealthKey));
2290        confidence = CFDictionaryGetValue(one_ps, CFSTR(kIOPSHealthConfidenceKey));
2291        failure = CFDictionaryGetValue(one_ps, CFSTR("Failure"));
2292        charged = CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsChargedKey));
2293        finishingCharge = CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsFinishingChargeKey));
2294
2295        permFailuresArray = CFDictionaryGetValue(one_ps, CFSTR(kIOPSBatteryFailureModesKey));
2296
2297        if(name) CFStringGetCString(name, _name,
2298                                kMaxNameLength, kCFStringEncodingMacRoman);
2299        if(health) CFStringGetCString(health, _health,
2300                                kMaxHealthLength, kCFStringEncodingMacRoman);
2301        if(confidence) CFStringGetCString(confidence, _confidence,
2302                                kMaxHealthLength, kCFStringEncodingMacRoman);
2303        if(failure) CFStringGetCString(failure, _failure,
2304                                kMaxLongStringLength, kCFStringEncodingMacRoman);
2305        if(charge) CFNumberGetValue(charge, kCFNumberIntType, &_charge);
2306        if(capacity) CFNumberGetValue(capacity, kCFNumberIntType, &_FCCap);
2307        if(remaining)
2308        {
2309            CFNumberGetValue(remaining, kCFNumberIntType, &_minutes);
2310            if(-1 != _minutes) {
2311                _hours = _minutes/60;
2312                _minutes = _minutes%60;
2313            }
2314        }
2315        if(charging) _charging = (kCFBooleanTrue == charging);
2316        if (charged) _charged = (kCFBooleanTrue == charged);
2317        if (finishingCharge) _finishingCharge = (kCFBooleanTrue == finishingCharge);
2318
2319        _warningLevel = IOPSGetBatteryWarningLevel();
2320
2321        show_time_estimate = 1;
2322
2323        printf(" -");
2324        if(name) printf("%s\t", _name);
2325        if(present && (kCFBooleanTrue == present))
2326        {
2327            if(charge && _FCCap) printf("%d%%; ", _charge*100/_FCCap);
2328            if(charging) {
2329                if (_finishingCharge) {
2330                    printf("finishing charge");
2331                } else if (_charged) {
2332                    printf("charged");
2333                } else if(_charging) {
2334                    printf("charging");
2335                } else {
2336                    if(kCFCompareEqualTo == CFStringCompare(state, CFSTR(kIOPSACPowerValue), 0)) {
2337                        printf("AC attached; not charging");
2338                        show_time_estimate = 0;
2339                    } else {
2340                        printf("discharging");
2341                    }
2342                }
2343            }
2344            if(show_time_estimate && remaining) {
2345                if(-1 != _minutes) {
2346                    printf("; %d:%d%d remaining", _hours, _minutes/10, _minutes%10);
2347                } else {
2348                    printf("; (no estimate)");
2349                }
2350            }
2351            if (health && confidence
2352                && !CFEqual(CFSTR("Good"), health)) {
2353                printf(" (%s/%s)", _health, _confidence);
2354            }
2355            if(failure) {
2356                printf("\n\tfailure: \"%s\"", _failure);
2357            }
2358            if (permFailuresArray) {
2359                CFIndex failure_count = CFArrayGetCount(permFailuresArray);
2360                int m = 0;
2361
2362                printf("\n\tDetailed failures:");
2363
2364                for(m=0; m<failure_count; m++) {
2365                    pfString = CFArrayGetValueAtIndex(permFailuresArray, m);
2366                    if (pfString)
2367                    {
2368                        CFStringGetCString(pfString, strbuf, kMaxLongStringLength, kCFStringEncodingMacRoman);
2369                        printf(" \"%s\"", strbuf);
2370                    }
2371                    if (m != failure_count - 1)
2372                        printf(",");
2373                }
2374            }
2375            printf("\n"); fflush(stdout);
2376
2377            // Show batery warnings on a new line:
2378            if (kIOPSLowBatteryWarningEarly == _warningLevel) {
2379                printf("\tBattery Warning: Early\n");
2380            } else if (kIOPSLowBatteryWarningFinal == _warningLevel) {
2381                printf("\tBattery Warning: Final\n");
2382            }
2383        } else {
2384            printf(" (removed)\n");
2385        }
2386
2387
2388    }
2389
2390    // Display the battery-specific assertions that are affecting the system
2391    show_active_assertions( kAssertionInflow | kAssertionCharge );
2392
2393exit:
2394    if(ps_info) CFRelease(ps_info);
2395    if(list) CFRelease(list);
2396    return;
2397}
2398
2399static void print_pretty_date(CFAbsoluteTime t, bool newline)
2400{
2401    CFDateFormatterRef  date_format;
2402    CFStringRef         time_date;
2403    char                _date[60];
2404
2405    date_format = CFDateFormatterCreate (NULL, NULL, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
2406    CFDateFormatterSetFormat(date_format, CFSTR("yyyy-MM-dd HH:mm:ss ZZZ"));
2407
2408    time_date = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault,
2409        date_format, t);
2410    CFRelease(date_format);
2411
2412    if(time_date)
2413    {
2414        CFStringGetCString(time_date, _date, 60, kCFStringEncodingMacRoman);
2415        printf("%s ", _date); fflush(stdout);
2416        if(newline) printf("\n");
2417        CFRelease(time_date);
2418    }
2419
2420}
2421
2422static void print_short_date(CFAbsoluteTime t, bool newline)
2423{
2424    print_date_with_style("%s ", kCFDateFormatterShortStyle, kCFDateFormatterShortStyle, t, newline);
2425}
2426
2427static void print_compact_date(CFAbsoluteTime t, bool newline)
2428{
2429    int month, day, hour, minute, second;
2430    CFCalendarDecomposeAbsoluteTime(_gregorian(), t, "MdHms", &month, &day, &hour, &minute, &second);
2431    printf("%02d/%02d %02d:%02d:%02d", month, day, hour, minute, second);
2432    if (newline) printf("\n");
2433}
2434
2435static void print_date_with_style(const char *dsf, CFDateFormatterStyle dayStyle, CFDateFormatterStyle timeStyle, CFAbsoluteTime t, bool newline)
2436{
2437    CFDateFormatterRef  date_format;
2438    CFTimeZoneRef       tz;
2439    CFStringRef         time_date;
2440    CFLocaleRef         loc;
2441    char                _date[60];
2442
2443    loc = CFLocaleCopyCurrent();
2444    date_format = CFDateFormatterCreate(kCFAllocatorDefault, loc,
2445        dayStyle, timeStyle);
2446    CFRelease(loc);
2447    tz = CFTimeZoneCopySystem();
2448    CFDateFormatterSetProperty(date_format, kCFDateFormatterTimeZone, tz);
2449    CFRelease(tz);
2450    time_date = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault,
2451        date_format, t);
2452    CFRelease(date_format);
2453
2454    if(time_date)
2455    {
2456        CFStringGetCString(time_date, _date, 60, kCFStringEncodingMacRoman);
2457        printf(dsf, _date); fflush(stdout);
2458        if(newline) printf("\n");
2459        CFRelease(time_date);
2460    }
2461}
2462
2463/******************************************************************************/
2464
2465static void show_assertions_system_aggregates(bool updates_only)
2466{
2467    /*
2468     *   Copy aggregates
2469     */
2470    CFStringRef             *assertionNames = NULL;
2471    CFNumberRef             *assertionValues = NULL;
2472    char                    name[50];
2473    int                     val;
2474    CFIndex                 count;
2475    CFDictionaryRef         assertions_status;
2476    IOReturn                ret;
2477    int                     i;
2478    char                    logStr[120];
2479    int                     len = 0;
2480    static CFDictionaryRef         prevAssertion_status = NULL;
2481    static CFStringRef             *prevAssertionNames = NULL;
2482    static CFNumberRef             *prevAssertionValues = NULL;
2483
2484    ret = IOPMCopyAssertionsStatus(&assertions_status);
2485    if ((kIOReturnSuccess != ret) || (NULL == assertions_status))
2486    {
2487        printf("No assertions.\n");
2488        return;
2489    }
2490
2491    count = CFDictionaryGetCount(assertions_status);
2492    if (0 == count)
2493    {
2494        return;
2495    }
2496
2497    assertionNames = (CFStringRef *)malloc(sizeof(CFStringRef *)*count);
2498    assertionValues = (CFNumberRef *)malloc(sizeof(CFNumberRef *)*count);
2499    CFDictionaryGetKeysAndValues(assertions_status,
2500                                 (const void **)assertionNames, (const void **)assertionValues);
2501
2502    logStr[0] = 0;
2503    if (!updates_only) printf("Assertion status system-wide:\n");
2504
2505    for (i=0; i<count; i++)
2506    {
2507        CFNumberGetValue(assertionValues[i], kCFNumberIntType, &val);
2508        if ((kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeNeedsCPU, 0)) ||
2509            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeDisableInflow, 0)) ||
2510            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeInhibitCharging, 0)) ||
2511            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeDisableLowBatteryWarnings, 0)) ||
2512            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertInternalPreventSleep, 0)) ||
2513            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertInternalPreventDisplaySleep, 0)) ||
2514            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertDisplayWake, 0)) ||
2515            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertPreventDiskIdle, 0)) ||
2516            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertInteractivePushServiceTask, 0)) ||
2517            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeDisableRealPowerSources_Debug, 0)))
2518        {
2519            /* These are rarely used. So, print only if they are set */
2520            if (val == 0)
2521                continue;
2522        }
2523
2524#if !TARGET_OS_EMBEDDED
2525        if ((kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeEnableIdleSleep, 0)) ||
2526            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertAwakeReservePower, 0)) ||
2527            (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeSystemIsActive, 0)))
2528            continue;
2529#endif
2530
2531        if (updates_only) {
2532            if ((prevAssertionNames == NULL) || (prevAssertionValues == NULL) ||
2533                (CFStringCompare(assertionNames[i], prevAssertionNames[i], 0) != kCFCompareEqualTo) ||
2534                (CFNumberCompare(assertionValues[i], prevAssertionValues[i], NULL) != kCFCompareEqualTo)) {
2535
2536                // Print if this assertion status has changed
2537                CFStringGetCString(assertionNames[i], name, 50, kCFStringEncodingMacRoman);
2538
2539                if (len + strlen(name)+4 > sizeof(logStr)) {
2540                    print_compact_date(CFAbsoluteTimeGetCurrent(), false);
2541                    printf("   System wide status: %s\n", logStr);
2542                    len = 0;
2543                    logStr[0] = 0;
2544                }
2545
2546                len += snprintf(logStr, sizeof(logStr), "%s%s: %d  ", logStr, name, val);
2547            }
2548        }
2549        else {
2550            CFStringGetCString(assertionNames[i], name, 50, kCFStringEncodingMacRoman);
2551            printf("   %-30s %d\n", name, val);
2552        }
2553    }
2554
2555    if (len != 0) {
2556        print_compact_date(CFAbsoluteTimeGetCurrent(), false);
2557        printf("   System wide status: %s\n", logStr);
2558    }
2559
2560    if (prevAssertionNames) free(prevAssertionNames);
2561    if (prevAssertionValues) free(prevAssertionValues);
2562    if (prevAssertion_status) CFRelease(prevAssertion_status);
2563    prevAssertionNames = assertionNames;
2564    prevAssertionValues = assertionValues;
2565    prevAssertion_status = assertions_status;
2566}
2567
2568static void show_assertions_individually(void (^printer)(
2569                                   char *pname, char *assertionType, char *assertionName, int createdSince))
2570{
2571    CFDictionaryRef         assertions_info = NULL;
2572    IOReturn                ret;
2573
2574    ret = IOPMCopyAssertionsByProcess(&assertions_info);
2575    if ((kIOReturnSuccess != ret) || !assertions_info) {
2576        return;
2577    }
2578
2579//    printf("\nListed by owning process:\n");
2580    if (!printer) printf("Listed by owning process:\n");
2581    if (!assertions_info) {
2582        if (!printer) printf("   None\n");
2583    } else {
2584
2585        CFNumberRef             *pids = NULL;
2586        CFArrayRef              *assertions = NULL;
2587        CFIndex                 process_count;
2588        int                     i;
2589
2590        process_count = CFDictionaryGetCount(assertions_info);
2591        pids = malloc(sizeof(CFNumberRef)*process_count);
2592        assertions = (CFArrayRef *)malloc(sizeof(CFArrayRef *)*process_count);
2593        CFDictionaryGetKeysAndValues(assertions_info,
2594                                     (const void **)pids,
2595                                     (const void **)assertions);
2596
2597        for(i=0; i<process_count; i++)
2598        {
2599            int the_pid;
2600            int j;
2601
2602            CFNumberGetValue(pids[i], kCFNumberIntType, &the_pid);
2603
2604            for(j=0; j<CFArrayGetCount(assertions[i]); j++)
2605            {
2606                CFDictionaryRef         tmp_dict = NULL;
2607                CFStringRef             val_string = NULL;
2608                CFStringRef             raw_localizable_string = NULL;
2609                CFStringRef             localized_string = NULL;
2610                CFStringRef             bundlePath = NULL;
2611                CFBundleRef             bundle = NULL;
2612                CFURLRef                _url = NULL;
2613                CFNumberRef             uniqueID = NULL;
2614                CFBooleanRef            power_limits = NULL;
2615                uint64_t                uniqueID_int = 0;
2616                CFDateRef               createdDate = NULL;
2617                CFAbsoluteTime          createdCFTime = 0.0;
2618                char                    ageString[40];
2619                CFStringRef             pidName = NULL;
2620                char                    pid_name_buf[100];
2621                CFNumberRef             numRef;
2622                CFStringRef             strRef;
2623
2624                char                    assertionType[400];
2625                char                    val_buf[300];
2626                char                    assertionName[300];
2627                bool                    timed_out = false;
2628                int                     createdSince = 0;
2629
2630                tmp_dict = CFArrayGetValueAtIndex(assertions[i], j);
2631                if(!tmp_dict) {
2632                    goto exit;
2633                }
2634
2635                assertionType[0] = 0;
2636
2637                val_string = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTypeKey);
2638                if (val_string) {
2639                    CFStringGetCString(val_string, assertionType, sizeof(assertionType), kCFStringEncodingMacRoman);
2640                } else {
2641                    snprintf(assertionType, sizeof(assertionType), "Missing AssertType property");
2642                }
2643
2644                val_string = CFDictionaryGetValue(tmp_dict, kIOPMAssertionNameKey);
2645                if (val_string) {
2646                    CFStringGetCString(val_string, assertionName, sizeof(assertionName), kCFStringEncodingMacRoman);
2647                }
2648
2649                timed_out = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTimedOutDateKey);
2650
2651                uniqueID = CFDictionaryGetValue(tmp_dict, kIOPMAssertionGlobalUniqueIDKey);
2652                if (uniqueID) {
2653                    CFNumberGetValue(uniqueID, kCFNumberSInt64Type, &uniqueID_int);
2654                }
2655
2656                if ((createdDate = CFDictionaryGetValue(tmp_dict, kIOPMAssertionCreateDateKey)))
2657                {
2658                    createdCFTime                   = CFDateGetAbsoluteTime(createdDate);
2659                    createdSince                    = (int)(CFAbsoluteTimeGetCurrent() - createdCFTime);
2660                    int hours                       = createdSince / 3600;
2661                    int minutes                     = (createdSince / 60) % 60;
2662                    int seconds                     = createdSince % 60;
2663                    snprintf(ageString, sizeof(ageString), "%02d:%02d:%02d ", hours, minutes, seconds);
2664                }
2665
2666                pid_name_buf[0] = 0;
2667                if ((pidName = CFDictionaryGetValue(tmp_dict, kIOPMAssertionProcessNameKey)))
2668                {
2669                    CFStringGetCString(pidName, pid_name_buf, sizeof(pid_name_buf), kCFStringEncodingUTF8);
2670                }
2671
2672                if (!printer) printf("   pid %d(%s): [0x%016llx] %s%s named: \"%s\" %s\n",
2673                       the_pid, pidName?pid_name_buf:"?",
2674                       uniqueID_int,
2675                       createdDate ? ageString:"",
2676                       assertionType,
2677                       val_string ? assertionName : "(error - no name)",
2678                       timed_out ? "(timed out)" : "");
2679
2680                val_string = CFDictionaryGetValue(tmp_dict, kIOPMAssertionDetailsKey);
2681                if (val_string) {
2682                    CFStringGetCString(val_string, val_buf, sizeof(val_buf), kCFStringEncodingMacRoman);
2683                    if (!printer) printf("\tDetails: %s\n", val_buf);
2684                }
2685
2686                numRef = CFDictionaryGetValue(tmp_dict, kIOPMAssertionOnBehalfOfPID);
2687                if (isA_CFNumber(numRef)) {
2688                    pid_t beneficiary;
2689
2690                    CFNumberGetValue(numRef, kCFNumberIntType, &beneficiary);
2691                    if (!printer) printf("\tCreated for PID: %d. ", beneficiary);
2692                    strRef = CFDictionaryGetValue(tmp_dict, kIOPMAssertionOnBehalfOfPIDReason);
2693                    if (isA_CFString(strRef)) {
2694                        char buf[128];
2695                        buf[0] = 0;
2696                        CFStringGetCString(strRef, buf, sizeof(buf), kCFStringEncodingMacRoman);
2697                        if (!printer) printf("Description: %s", buf);
2698                    }
2699                    if (!printer) printf("\n");
2700                }
2701
2702                raw_localizable_string = CFDictionaryGetValue(tmp_dict, kIOPMAssertionHumanReadableReasonKey);
2703                bundlePath = CFDictionaryGetValue(tmp_dict, kIOPMAssertionLocalizationBundlePathKey);
2704
2705                if (raw_localizable_string && bundlePath) {
2706                    _url = CFURLCreateWithFileSystemPath(0, bundlePath, kCFURLPOSIXPathStyle, TRUE);
2707                    if (_url) {
2708                        bundle = CFBundleCreate(0, _url);
2709                        CFRelease(_url);
2710                    }
2711                    if (bundle) {
2712
2713                        localized_string = CFBundleCopyLocalizedString(bundle, raw_localizable_string, NULL, NULL);
2714
2715                        if (localized_string) {
2716                            if (CFStringGetCString(localized_string, val_buf, sizeof(val_buf), kCFStringEncodingUTF8)) {
2717                                if (!printer) printf("\tLocalized=%s\n", val_buf);
2718                            }
2719                            CFRelease(localized_string);
2720                        }
2721                    }
2722                } // Localize & display human readable string
2723
2724                if ( (power_limits = CFDictionaryGetValue(tmp_dict,
2725                                                          kIOPMAssertionAppliesToLimitedPowerKey)) ) {
2726                    if ((CFBooleanGetValue(power_limits))) {
2727                        if (!printer) printf("\tAssertion applied on Battery power also\n");
2728                    }
2729                    else {
2730                        if (!printer) printf("\tAssertion applied on AC  power only\n");
2731                    }
2732                }
2733
2734                CFNumberRef         timeoutNumCF    = NULL;
2735                uint64_t            timeout         = 0;
2736                CFStringRef         actionStr       = NULL;
2737                char                actionBuf[55];
2738                CFDateRef           updateDate      = NULL;
2739                CFAbsoluteTime      updateTime      = 0;
2740                CFTimeInterval      timeLeft      = 0;
2741                CFAbsoluteTime      now             = CFAbsoluteTimeGetCurrent();
2742
2743                if ( (timeoutNumCF = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTimeoutTimeLeftKey)))
2744                {
2745                    CFNumberGetValue(timeoutNumCF, kCFNumberIntType, &timeout);
2746
2747                    updateDate = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTimeoutUpdateTimeKey);
2748                    if (updateDate) {
2749                        updateTime = CFDateGetAbsoluteTime(updateDate);
2750                    }
2751
2752                    if (timeout && updateDate && ((timeLeft = updateTime+timeout-now) > 0)) {
2753
2754                        actionStr = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTimeoutActionKey);
2755                        if (actionStr) {
2756                            CFStringGetCString(actionStr, actionBuf, sizeof(actionBuf), kCFStringEncodingUTF8);
2757                        }
2758
2759                        if (!printer) printf("\tTimeout will fire in %.0f secs Action=%s\n",
2760                               timeLeft, actionStr ? actionBuf : "<unknown action>");
2761                    }
2762                }
2763
2764                CFArrayRef syms_cf = NULL;;
2765                CFStringRef frame_cf = NULL;
2766                char frame[200];
2767                int  index;
2768
2769                syms_cf = CFDictionaryGetValue(tmp_dict, kIOPMAssertionCreatorBacktrace);
2770                if (syms_cf != NULL) {
2771                    for (index = 0; index < CFArrayGetCount(syms_cf); index++) {
2772                        frame_cf = CFArrayGetValueAtIndex(syms_cf, index);
2773
2774                        frame[0] = 0;
2775                        CFStringGetCString(frame_cf, frame, sizeof(frame), kCFStringEncodingMacRoman);
2776                        if (!printer) printf("%s \n", frame);
2777                    }
2778                }
2779
2780                if (printer) {
2781                    printer(pid_name_buf, assertionType, assertionName, createdSince);
2782                }
2783            }
2784        }
2785        free(pids);
2786        free(assertions);
2787    }
2788
2789exit:
2790    if(assertions_info)
2791        CFRelease(assertions_info);
2792}
2793
2794static void show_assertion_activity(bool init_only)
2795{
2796    int                 num;
2797    CFIndex             cnt = 0;
2798    char                str[200];
2799    bool                of;
2800    uint64_t            num64;
2801    CFDateRef           time_cf = NULL;
2802    static int          lines = 0;
2803    CFArrayRef          log = NULL;
2804    CFNumberRef         num_cf = NULL;
2805    CFStringRef         str_cf = NULL;
2806    static uint32_t     refCnt = UINT_MAX;
2807    CFDictionaryRef     entry;
2808    IOReturn            rc;
2809    pid_t               beneficiary;
2810
2811    rc = IOPMCopyAssertionActivityUpdate(&log, &of, &refCnt);
2812    if ((rc  != kIOReturnSuccess) && (rc != kIOReturnNotFound)) {
2813        show_assertions("Showing all currently held IOKit power assertions");
2814        return;
2815    }
2816    if (!log) {
2817        return;
2818    }
2819
2820    if (init_only) goto exit;
2821
2822    if (of) {
2823        show_assertions("Showing all currently held IOKit power assertions");
2824    }
2825    cnt = isA_CFArray(log) ? CFArrayGetCount(log) : 0;
2826    for (int i=0; i < cnt; i++) {
2827        entry = CFArrayGetValueAtIndex(log, i);
2828        if (entry == NULL) continue;
2829
2830        if ((lines++ % 30) == 0) {
2831            printf("\n%-17s%-12s%-30s%-20s%-20s%-50s\n",
2832                   "Time","Action", "Type", "PID(Causing PID)", "ID", "Name");
2833            printf("%-17s%-12s%-30s%-20s%-20s%-50s\n",
2834                   "====","======", "====", "================", "==", "====");
2835        }
2836
2837        time_cf = CFDictionaryGetValue(entry, kIOPMAssertionActivityTime);
2838        if (time_cf)
2839            print_compact_date(CFDateGetAbsoluteTime(time_cf), false);
2840        printf("   ");
2841
2842        str_cf = CFDictionaryGetValue(entry, kIOPMAssertionActivityAction);
2843        str[0]=0;
2844        if (isA_CFString(str_cf))
2845            CFStringGetCString(str_cf, str, sizeof(str), kCFStringEncodingMacRoman);
2846        printf("%-12s", str);
2847
2848        str_cf = CFDictionaryGetValue(entry, kIOPMAssertionTypeKey);
2849        str[0]=0;
2850        if (isA_CFString(str_cf))
2851            CFStringGetCString(str_cf, str, sizeof(str), kCFStringEncodingMacRoman);
2852        printf("%-30s", str);
2853
2854        num_cf = CFDictionaryGetValue(entry, kIOPMAssertionPIDKey);
2855        if (isA_CFNumber(num_cf)) {
2856            CFNumberGetValue(num_cf, kCFNumberIntType, &num);
2857
2858            num_cf = CFDictionaryGetValue(entry, kIOPMAssertionOnBehalfOfPID);
2859            if (isA_CFNumber(num_cf)) {
2860                CFNumberGetValue(num_cf, kCFNumberIntType, &beneficiary);
2861                str[0] = 0;
2862                sprintf(str,"%d(%d)", num, beneficiary);
2863                printf("%-20s", str);
2864            }
2865            else
2866                printf("%-20d", num);
2867        }
2868
2869        num_cf = CFDictionaryGetValue(entry, kIOPMAssertionGlobalUniqueIDKey);
2870        if (isA_CFNumber(num_cf)) {
2871            CFNumberGetValue(num_cf, kCFNumberSInt64Type, &num64);
2872            printf("0x%-18llx", num64);
2873        }
2874
2875        str_cf = CFDictionaryGetValue(entry, kIOPMAssertionNameKey);
2876        str[0]=0;
2877        if (isA_CFString(str_cf)) {
2878            CFStringGetCString(str_cf, str, sizeof(str), kCFStringEncodingMacRoman);
2879            printf("%-50s", str);
2880        }
2881
2882
2883        printf("\n");
2884    }
2885
2886exit:
2887
2888    if (cnt) CFRelease(log);
2889
2890}
2891
2892static void print_descriptive_kernel_assertions(uint32_t val32)
2893{
2894    bool first = false;
2895    if (0!= val32)
2896        printf("=");
2897    if (val32&kIOPMDriverAssertionCPUBit) {
2898        printf("CPU");
2899        first = true;
2900    }
2901    if (val32&kIOPMDriverAssertionUSBExternalDeviceBit) {
2902        if (first) printf(",");
2903        first=true;
2904        printf("USB");
2905    }
2906    if (val32&kIOPMDriverAssertionBluetoothHIDDevicePairedBit) {
2907        if (first) printf(",");
2908        first=true;
2909        printf("BT-HID");
2910    }
2911    if (val32&kIOPMDriverAssertionExternalMediaMountedBit) {
2912        if (first) printf(",");
2913        first=true;
2914        printf("MEDIA");
2915    }
2916    if (val32&kIOPMDriverAssertionReservedBit5) {
2917        if (first) printf(",");
2918        first=true;
2919        printf("THNDR");
2920    }
2921    if (val32&kIOPMDriverAssertionPreventDisplaySleepBit) {
2922        if (first) printf(",");
2923        first=true;
2924        printf("DSPLY");
2925    }
2926    if (val32&kIOPMDriverAssertionReservedBit7) {
2927        if (first) printf(",");
2928        first=true;
2929        printf("STORAGE");
2930    }
2931    if (val32&kIOPMDriverAssertionMagicPacketWakeEnabledBit) {
2932        if (first) printf(",");
2933        first=true;
2934        printf("MAGICWAKE");
2935    }
2936    return;
2937}
2938
2939static void show_assertions_in_kernel(void)
2940{
2941    CFMutableDictionaryRef  rootDomainProperties = NULL;
2942
2943    CFArrayRef      kernelAssertionsArray = NULL;
2944    CFNumberRef     kernelAssertions = NULL;
2945    int             kernelAssertionsSum = 0;
2946    CFIndex         count;
2947    int             i;
2948    io_registry_entry_t rootDomain = copyRootDomainRef();
2949
2950    IORegistryEntryCreateCFProperties(rootDomain, &rootDomainProperties, 0, 0);
2951
2952    if (rootDomainProperties)
2953    {
2954        kernelAssertions = CFDictionaryGetValue(rootDomainProperties, CFSTR(kIOPMAssertionsDriverKey));
2955        if (kernelAssertions) {
2956            CFNumberGetValue(kernelAssertions, kCFNumberIntType, &kernelAssertionsSum);
2957        }
2958
2959        kernelAssertionsArray = CFDictionaryGetValue(rootDomainProperties, CFSTR(kIOPMAssertionsDriverDetailedKey));
2960    }
2961
2962    if (0 == kernelAssertionsSum) {
2963        printf("No kernel assertions.\n");
2964//        printf("\nNo kernel assertions.\n");
2965        return;
2966    }
2967
2968    printf("Kernel Assertions: 0x%x", kernelAssertionsSum);
2969//    printf("\nKernel Assertions: 0x%x", kernelAssertionsSum);
2970    print_descriptive_kernel_assertions(kernelAssertionsSum);
2971    printf("\n");
2972
2973    if (!kernelAssertionsArray
2974        || !(count = CFArrayGetCount(kernelAssertionsArray)))
2975    {
2976        printf("   None");
2977    } else {
2978        CFDictionaryRef whichAssertion = NULL;
2979        CFStringRef     ownerString = NULL;
2980        char            ownerBuf[100];
2981        io_name_t       serviceNameBuf;
2982        CFNumberRef     registryEntryID = NULL;
2983        CFNumberRef     n_id = NULL;
2984        CFNumberRef     n_modified = NULL;
2985        CFNumberRef     n_owner = NULL;
2986        CFNumberRef     n_level = NULL;
2987        CFNumberRef     n_asserted = NULL;
2988        uint64_t        val64=0;
2989        uint32_t        val32=0;
2990
2991        for (i=0; i<count; i++)
2992        {
2993            whichAssertion = isA_CFDictionary(CFArrayGetValueAtIndex(kernelAssertionsArray, i));
2994            if (!whichAssertion)
2995                continue;
2996#ifndef kIOPMDriverRegistryEntryIDKey
2997#define kIOPMDriverRegistryEntryIDKey "RegistryEntryID"
2998#endif
2999            ownerString         = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionOwnerStringKey));
3000            registryEntryID     = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverRegistryEntryIDKey));
3001            n_id                = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionIDKey));
3002            n_modified          = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionModifiedTimeKey));
3003            n_owner             = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionOwnerServiceKey));
3004            n_level             = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionLevelKey));
3005            n_asserted          = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionAssertedKey));
3006
3007
3008            CFAbsoluteTime      modifiedTime = 1.0;
3009            uint32_t            level = 0;
3010
3011            if (n_modified && CFNumberGetValue(n_modified, kCFNumberSInt64Type, &val64)) {
3012                modifiedTime = _CFAbsoluteTimeFromPMEventTimeStamp(val64);
3013            }
3014            if (n_level) {
3015                CFNumberGetValue(n_level, kCFNumberSInt32Type, &level);
3016            }
3017
3018            if (level != kIOPMAssertionLevelOff)
3019            {
3020                if (n_id && CFNumberGetValue(n_id, kCFNumberSInt64Type, &val64)) {
3021                    printf("   id=%ld ", (long)val64);
3022                }
3023                if (n_owner && CFNumberGetValue(n_owner, kCFNumberSInt64Type, &val64)) {
3024                    printf("by [0x%016lx]", (unsigned long)val64);
3025                }
3026
3027                if (n_asserted) {
3028                    if (CFNumberGetValue(n_asserted, kCFNumberSInt32Type, &val32)) {
3029                        printf(" level=%d 0x%x", level, val32);
3030                        print_descriptive_kernel_assertions(val32);
3031                    }
3032                }
3033                printf(" mod=");
3034                print_short_date(modifiedTime, false);
3035                if (ownerString &&
3036                    CFStringGetCString(ownerString, ownerBuf, sizeof(ownerBuf), kCFStringEncodingUTF8))
3037                {
3038                    printf("description=%s ", ownerBuf);
3039                }
3040
3041                if (registryEntryID && CFNumberGetValue(registryEntryID, kCFNumberSInt64Type, &val64))
3042                {
3043                    io_service_t match = IO_OBJECT_NULL;
3044                    match = IOServiceGetMatchingService(kIOMasterPortDefault, IORegistryEntryIDMatching(val64));
3045                    if (match) {
3046                        IORegistryEntryGetName(match, serviceNameBuf);
3047                        printf("owner=%s", serviceNameBuf);
3048                        IOObjectRelease(match);
3049                    }
3050                }
3051                printf("\n");
3052            }
3053        }
3054    }
3055    CFRelease(rootDomainProperties);
3056}
3057static void show_assertions(const char *decorate)
3058{
3059    print_pretty_date(CFAbsoluteTimeGetCurrent(), decorate?false:true);
3060    if (decorate) {
3061        printf(":%s\n", decorate);
3062    }
3063
3064    show_assertions_system_aggregates(false);
3065    show_assertions_individually(NULL);
3066    show_assertions_in_kernel();
3067
3068    return;
3069}
3070
3071static void log_assertions(void)
3072{
3073    int                 token;
3074    int                 notify_status;
3075
3076    IOPMAssertionNotify(kIOPMAssertionsAnyChangedNotifyString, kIOPMNotifyRegister);
3077    IOPMSetAssertionActivityLog(true);
3078    notify_status = notify_register_dispatch(
3079                                             kIOPMAssertionsAnyChangedNotifyString,
3080                                             &token,
3081                                             dispatch_get_main_queue(),
3082                                             ^(int t) {
3083                                                 show_assertion_activity(false);
3084                                                 show_assertions_system_aggregates(true);
3085                                             });
3086
3087    if (NOTIFY_STATUS_OK != notify_status) {
3088        printf("Could not get notification for %s. Exiting.\n",
3089               kIOPMAssertionsAnyChangedNotifyString);
3090        return;
3091    }
3092
3093    show_assertions("Showing all currently held IOKit power assertions");
3094    show_assertion_activity(true);
3095    printf("\nShowing assertion changes(Press Ctrl-T to log all currently held assertions):\n");
3096
3097    dispatch_source_t sig_info = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGINFO,
3098                                                        0, dispatch_get_main_queue());
3099    dispatch_source_set_event_handler(sig_info,
3100                                      ^{
3101                                          printf("\n");
3102                                          show_assertions("Showing all currently held IOKit power assertions");
3103                                          printf("\nShowing assertion changes(Press Ctrl-T to log all currently held assertions):\n");
3104
3105                                          printf("\n%-17s%-12s%-30s%-10s%-16s%-50s\n",
3106                                                 "Time","Action", "Type", "PID", "ID", "Name");
3107                                          printf("%-17s%-12s%-30s%-10s%-16s%-50s\n",
3108                                                 "====","======", "====", "===", "==", "====");
3109                                      });
3110    dispatch_resume(sig_info);
3111
3112    dispatch_main();
3113}
3114
3115/******************************************************************************/
3116
3117static const char *stringForGTLevel(int gtl)
3118{
3119    if (kIOSystemLoadAdvisoryLevelGreat == gtl) {
3120        return "Great";
3121    } else if (kIOSystemLoadAdvisoryLevelOK == gtl) {
3122        return "OK";
3123    } else if (kIOSystemLoadAdvisoryLevelBad == gtl) {
3124        return "Bad";
3125    }
3126    return "(Unknown system load level)";
3127}
3128
3129static void show_systemload(void)
3130{
3131    CFDictionaryRef     detailed = NULL;
3132    CFNumberRef         n = NULL;
3133    int                 userLevel       = kIOSystemLoadAdvisoryLevelOK;
3134    int                 batteryLevel    = kIOSystemLoadAdvisoryLevelOK;
3135    int                 thermalLevel    = kIOSystemLoadAdvisoryLevelOK;
3136    int                 combinedLevel   = kIOSystemLoadAdvisoryLevelOK;
3137
3138    print_pretty_date(CFAbsoluteTimeGetCurrent(), true);
3139
3140    combinedLevel = IOGetSystemLoadAdvisory();
3141    if (0 == combinedLevel) {
3142        printf("- Internal error: IOGetSystemLoadAdvisory returns error value %d\n", combinedLevel);
3143        return;
3144    }
3145
3146    detailed = IOCopySystemLoadAdvisoryDetailed();
3147    if (!detailed) {
3148        printf("- Internal error: Invalid dictionary %p returned from IOCopySystemLoadAdvisoryDetailed.\n", detailed);
3149        return;
3150    }
3151
3152    n = CFDictionaryGetValue(detailed, kIOSystemLoadAdvisoryUserLevelKey);
3153    if (n) {
3154        CFNumberGetValue(n, kCFNumberIntType, &userLevel);
3155    }
3156    n = CFDictionaryGetValue(detailed, kIOSystemLoadAdvisoryBatteryLevelKey);
3157    if (n) {
3158        CFNumberGetValue(n, kCFNumberIntType, &batteryLevel);
3159    }
3160    n = CFDictionaryGetValue(detailed, kIOSystemLoadAdvisoryThermalLevelKey);
3161    if (n) {
3162        CFNumberGetValue(n, kCFNumberIntType, &thermalLevel);
3163    }
3164    CFRelease(detailed);
3165
3166    printf("  combined level = %s\n",  stringForGTLevel(combinedLevel));
3167    printf("  - user level = %s\n",    stringForGTLevel(userLevel));
3168    printf("  - battery level = %s\n", stringForGTLevel(batteryLevel));
3169    printf("  - thermal level = %s\n", stringForGTLevel(thermalLevel));
3170    fflush(stdout);
3171
3172    return;
3173}
3174
3175static void log_systemload(void)
3176{
3177    int                 token = 0;
3178    uint32_t            notify_status = 0;
3179
3180    show_systemload();
3181
3182    notify_status = notify_register_dispatch(
3183            kIOSystemLoadAdvisoryNotifyName,
3184            &token,
3185            dispatch_get_main_queue(),
3186            ^(int t) {
3187               show_systemload();
3188             });
3189
3190    if (NOTIFY_STATUS_OK != notify_status)
3191    {
3192        printf("LogSystemLoad: notify_register_dispatch returns error %d; Exiting.\n", notify_status);
3193        return;
3194    }
3195
3196    dispatch_main();
3197}
3198
3199/*
3200 * IOKit has 3 SPI's tracking user active
3201 * (1) BSD notify: kIOUserActivityNotifyName
3202 * (2) IOKit kernel notification: IOPMScheduleUserActiveChangedNotification()
3203 * (3) powerd notification: IOPMScheduleUserActivityLevelNotification()
3204 *
3205 * <rdar://problem/16346212> Migrate UserActive SPI clients onto UserActivityLevel
3206 */
3207
3208
3209static void show_useractivity_presentActive(int notifyToken)
3210{
3211    uint64_t newVal;
3212    notify_get_state(notifyToken, &newVal);
3213
3214    print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3215    if (newVal == kIOUserIsIdle) {
3216        printf("[KernelDisplayEvent] User is idle on the system\n");
3217    } else {
3218        printf("[KernelDisplayEvent] User is active on the system\n");
3219    }
3220}
3221static void log_useractivity_presentActive(bool runOnce)
3222{
3223    int                 token = 0;
3224    int                 status;
3225
3226    status = notify_register_check(kIOUserActivityNotifyName, &token);
3227    if (NOTIFY_STATUS_OK == status)
3228    {
3229        show_useractivity_presentActive(token);
3230        notify_cancel(token);
3231    }
3232
3233    log_useractivity_level(kRunOnce);
3234
3235    if (runOnce == kRunOnce) {
3236        return;
3237    }
3238
3239    status = notify_register_dispatch(
3240            kIOUserActivityNotifyName,
3241            &token,
3242            dispatch_get_main_queue(),
3243            ^(int t) {
3244                show_useractivity_presentActive(t);
3245            });
3246
3247    if (NOTIFY_STATUS_OK != status)
3248    {
3249        printf("LogUserActivity: notify_register_dispatch returns error %d; Exiting.\n", status);
3250        return;
3251    }
3252
3253    log_useractivity_level(kRunLoop);
3254
3255    dispatch_main();
3256}
3257static void show_useractivity_level(uint64_t lev, uint64_t msb)
3258{
3259    CFStringRef     temp = NULL;
3260    char            buf[200];
3261
3262    print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3263    printf("UserActivity Level=0x%02x\n", (unsigned int)lev);
3264
3265    temp = IOPMCopyUserActivityLevelDescription(lev);
3266    if (!temp) {
3267        printf("[FAIL] IOPMCopyUserActivityLevelDescription(0x%02x) returned NULL", (unsigned int)lev);
3268    } else {
3269        CFStringGetCString(temp, buf, sizeof(buf), kCFStringEncodingUTF8);
3270        printf("  Level = \'%s\'\n", buf);
3271        CFRelease(temp);
3272    }
3273    temp = IOPMCopyUserActivityLevelDescription(msb);
3274    if (!temp) {
3275        printf("[FAIL] IOPMCopyUserActivityLevelDescription(0x%02x) returned NULL", (unsigned int)msb);
3276    } else {
3277        CFStringGetCString(temp, buf, sizeof(buf), kCFStringEncodingUTF8);
3278        printf("  MostSignificant = \'%s\'\n", buf);
3279        CFRelease(temp);
3280    }
3281    return;
3282}
3283
3284
3285static void log_useractivity_level(bool runOnce)
3286{
3287    IOPMNotificationHandle pmHandle = NULL;
3288    uint64_t userLevel, significantLevel;
3289    IOReturn r;
3290
3291    if (kRunOnce == runOnce) {
3292        r = IOPMGetUserActivityLevel(&userLevel, &significantLevel);
3293
3294        if (kIOReturnSuccess == r) {
3295            show_useractivity_level(userLevel, significantLevel);
3296        } else {
3297            printf("[FAIL] IOPMGetUserActivityLevel returns error 0x%08x\n", r);
3298            return;
3299        }
3300        return;
3301    }
3302
3303    pmHandle = IOPMScheduleUserActivityLevelNotification(dispatch_get_main_queue(),
3304         ^(uint64_t levels, uint64_t most) {
3305             show_useractivity_level(levels, most);
3306         });
3307
3308    if (!pmHandle) {
3309        printf("[FAIL] IOPMScheduleUserActivityLevelNotification returned NULL\n");
3310    }
3311
3312    // Share a run loop with the other useractivity listeners
3313//    dispatch_main();
3314
3315}
3316
3317/******************************************************************************/
3318
3319static void log_ps_change_handler(void *info)
3320{
3321    int which = (int)info;
3322
3323    if (!(which & kShowColumns)) {
3324        print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3325        printf("IOPSNotificationCreateRunLoopSource\n");
3326    }
3327    show_power_sources(which);
3328}
3329
3330static int install_listen_for_power_sources(uintptr_t which)
3331{
3332    CFRunLoopSourceRef          rls = NULL;
3333
3334    /* Log changes to all attached power sources */
3335    rls = IOPSNotificationCreateRunLoopSource(log_ps_change_handler, (void *)which);
3336    if(!rls) {
3337        printf("Error - IOPSNotificationCreateRunLoopSource failure.\n");
3338        return kParseInternalError;
3339    } else {
3340        CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
3341        CFRelease(rls);
3342
3343        printf("pmset is in logging mode now. Hit ctrl-c to exit.\n");
3344
3345        if (kShowColumns & which)
3346        {
3347            printf("%10s\t%15s\t%10s\t%10s\t%20s\n",
3348                "Elapsed", "TimeRemaining", "Charge", "Charging", "Timestamp");
3349        }
3350
3351        // and show initial power source state:
3352        log_ps_change_handler((void *)which);
3353    }
3354
3355    if (!(which & kShowColumns)) {
3356        int tokenA, tokenB, tokenC, tokenD;
3357
3358        notify_register_dispatch(kIOPSNotifyLowBattery,
3359                                &tokenA, dispatch_get_main_queue(),
3360                                ^(int t) {
3361                                    print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3362                                    printf("%s\n", kIOPSNotifyLowBattery);
3363                                });
3364
3365        notify_register_dispatch(kIOPSNotifyTimeRemaining,
3366                                 &tokenB, dispatch_get_main_queue(),
3367                                 ^(int t) {
3368                                     print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3369                                     printf("%s\n", kIOPSNotifyTimeRemaining);
3370                                 });
3371        notify_register_dispatch(kIOPSNotifyPowerSource,
3372                                 &tokenC, dispatch_get_main_queue(),
3373                                 ^(int t) {
3374                                     print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3375                                     printf("%s\n", kIOPSNotifyPowerSource);
3376                                 });
3377        notify_register_dispatch(kIOPSNotifyAttach,
3378                                 &tokenC, dispatch_get_main_queue(),
3379                                 ^(int t) {
3380                                     print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3381                                     printf("%s\n", kIOPSNotifyAttach);
3382                                 });
3383        notify_register_dispatch(kIOPSNotifyAnyPowerSource,
3384                                 &tokenC, dispatch_get_main_queue(),
3385                                 ^(int t) {
3386                                     print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3387                                     printf("%s\n", kIOPSNotifyAnyPowerSource);
3388                                 });
3389        notify_register_dispatch(kIOPSNotifyPercentChange,
3390                                 &tokenD, dispatch_get_main_queue(),
3391                                 ^(int t) {
3392                                     print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3393                                     printf("%s\n", kIOPSNotifyPercentChange);
3394                                 });
3395    }
3396
3397    return 0;
3398}
3399
3400
3401
3402
3403/******************************************************************************/
3404/*                                                                            */
3405/*     RAW PS LOGGING                                                         */
3406/*                                                                            */
3407/******************************************************************************/
3408
3409static CFAbsoluteTime getAbsoluteTimeForProperty(CFDictionaryRef d, CFStringRef key)
3410{
3411    CFNumberRef     secSince1970 = NULL;
3412    uint32_t        secs = 0;
3413    CFAbsoluteTime  return_val = 0.0;
3414
3415    if (d && key)
3416    {
3417        secSince1970 = CFDictionaryGetValue(d, key);
3418        if (secSince1970) {
3419            CFNumberGetValue(secSince1970, kCFNumberIntType, &secs);
3420            return_val = (CFAbsoluteTime)secs - kCFAbsoluteTimeIntervalSince1970;
3421        }
3422    }
3423
3424    return return_val;
3425}
3426
3427static void print_raw_battery_state(io_registry_entry_t b_reg)
3428{
3429    CFDateFormatterRef      date_format;
3430    CFTimeZoneRef           tz;
3431    CFStringRef             time_date;
3432    CFLocaleRef             loc;
3433    char                    _date[60];
3434
3435    CFStringRef             failure;
3436    char                    _failure[200];
3437    CFBooleanRef            boo;
3438    CFNumberRef             n;
3439    int                     tmp;
3440    int                     cur_cap = -1;
3441    int                     max_cap = -1;
3442    int                     design_cap = -1;
3443    int                     cur_cycles = -1;
3444    CFMutableDictionaryRef  prop = NULL;
3445    IOReturn                ret;
3446
3447    loc = CFLocaleCopyCurrent();
3448    date_format = CFDateFormatterCreate(kCFAllocatorDefault, loc,
3449                                        kCFDateFormatterShortStyle, kCFDateFormatterLongStyle);
3450    CFRelease(loc);
3451    tz = CFTimeZoneCopySystem();
3452    CFDateFormatterSetProperty(date_format, kCFDateFormatterTimeZone, tz);
3453    CFRelease(tz);
3454    CFDateFormatterSetFormat(date_format, CFSTR(kDateAndTimeFormat));
3455    time_date = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault,
3456                                                            date_format, CFAbsoluteTimeGetCurrent());
3457
3458    if(time_date)
3459    {
3460        CFStringGetCString(time_date, _date, 60, kCFStringEncodingMacRoman);
3461        printf("%s\n", _date); fflush(stdout);
3462        CFRelease(time_date);
3463    }
3464
3465    if (IO_OBJECT_NULL == b_reg) {
3466        b_reg = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleSmartBattery"));
3467    }
3468
3469    ret = IORegistryEntryCreateCFProperties(b_reg, &prop, 0, 0);
3470    if( (kIOReturnSuccess != ret) || (NULL == prop) )
3471    {
3472        printf("Couldn't read battery status; error = 0%08x\n", ret);
3473        goto exit;
3474    }
3475
3476    boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSExternalConnectedKey));
3477    printf(" %s; ", (kCFBooleanTrue == boo) ? "AC" : "No AC");
3478
3479    boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSBatteryInstalledKey));
3480    printf("%s", (kCFBooleanTrue == boo) ? "" : "No battery; ");
3481
3482    boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSIsChargingKey));
3483    printf("%s; ", (kCFBooleanTrue == boo) ? "Charging" : "Not Charging");
3484
3485    n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSCurrentCapacityKey));
3486    if(n) {
3487        CFNumberGetValue(n, kCFNumberIntType, &cur_cap);
3488    }
3489    n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSMaxCapacityKey));
3490    if(n) {
3491        CFNumberGetValue(n, kCFNumberIntType, &max_cap);
3492    }
3493    n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSDesignCapacityKey));
3494    if(n) {
3495        CFNumberGetValue(n, kCFNumberIntType, &design_cap);
3496    }
3497
3498    if( (-1 != cur_cap) && (-1 != max_cap) )
3499    {
3500        if (0 == max_cap) {
3501            printf("NaN%%; Cap=%d: FCC=%d; Design=%d; ", cur_cap, max_cap, design_cap);
3502        } else {
3503            printf("%d%%; Cap=%d: FCC=%d; Design=%d; ", (cur_cap*100)/max_cap, cur_cap, max_cap, design_cap);
3504        }
3505    }
3506
3507    n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSTimeRemainingKey));
3508    if(n) {
3509        CFNumberGetValue(n, kCFNumberIntType, &tmp);
3510        printf("Time=%d:%02d; ", tmp/60, tmp%60);
3511    }
3512    n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSAmperageKey));
3513    if(n) {
3514        CFNumberGetValue(n, kCFNumberIntType, &tmp);
3515        printf("%dmA; ", tmp);
3516    }
3517    n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSCycleCountKey));
3518    if(n) {
3519        CFNumberGetValue(n, kCFNumberIntType, &cur_cycles);
3520    }
3521
3522    printf("Cycles=%d", cur_cycles);
3523    n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSLocationKey));
3524    if(n) {
3525        CFNumberGetValue(n, kCFNumberIntType, &tmp);
3526        printf("; Location=%d; ", tmp);
3527    }
3528
3529    failure = CFDictionaryGetValue(prop, CFSTR("ErrorCondition"));
3530    if(failure) {
3531        CFStringGetCString(failure, _failure, 200, kCFStringEncodingMacRoman);
3532        printf("\n Failure=\"%s\"", _failure);
3533    }
3534
3535#ifndef kIOBatteryBootPathKey
3536#define kIOBatteryBootPathKey             "BootPathUpdated"
3537#define kIOBatteryFullPathKey             "FullPathUpdated"
3538#define kIOBatterykUserVisPathKey          "UserVisiblePathUpdated"
3539#endif
3540
3541    printf("\n");
3542    CFAbsoluteTime  since = 0.0;
3543    CFStringRef     since_string = NULL;
3544    char            since_str[65];
3545    since = getAbsoluteTimeForProperty(prop, CFSTR(kIOBatteryBootPathKey));
3546    if (0.0 != since) {
3547        since_string = CFDateFormatterCreateStringWithAbsoluteTime(0, date_format, since);
3548        CFStringGetCString(since_string, since_str, sizeof(since_str), kCFStringEncodingUTF8);
3549        printf(" Polled boot=%s", since_str);
3550        CFRelease(since_string);
3551    }
3552    since = getAbsoluteTimeForProperty(prop, CFSTR(kIOBatteryFullPathKey));
3553    if (0.0 != since) {
3554        since_string = CFDateFormatterCreateStringWithAbsoluteTime(0, date_format, since);
3555        CFStringGetCString(since_string, since_str, sizeof(since_str), kCFStringEncodingUTF8);
3556        printf("; Full=%s", since_str);
3557        CFRelease(since_string);
3558    }
3559    since = getAbsoluteTimeForProperty(prop, CFSTR(kIOBatterykUserVisPathKey));
3560    if (0.0 != since) {
3561        since_string = CFDateFormatterCreateStringWithAbsoluteTime(0, date_format, since);
3562        CFStringGetCString(since_string, since_str, sizeof(since_str), kCFStringEncodingUTF8);
3563        printf("; User visible=%s", since_str);
3564        CFRelease(since_string);
3565    }
3566    printf("\n"); fflush(stdout);
3567
3568exit:
3569    if (date_format) {
3570        CFRelease(date_format);
3571    }
3572    if (prop) {
3573        CFRelease(prop);
3574    }
3575    return;
3576}
3577
3578
3579static void log_raw_battery_match(
3580    void *refcon,
3581    io_iterator_t b_iter)
3582{
3583    IONotificationPortRef       notify = *((IONotificationPortRef *)refcon);
3584    io_registry_entry_t         battery;
3585    io_object_t                 notification_ref;
3586    int                         found = false;
3587
3588    while ((battery = (io_registry_entry_t)IOIteratorNext(b_iter)))
3589    {
3590        found = true;
3591        printf(" * Battery matched at registry = %d\n", (int32_t)battery);
3592
3593        print_raw_battery_state(battery);
3594
3595        // And install an interest notification on it
3596        IOServiceAddInterestNotification(notify, battery,
3597                            kIOGeneralInterest, log_raw_battery_interest,
3598                            NULL, &notification_ref);
3599
3600        IOObjectRelease(battery);
3601    }
3602
3603    if(!found) {
3604        printf("  (no batteries found; waiting)\n");
3605    }
3606}
3607
3608
3609static void log_raw_battery_interest(
3610    void *refcon,
3611    io_service_t batt,
3612    natural_t messageType,
3613    void *messageArgument)
3614{
3615    if(kIOPMMessageBatteryStatusHasChanged == messageType)
3616    {
3617        print_raw_battery_state((io_registry_entry_t)batt);
3618
3619    }
3620    return;
3621}
3622
3623static int log_raw_power_source_changes(void)
3624{
3625    IONotificationPortRef       notify_port = 0;
3626    io_iterator_t               battery_iter = 0;
3627    CFRunLoopSourceRef          rlser = 0;
3628    IOReturn                    ret;
3629
3630    printf("pmset is in RAW logging mode now. Hit ctrl-c to exit.\n");
3631
3632    notify_port = IONotificationPortCreate(0);
3633    rlser = IONotificationPortGetRunLoopSource(notify_port);
3634    if(!rlser) return 0;
3635    CFRunLoopAddSource(CFRunLoopGetCurrent(), rlser, kCFRunLoopDefaultMode);
3636
3637
3638    ret = IOServiceAddMatchingNotification(
3639                              notify_port,
3640                              kIOFirstMatchNotification,
3641                              IOServiceMatching("IOPMPowerSource"),
3642                              log_raw_battery_match,
3643                              (void *)&notify_port,
3644                              &battery_iter);
3645    if(KERN_SUCCESS != ret){
3646         printf("!!Error prevented matching notifications; err = 0x%08x\n", ret);
3647    }
3648
3649    // Install notifications on existing instances.
3650    log_raw_battery_match((void *)&notify_port, battery_iter);
3651
3652    CFRunLoopRun();
3653
3654    // should never return from CFRunLoopRun
3655    return 0;
3656}
3657
3658
3659static void show_systempower_notify(void)
3660{
3661    IOPMCapabilityBits b;
3662    char stateDescriptionStr[100];
3663
3664    b = IOPMConnectionGetSystemCapabilities();
3665
3666    IOPMGetCapabilitiesDescription(stateDescriptionStr, sizeof(stateDescriptionStr), b);
3667
3668    print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3669    printf("com.apple.powermanagement.systempowerstate=%s\n", stateDescriptionStr);
3670
3671    return;
3672}
3673
3674static void install_listen_for_notify_system_power(void)
3675{
3676    uint32_t        status;
3677    int             token;
3678
3679    printf("Logging: com.apple.powermanagement.systempowerstate\n");
3680
3681    status = notify_register_dispatch(
3682            kIOSystemLoadAdvisoryNotifyName,
3683            &token,
3684            dispatch_get_main_queue(),
3685            ^(int t) {
3686               show_systempower_notify();
3687             });
3688
3689    if (NOTIFY_STATUS_OK != status) {
3690        fprintf(stderr, "Registration failed for \"%s\" with (%u)\n",
3691                        kIOPMSystemPowerStateNotify, status);
3692    }
3693
3694}
3695
3696/*************************************************************************/
3697
3698void myPMConnectionHandler(
3699    void *param,
3700    IOPMConnection                      connection,
3701    IOPMConnectionMessageToken          token,
3702    IOPMSystemPowerStateCapabilities    capabilities)
3703{
3704#if TARGET_OS_EMBEDDED
3705    return;
3706#else
3707    char                        stateDescriptionStr[100];
3708    IOReturn                    ret;
3709    const                       char *earlyStr;
3710
3711    printf("\n");
3712    print_pretty_date(CFAbsoluteTimeGetCurrent(), true);
3713    IOPMGetCapabilitiesDescription(stateDescriptionStr, sizeof(stateDescriptionStr), (uint64_t)capabilities);
3714
3715    if (kIOPMEarlyWakeNotification & capabilities) {
3716        earlyStr = "(Early)";
3717    } else {
3718        earlyStr = "";
3719    }
3720
3721    printf("PMConnection: %s%s caps:0x%x\n", stateDescriptionStr, earlyStr, capabilities);
3722
3723    IOPMSystemPowerStateCapabilities    fromAPI = IOPMConnectionGetSystemCapabilities();
3724    if (capabilities != fromAPI)
3725    {
3726        printf("PMConnection: API IOPMConnectionGetSystemCapabilities() = 0x%04x, and differs from PMConnectionHandler Arg = 0x%04x\n", (uint32_t)fromAPI, (uint32_t)capabilities);
3727    }
3728
3729    if (!(kIOPMCapabilityCPU & capabilities))
3730    {
3731        printSleepAndWakeReasons(kJustPrintSleep);
3732    } else {
3733        printSleepAndWakeReasons(kJustPrintWake);
3734    }
3735
3736    ret = IOPMConnectionAcknowledgeEvent(connection, token);
3737    if (kIOReturnSuccess != ret)
3738    {
3739        printf("\t-> PM Connection acknowledgement error 0x%08x\n", ret);
3740    }
3741#endif /* TARGET_OS_EMBEDDED */
3742}
3743
3744static void install_listen_PM_connection(void)
3745{
3746#if TARGET_OS_EMBEDDED
3747    return;
3748#else
3749    IOPMConnection      myConnection;
3750    IOReturn            ret;
3751
3752    printf("Logging IOPMConnection\n");
3753
3754    ret = IOPMConnectionCreate(
3755                        CFSTR("SleepWakeLogTool"),
3756                        kIOPMEarlyWakeNotification
3757                            | kIOPMCapabilityCPU
3758                            | kIOPMCapabilityDisk
3759                            | kIOPMCapabilityNetwork
3760                            | kIOPMCapabilityAudio
3761                            | kIOPMCapabilityVideo
3762                            | kIOPMCapabilityPushServiceTask
3763                            | kIOPMCapabilityBackgroundTask
3764                            | kIOPMCapabilitySilentRunning
3765                            | kIOPMEarlyWakeNotification,
3766                        &myConnection);
3767
3768    if (kIOReturnSuccess != ret) {
3769        printf("IOPMConnectionCreate Create: Error 0x%08x\n", ret);
3770        return;
3771    }
3772
3773    ret = IOPMConnectionSetNotification(
3774                        myConnection, NULL,
3775                        (IOPMEventHandlerType)myPMConnectionHandler);
3776
3777    if (kIOReturnSuccess != ret) {
3778        printf("IOPMConnectionCreate SetNotification: Error 0x%08x\n", ret);
3779        return;
3780    }
3781
3782    ret = IOPMConnectionScheduleWithRunLoop(
3783                        myConnection, CFRunLoopGetCurrent(),
3784                        kCFRunLoopDefaultMode);
3785
3786    if (kIOReturnSuccess != ret) {
3787        printf("IOPMConnection ScheduleWithRunloop: Error 0x%08x\n", ret);
3788        return;
3789    }
3790#endif /* TARGET_OS_EMBEDDED */
3791}
3792
3793static void install_listen_com_apple_powermanagement_sleepservices_notify(void)
3794{
3795    int     token;
3796    int     status;
3797
3798    status = notify_register_dispatch(kIOPMSleepServiceActiveNotifyName, &token, dispatch_get_main_queue(),
3799                                      ^(int t) {
3800                                          if (IOPMGetSleepServicesActive()) {
3801                                              printf("SleepServices are: ON\n");
3802                                          } else {
3803                                              printf("SleepServices are: OFF\n");
3804                                          }
3805                                      });
3806
3807
3808    if (NOTIFY_STATUS_OK != status) {
3809        fprintf(stderr, "Registration failed for \"%s\" with (%u)\n",
3810                kIOPMSleepServiceActiveNotifyName, status);
3811    }
3812
3813    if (IOPMGetSleepServicesActive()) {
3814        printf("SleepServices are: ON\n");
3815    } else {
3816        printf("SleepServices are: OFF\n");
3817    }
3818}
3819
3820static void install_listen_IORegisterForSystemPower(void)
3821{
3822    io_object_t                 root_notifier = MACH_PORT_NULL;
3823    IONotificationPortRef       notify = NULL;
3824
3825    printf("Logging IORegisterForSystemPower sleep/wake messages\n");
3826
3827    /* Log sleep/wake messages */
3828    gPMAckPort = IORegisterForSystemPower (
3829                        (void *)kLogSleepEvents, &notify,
3830                        sleepWakeCallback, &root_notifier);
3831
3832   if( notify && (MACH_PORT_NULL != gPMAckPort) )
3833   {
3834        CFRunLoopAddSource(CFRunLoopGetCurrent(),
3835                    IONotificationPortGetRunLoopSource(notify),
3836                    kCFRunLoopDefaultMode);
3837    }
3838
3839    return;
3840}
3841
3842static void pmPrefsCallBack(void *context)
3843{
3844    print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3845    printf("Prefs updated\n");
3846    return;
3847}
3848
3849
3850static void listen_for_everything(void)
3851{
3852    install_listen_for_power_sources(kApplyToBattery | kApplyToUPS);
3853    install_listen_for_notify_system_power();
3854    install_listen_PM_connection();
3855    install_listen_IORegisterForSystemPower();
3856    install_listen_com_apple_powermanagement_sleepservices_notify();
3857
3858    CFRunLoopSourceRef  prefsSrc = NULL;
3859    prefsSrc = IOPMPrefsNotificationCreateRunLoopSource(pmPrefsCallBack, NULL);
3860    if (prefsSrc) {
3861        CFRunLoopAddSource(CFRunLoopGetCurrent(), prefsSrc, kCFRunLoopDefaultMode);
3862    }
3863
3864    CFRunLoopRun();
3865    // should never return from CFRunLoopRun
3866}
3867
3868static void log_thermal_events(void)
3869{
3870    int             powerConstraintNotifyToken = 0;
3871    int             cpuPowerNotifyToken = 0;
3872
3873    uint32_t        status;
3874
3875
3876    status = notify_register_dispatch(
3877            kIOPMCPUPowerNotificationKey,
3878            &cpuPowerNotifyToken,
3879            dispatch_get_main_queue(),
3880            ^(int t) {
3881                show_thermal_cpu_power_level();
3882             });
3883
3884
3885    if (NOTIFY_STATUS_OK != status) {
3886        fprintf(stderr, "Registration failed for \"%s\" with (%u)\n",
3887                        kIOPMCPUPowerNotificationKey, status);
3888    }
3889
3890
3891    status = notify_register_dispatch(
3892            kIOPMThermalWarningNotificationKey,
3893            &powerConstraintNotifyToken,
3894            dispatch_get_main_queue(),
3895            ^(int t) {
3896                show_thermal_warning_level();
3897             });
3898
3899
3900    if (NOTIFY_STATUS_OK != status)
3901    {
3902        fprintf(stderr, "Registration failed for \"%s\" with (%u)\n",
3903                        kIOPMThermalWarningNotificationKey, status);
3904    }
3905
3906    show_thermal_warning_level();
3907    show_thermal_cpu_power_level();
3908
3909    dispatch_main();
3910}
3911
3912
3913static void show_thermal_warning_level(void)
3914{
3915    uint32_t                warn = -1;
3916    IOReturn                ret;
3917
3918    ret = IOPMGetThermalWarningLevel(&warn);
3919
3920    if (kIOReturnNotFound == ret) {
3921        printf("Note: No thermal warning level has been recorded\n");
3922        return;
3923    }
3924
3925    if (kIOReturnSuccess != ret)
3926    {
3927        printf("Error: No thermal warning level with error code 0x%08x\n", ret);
3928        return;
3929    }
3930
3931    // successfully found warning level
3932    print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3933    printf("Thermal Warning Level = %d\n", warn);
3934    return;
3935}
3936
3937
3938static void show_thermal_cpu_power_level(void)
3939{
3940    CFDictionaryRef         cpuStatus;
3941    CFStringRef             *keys = NULL;
3942    CFNumberRef             *vals = NULL;
3943    CFIndex                 count = 0;
3944    int                     i;
3945    IOReturn                ret;
3946
3947    ret = IOPMCopyCPUPowerStatus(&cpuStatus);
3948
3949    if (kIOReturnNotFound == ret) {
3950        printf("Note: No CPU power status has been recorded\n");
3951        return;
3952    }
3953
3954    if (!cpuStatus || (kIOReturnSuccess != ret))
3955    {
3956        printf("Error: No CPU power status with error code 0x%08x\n", ret);
3957        return;
3958    }
3959
3960    print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
3961    fprintf(stderr, "CPU Power notify\n"), fflush(stderr);
3962
3963    count = CFDictionaryGetCount(cpuStatus);
3964    keys = (CFStringRef *)malloc(count*sizeof(CFStringRef));
3965    vals = (CFNumberRef *)malloc(count*sizeof(CFNumberRef));
3966    if (!keys||!vals)
3967        goto exit;
3968
3969    CFDictionaryGetKeysAndValues(cpuStatus,
3970                    (const void **)keys, (const void **)vals);
3971
3972    for(i=0; i<count; i++) {
3973        char strbuf[125];
3974        int  valint;
3975
3976        CFStringGetCString(keys[i], strbuf, 125, kCFStringEncodingUTF8);
3977        CFNumberGetValue(vals[i], kCFNumberIntType, &valint);
3978        printf("\t%s \t= %d\n", strbuf, valint);
3979    }
3980
3981
3982exit:
3983    if (keys)
3984        free(keys);
3985    if (vals)
3986        free(vals);
3987    if (cpuStatus)
3988        CFRelease(cpuStatus);
3989
3990}
3991
3992static void show_power_adapter(void)
3993{
3994    CFDictionaryRef     acInfo = NULL;
3995    CFNumberRef         valNum = NULL;
3996    int                 val;
3997
3998    acInfo = IOPSCopyExternalPowerAdapterDetails();
3999    if (!acInfo) {
4000        printf("No adapter attached.\n");
4001        return;
4002    }
4003
4004    valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterWattsKey));
4005    if (valNum) {
4006        CFNumberGetValue(valNum, kCFNumberIntType, &val);
4007        printf(" Wattage = %dW\n", val);
4008    }
4009
4010    valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterSourceKey));
4011    if (valNum) {
4012        // New format
4013        CFNumberGetValue(valNum, kCFNumberIntType, &val);
4014        printf(" SourceID = 0x%04x\n", val);
4015
4016        valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterCurrentKey));
4017        if (valNum) {
4018            CFNumberGetValue(valNum, kCFNumberIntType, &val);
4019            printf(" Current = %dmA\n", val);
4020        }
4021
4022        if ((valNum = CFDictionaryGetValue(acInfo, CFSTR("Voltage")))) {
4023            CFNumberGetValue(valNum, kCFNumberIntType, &val);
4024            printf(" Voltage = %dmW\n", val);
4025        }
4026    }
4027    else {
4028        valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterRevisionKey));
4029        if (valNum) {
4030            CFNumberGetValue(valNum, kCFNumberIntType, &val);
4031            printf(" Revision = 0x%04x\n", val);
4032        }
4033    }
4034
4035    // Legacy format
4036    valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterIDKey));
4037    if (valNum) {
4038        CFNumberGetValue(valNum, kCFNumberIntType, &val);
4039        printf(" AdapterID = 0x%04x\n", val);
4040    }
4041
4042    valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterFamilyKey));
4043    if (valNum) {
4044        CFNumberGetValue(valNum, kCFNumberIntType, &val);
4045        printf(" Family Code = 0x%04x\n", val);
4046    }
4047
4048    valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterSerialNumberKey));
4049    if (valNum) {
4050        CFNumberGetValue(valNum, kCFNumberIntType, &val);
4051        printf(" Serial Number = 0x%08x\n", val);
4052    }
4053    CFRelease(acInfo);
4054}
4055
4056
4057/******************************************************************************/
4058/*                                                                            */
4059/*     BORING SETTINGS & PARSING                                              */
4060/*                                                                            */
4061/******************************************************************************/
4062
4063
4064static int checkAndSetIntValue(
4065    char *valstr,
4066    CFStringRef settingKey,
4067    int apply,
4068    int isOnOffSetting,
4069    int multiplier,
4070    CFMutableDictionaryRef ac,
4071    CFMutableDictionaryRef batt,
4072    CFMutableDictionaryRef ups)
4073{
4074    CFNumberRef     cfnum;
4075    char            *endptr = NULL;
4076    long            val;
4077    int32_t         val32;
4078
4079    if(!valstr) return -1;
4080
4081    val = strtol(valstr, &endptr, 0);
4082
4083    if(0 != *endptr)
4084    {
4085        // the string contained some non-numerical characters - bail
4086        return -1;
4087    }
4088
4089    // for on/off settings, turn any non-zero number into a 1
4090    if(isOnOffSetting) {
4091        val = (val?1:0);
4092    } else {
4093        // Numerical values may have multipliers (i.e. x1000 for sec -> msec)
4094        if(0 != multiplier) val *= multiplier;
4095    }
4096    // negative number? reject it
4097    if(val < 0) return -1;
4098
4099    val32 = (int32_t)val;
4100    cfnum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &val32);
4101    if(!cfnum) return -1;
4102    if(apply & kApplyToBattery)
4103        CFDictionarySetValue(batt, settingKey, cfnum);
4104    if(apply & kApplyToCharger)
4105        CFDictionarySetValue(ac, settingKey, cfnum);
4106    if(apply & kApplyToUPS)
4107        CFDictionarySetValue(ups, settingKey, cfnum);
4108    CFRelease(cfnum);
4109    return 0;
4110}
4111
4112static int checkAndSetStrValue(char *valstr, CFStringRef settingKey, int apply,
4113                CFMutableDictionaryRef ac, CFMutableDictionaryRef batt, CFMutableDictionaryRef ups)
4114{
4115    CFStringRef     cfstr;
4116
4117    if(!valstr) return -1;
4118
4119    cfstr = CFStringCreateWithCString(kCFAllocatorDefault,
4120                        valstr, kCFStringEncodingMacRoman);
4121    if(!cfstr) return -1;
4122    if(apply & kApplyToBattery)
4123        CFDictionarySetValue(batt, settingKey, cfstr);
4124    if(apply & kApplyToCharger)
4125        CFDictionarySetValue(ac, settingKey, cfstr);
4126    if(apply & kApplyToUPS)
4127        CFDictionarySetValue(ups, settingKey, cfstr);
4128    CFRelease(cfstr);
4129    return 0;
4130}
4131
4132
4133static int setUPSValue(char *valstr,
4134    CFStringRef    whichUPS,
4135    CFStringRef settingKey,
4136    int apply,
4137    CFMutableDictionaryRef thresholds)
4138{
4139    CFMutableDictionaryRef ups_setting = NULL;
4140    CFDictionaryRef     tmp_ups_setting = NULL;
4141    CFNumberRef     cfnum = NULL;
4142    CFBooleanRef    on_off = kCFBooleanTrue;
4143    char            *endptr = NULL;
4144    long            val;
4145    int32_t         val32;
4146
4147    if(!valstr) return -1;
4148
4149    val = strtol(valstr, &endptr, 10);
4150
4151    if(0 != *endptr)
4152    {
4153        // the string contained some non-numerical characters - bail
4154        return -1;
4155    }
4156
4157    if(-1 == val)
4158    {
4159        on_off = kCFBooleanFalse;
4160    }
4161
4162    // negative number? reject it
4163    if(val < 0) val = 0;
4164
4165    // if this should be a percentage, cap the value at 100%
4166    if(kCFCompareEqualTo == CFStringCompare(settingKey, CFSTR(kIOUPSShutdownAtLevelKey), 0))
4167    {
4168        if(val > 100) val = 100;
4169    };
4170
4171    // bail if -u or -a hasn't been specified:
4172    if(!(apply & kApplyToUPS)) return -1;
4173
4174    // Create the nested dictionaries of UPS settings
4175    tmp_ups_setting = CFDictionaryGetValue(thresholds, settingKey);
4176    ups_setting = CFDictionaryCreateMutableCopy(0, 0, tmp_ups_setting);
4177    if(!ups_setting)
4178    {
4179        ups_setting = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
4180            &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
4181    }
4182
4183    val32 = (int32_t)val;
4184    cfnum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &val32);
4185
4186    if(kCFBooleanFalse == on_off) {
4187        // If user is turning this setting off, then preserve the existing value in there.
4188        // via CFDictionaryAddValue
4189        CFDictionaryAddValue(ups_setting, CFSTR(kIOUPSShutdownLevelValueKey), cfnum);
4190    } else {
4191        // If user is providing a new value for this setting, overwrite the existing value.
4192        CFDictionarySetValue(ups_setting, CFSTR(kIOUPSShutdownLevelValueKey), cfnum);
4193    }
4194    CFRelease(cfnum);
4195    CFDictionarySetValue(ups_setting, CFSTR(kIOUPSShutdownLevelEnabledKey), on_off);
4196
4197    CFDictionarySetValue(thresholds, settingKey, ups_setting);
4198    CFRelease(ups_setting);
4199    return 0;
4200}
4201
4202
4203//  pmset repeat cancel
4204//  pmset repeat <type> <days of week> <time> [<type> <days of week> <time>]\n");
4205static int parseRepeatingEvent(
4206    char                        **argv,
4207    int                         *num_args_parsed,
4208    CFMutableDictionaryRef      local_repeating_event,
4209    bool                        *local_cancel_repeating)
4210{
4211    CFDateFormatterRef          formatter = 0;
4212    CFTimeZoneRef               tz = 0;
4213    CFStringRef                 cf_str_date = 0;
4214    int                         i = 0;
4215    int                         j = 0;
4216    size_t                      str_len = 0;
4217    int                         days_mask = 0;
4218    int                         on_off = 0;
4219    IOReturn                    ret = kParseInternalError;
4220
4221    CFStringRef                 the_type = 0;
4222    CFNumberRef                 the_days = 0;
4223    CFDateRef                   cf_date = 0;
4224    int                         event_time = 0;
4225    CFNumberRef                 the_time = 0;       // in minutes from midnight
4226    CFMutableDictionaryRef      one_repeating_event = 0;
4227
4228    formatter = CFDateFormatterCreate(kCFAllocatorDefault, CFLocaleGetSystem(),
4229        kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle);
4230    if(!formatter) {
4231        ret = kParseInternalError;
4232        goto exit;
4233    }
4234    tz = CFTimeZoneCopySystem();
4235    if(!tz) {
4236        ret = kParseInternalError;
4237        goto exit;
4238    }
4239    CFDateFormatterSetFormat(formatter, CFSTR(kTimeFormat));
4240    if(!argv[i]) {
4241        ret = kParseBadArgs;
4242        goto exit;
4243    }
4244    // cancel ALL repeating events
4245    if(0 == strcmp(argv[i], ARG_CANCEL) ) {
4246
4247        *local_cancel_repeating = true;
4248        i++;
4249        ret = kParseSuccess;
4250        goto exit;
4251    }
4252
4253    while(argv[i])
4254    {
4255        string_tolower(argv[i], argv[i]);
4256
4257        // type
4258        if(0 == strcmp(argv[i], ARG_SLEEP))
4259        {
4260            on_off = 0;
4261            the_type = CFSTR(kIOPMAutoSleep);
4262        } else if(0 == strcmp(argv[i], ARG_SHUTDOWN))
4263        {
4264            on_off = 0;
4265            the_type =  CFSTR(kIOPMAutoShutdown);
4266        } else if(0 == strcmp(argv[i], ARG_RESTART))
4267        {
4268            on_off = 0;
4269            the_type =  CFSTR(kIOPMAutoRestart);
4270        } else if(0 == strcmp(argv[i], ARG_WAKE))
4271        {
4272            on_off = 1;
4273            the_type =  CFSTR(kIOPMAutoWake);
4274        } else if(0 == strcmp(argv[i], ARG_POWERON))
4275        {
4276            on_off = 1;
4277            the_type =  CFSTR(kIOPMAutoPowerOn);
4278        } else if(0 == strcmp(argv[i], ARG_WAKEORPOWERON))
4279        {
4280            on_off = 1;
4281            the_type =  CFSTR(kIOPMAutoWakeOrPowerOn);
4282        } else {
4283            printf("Error: Unspecified scheduled event type\n");
4284            ret = kParseBadArgs;
4285            goto bail;
4286        }
4287
4288        i++;
4289
4290        // days of week
4291        // Expect argv[i] to be a NULL terminated string with a subset of: MTWRFSU
4292        // indicating the days of the week to schedule repeating wakeup
4293        // TODO: accept M-F style ranges
4294        if (!argv[i] || !argv[i+1]) {
4295            ret = kParseBadArgs;
4296            goto bail;
4297        }
4298
4299        string_tolower(argv[i], argv[i]);
4300
4301		days_mask = 0;
4302        str_len = strlen(argv[i]);
4303        for(j=0; j<str_len; j++)
4304        {
4305            if('m' == argv[i][j]) {
4306                days_mask |= kIOPMMonday;
4307            } else if('t' == argv[i][j]) {
4308                days_mask |= kIOPMTuesday;
4309            } else if('w' == argv[i][j]) {
4310                days_mask |= kIOPMWednesday;
4311            } else if('r' == argv[i][j]) {
4312                days_mask |= kIOPMThursday;
4313            } else if('f' == argv[i][j]) {
4314                days_mask |= kIOPMFriday;
4315            } else if('s' == argv[i][j]) {
4316                days_mask |= kIOPMSaturday;
4317            } else if('u' == argv[i][j]) {
4318                days_mask |= kIOPMSunday;
4319            }
4320        }
4321        if(0 == days_mask) {
4322            // something went awry; we expect a non-zero days mask.
4323            ret = kParseBadArgs;
4324            goto bail;
4325        }
4326
4327        i++;
4328        string_tolower(argv[i], argv[i]);
4329
4330        cf_str_date = CFStringCreateWithCString(kCFAllocatorDefault,
4331                        argv[i], kCFStringEncodingMacRoman);
4332        if (!cf_str_date) {
4333            ret = kParseInternalError;
4334            goto bail;
4335        }
4336        cf_date = CFDateFormatterCreateDateFromString(0, formatter, cf_str_date, 0);
4337        CFRelease(cf_str_date);
4338        if (!cf_date) {
4339            ret = kParseBadArgs;
4340            goto bail;
4341        }
4342
4343        int hour, minute;
4344        CFCalendarDecomposeAbsoluteTime(_gregorian(),
4345                CFDateGetAbsoluteTime(cf_date), "Hm", &hour, &minute);
4346        event_time = hour*60 + minute;
4347        the_time = CFNumberCreate(0, kCFNumberIntType, &event_time);
4348
4349        i++;
4350
4351        the_days = CFNumberCreate(0, kCFNumberIntType, &days_mask);
4352
4353        // check for existence of the_days, the_time, the_type
4354        // if this was a validly formatted dictionary, pack the repeating dict appropriately.
4355        if( isA_CFNumber(the_days) && isA_CFString(the_type) && isA_CFNumber(the_time) )
4356        {
4357            one_repeating_event = CFDictionaryCreateMutable(0, 0,
4358                &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
4359            if(one_repeating_event)
4360            {
4361                CFDictionarySetValue(one_repeating_event, CFSTR(kIOPMPowerEventTypeKey), the_type);
4362                CFDictionarySetValue(one_repeating_event, CFSTR(kIOPMDaysOfWeekKey), the_days);
4363                CFDictionarySetValue(one_repeating_event, CFSTR(kIOPMPowerEventTimeKey), the_time);
4364
4365                CFDictionarySetValue(local_repeating_event,
4366                     (on_off ? CFSTR(kIOPMRepeatingPowerOnKey):CFSTR(kIOPMRepeatingPowerOffKey)),
4367                                    one_repeating_event);
4368                CFRelease(one_repeating_event);
4369            }
4370        }
4371        if (the_days)
4372            CFRelease(the_days);
4373        if (the_time)
4374            CFRelease(the_time);
4375        if (cf_date)
4376            CFRelease(cf_date);
4377
4378    } // while loop
4379
4380    ret = kParseSuccess;
4381    goto exit;
4382
4383bail:
4384    fprintf(stderr, "Error: badly formatted repeating power event\n");
4385    fflush(stderr);
4386
4387exit:
4388    if (the_type)
4389        CFRelease(the_type);
4390    if(num_args_parsed)
4391        *num_args_parsed = i;
4392    if(tz)
4393        CFRelease(tz);
4394    if(formatter)
4395        CFRelease(formatter);
4396    return ret;
4397}
4398
4399
4400// pmset sched wake "4/27/04 1:00:00 PM" "Ethan Bold"
4401// pmset sched cancel sleep "4/27/04 1:00:00 PM" "MyAlarmClock"
4402// pmset sched cancel shutdown "4/27/04 1:00:00 PM"
4403static int parseScheduledEvent(
4404    char                        **argv,
4405    int                         *num_args_parsed,
4406    ScheduledEventReturnType    *local_scheduled_event,
4407    bool                        *cancel_scheduled_event,
4408    bool                        is_relative_event)
4409{
4410    CFDateFormatterRef          formatter = 0;
4411    CFStringRef                 cf_str_date = 0;
4412    int                         i = 0;
4413    IOReturn                    ret = kParseInternalError;
4414
4415    formatter = CFDateFormatterCreate(kCFAllocatorDefault, CFLocaleGetSystem(),
4416        kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle);
4417    if(!formatter)
4418        return kParseInternalError;
4419
4420    *num_args_parsed = 0;
4421
4422    // We manually set the format (as recommended by header comments)
4423    // to ensure it doesn't vary from release to release or from locale
4424    // to locale.
4425    CFDateFormatterSetFormat(formatter, CFSTR(kDateAndTimeFormat));
4426    if(!argv[i]) {
4427        ret = kParseInternalError;
4428        goto exit;
4429    }
4430
4431    string_tolower(argv[i], argv[i]);
4432
4433    // cancel
4434    if(!is_relative_event && (0 == strcmp(argv[i], ARG_CANCEL))) {
4435        char            *endptr = NULL;
4436        long            val;
4437        CFArrayRef      all_events = 0;
4438        CFDictionaryRef the_event = 0;
4439
4440        *cancel_scheduled_event = true;
4441        i++;
4442
4443        // See if the next field is an integer. If so, we cancel the event
4444        // indicated by the indices printed in "pmset -g sched"
4445        // If not, parse out the rest of the entry for a full-description
4446        // of the event to cancel.
4447        if(!argv[i]) {
4448            ret = kParseBadArgs;
4449            goto exit;
4450        }
4451
4452        val = strtol(argv[i], &endptr, 10);
4453
4454        if(0 == *endptr)
4455        {
4456            all_events = IOPMCopyScheduledPowerEvents();
4457            if(!all_events) {
4458                ret = kParseInternalError;
4459                goto exit;
4460            }
4461            if(val >= 0 && val < CFArrayGetCount(all_events)) {
4462
4463                // the string was indeed a number
4464                the_event = isA_CFDictionary(CFArrayGetValueAtIndex(all_events, val));
4465                if(!the_event) {
4466                        ret = kParseInternalError;
4467                } else {
4468                    local_scheduled_event->when = CFRetain(
4469                        CFDictionaryGetValue(the_event, CFSTR(kIOPMPowerEventTimeKey)));
4470                    local_scheduled_event->who = CFRetain(
4471                        CFDictionaryGetValue(the_event, CFSTR(kIOPMPowerEventAppNameKey)));
4472                    local_scheduled_event->which = CFRetain(
4473                        CFDictionaryGetValue(the_event, CFSTR(kIOPMPowerEventTypeKey)));
4474                    ret = kParseSuccess;
4475                }
4476
4477                i++;
4478            } else {
4479                ret = kParseBadArgs;
4480            }
4481
4482            CFRelease(all_events);
4483            goto exit;
4484        }
4485    }
4486
4487    string_tolower(argv[i], argv[i]);
4488
4489    // type
4490    if(0 == strcmp(argv[i], ARG_SLEEP))
4491    {
4492        local_scheduled_event->which = (!is_relative_event) ?
4493            CFStringCreateWithCString(0, kIOPMAutoSleep, kCFStringEncodingMacRoman) : 0;
4494        i++;
4495    } else if(0 == strcmp(argv[i], ARG_SHUTDOWN))
4496    {
4497        local_scheduled_event->which = (!is_relative_event) ?
4498            CFStringCreateWithCString(0, kIOPMAutoShutdown, kCFStringEncodingMacRoman) : 0;
4499        i++;
4500    } else if(0 == strcmp(argv[i], ARG_RESTART))
4501    {
4502        local_scheduled_event->which = (!is_relative_event) ?
4503            CFStringCreateWithCString(0, kIOPMAutoRestart, kCFStringEncodingMacRoman) : 0;
4504        i++;
4505    } else if(0 == strcmp(argv[i], ARG_WAKE))
4506    {
4507        local_scheduled_event->which = (!is_relative_event) ?
4508            CFStringCreateWithCString(0, kIOPMAutoWake, kCFStringEncodingMacRoman) :
4509            CFStringCreateWithCString(0, kIOPMAutoWakeRelativeSeconds, kCFStringEncodingMacRoman);
4510        i++;
4511    } else if(0 == strcmp(argv[i], ARG_POWERON))
4512    {
4513        local_scheduled_event->which = (!is_relative_event) ?
4514            CFStringCreateWithCString(0, kIOPMAutoPowerOn, kCFStringEncodingMacRoman) : 0;
4515        i++;
4516    } else if(0 == strcmp(argv[i], ARG_WAKEORPOWERON))
4517    {
4518        local_scheduled_event->which = (!is_relative_event) ?
4519            CFStringCreateWithCString(0, kIOPMAutoWakeOrPowerOn, kCFStringEncodingMacRoman) : 0;
4520        i++;
4521    } else {
4522        printf("Error: Unspecified scheduled event type\n");
4523        ret = kParseBadArgs;
4524        goto exit;
4525    }
4526
4527    if(0 == local_scheduled_event->which) {
4528        printf("Error: Unspecified scheduled event type (2)\n");
4529        ret = kParseBadArgs;
4530        goto exit;
4531    }
4532
4533    // date & time
4534    if(argv[i]) {
4535        if (is_relative_event) {
4536            char    *endptr = NULL;
4537            long    secs;
4538
4539            secs = strtol(argv[i], &endptr, 10);
4540            if ((0 != *endptr) || !secs) {
4541                ret = kParseBadArgs;
4542                goto exit;
4543            }
4544
4545            local_scheduled_event->when = CFDateCreate(0, CFAbsoluteTimeGetCurrent() + secs);
4546            i++;
4547        } else {
4548            string_tolower(argv[i], argv[i]);
4549
4550            cf_str_date = CFStringCreateWithCString(kCFAllocatorDefault,
4551                            argv[i], kCFStringEncodingMacRoman);
4552            if(!cf_str_date) {
4553                local_scheduled_event->when = NULL;
4554                ret = kParseInternalError;
4555                goto exit;
4556            }
4557            local_scheduled_event->when =
4558                CFDateFormatterCreateDateFromString(
4559                    0,
4560                    formatter,
4561                    cf_str_date,
4562                    NULL);
4563            CFRelease(cf_str_date);
4564            i++;
4565        }
4566    } else {
4567        printf("Error: Badly formatted date\n");
4568        ret = kParseBadArgs;
4569        goto exit;
4570    }
4571
4572    if(0 == local_scheduled_event->when) {
4573        printf("Error: Badly formatted date (2)\n");
4574        ret = kParseBadArgs;
4575        goto exit;
4576    }
4577
4578    // Author. Please preserve case - do not lowercase - this argument.
4579    if(argv[i]) {
4580        local_scheduled_event->who = CFStringCreateWithCString(0, argv[i], kCFStringEncodingMacRoman);
4581        i++;
4582    } else {
4583        local_scheduled_event->who = 0;
4584    }
4585
4586    ret = kParseSuccess;
4587
4588exit:
4589    if(num_args_parsed) *num_args_parsed = i;
4590
4591    if(formatter) CFRelease(formatter);
4592
4593    if (kParseSuccess != ret) {
4594        printf("Error parsing scheduled event.\n");
4595        exit(EX_SOFTWARE);
4596    }
4597
4598    return ret;
4599}
4600
4601static void string_tolower(char *lower_me, char *dst)
4602{
4603	size_t length = strlen(lower_me);
4604	int j = 0;
4605
4606	for (j=0; j<length; j++)
4607	{
4608	    dst[j] = tolower(lower_me[j]);
4609	}
4610}
4611
4612static void string_toupper(char *upper_me, char *dst)
4613{
4614	size_t length = strlen(upper_me);
4615	int j = 0;
4616
4617	for (j=0; j<length; j++)
4618	{
4619	    dst[j] = toupper(upper_me[j]);
4620	}
4621}
4622
4623/*
4624 * parseArgs - parse argv input stream into executable commands
4625 *      and returns executable commands.
4626 * INPUTS:
4627 *  int argc,
4628 *  char* argv[],
4629 * OUTPUTS:
4630 * If these pointers are specified on exit, that means parseArgs modified these settings
4631 * and they should be written out to persistent store by the caller.
4632 *  settings: Energy Saver settings
4633 *  modified_power_sources: which power sources the modified Energy Saver settings apply to
4634 *                          (only valid if settings is defined)
4635 *  active_profiles: Changes the active profile
4636 *  system_power_settings: system-wide settings, not tied to power source. like "disablesleep"
4637 *  ups_thresholds: UPS shutdown thresholds
4638 *  scheduled_event: Description of a one-time power event
4639 *  cancel_scheduled_event: true = cancel the scheduled event/false = schedule the event
4640 *                          (only valid if scheduled_event is defined)
4641 *  repeating_event: Description of a repeating power event
4642 *  cancel_repeating_event: true = cancel the repeating event/false = schedule the repeating event
4643 *                          (only valid if repeating_event is defined)
4644*/
4645
4646static int parseArgs(int argc,
4647    char* argv[],
4648    CFDictionaryRef             *settings,
4649    int                         *modified_power_sources,
4650    bool                        *force_activate_settings,
4651    CFDictionaryRef             *active_profiles,
4652    CFDictionaryRef             *system_power_settings,
4653    CFDictionaryRef             *ups_thresholds,
4654    ScheduledEventReturnType    **scheduled_event,
4655    bool                        *cancel_scheduled_event,
4656    CFDictionaryRef             *repeating_event,
4657    bool                        *cancel_repeating_event,
4658    uint32_t                    *pmCmd)
4659{
4660    int                         i = 1;
4661    int                         apply = 0;
4662    int                         ret = kParseSuccess;
4663    int                         modified = 0;
4664    IOReturn                    kr;
4665    ScheduledEventReturnType    *local_scheduled_event = 0;
4666    bool                        local_cancel_event = false;
4667    CFMutableDictionaryRef      local_repeating_event = 0;
4668    bool                        local_cancel_repeating = false;
4669    CFDictionaryRef             tmp_profiles = 0;
4670    CFMutableDictionaryRef      local_profiles = 0;
4671    CFDictionaryRef             tmp_ups_settings = 0;
4672    CFMutableDictionaryRef      local_ups_settings = 0;
4673    CFDictionaryRef             tmp_settings = 0;
4674    CFMutableDictionaryRef      local_settings = 0;
4675    CFMutableDictionaryRef      local_system_power_settings = 0;
4676    CFDictionaryRef             tmp_battery = 0;
4677    CFMutableDictionaryRef      battery = 0;
4678    CFDictionaryRef             tmp_ac = 0;
4679    CFMutableDictionaryRef      ac = 0;
4680    CFDictionaryRef             tmp_ups = 0;
4681    CFMutableDictionaryRef      ups = 0;
4682
4683    if(argc == 1) {
4684        return kParseBadArgs;
4685    }
4686
4687
4688/*
4689 * Check for any commands
4690 * Commands may not be combined with any other flags
4691 *
4692 */
4693    if(0 == strcmp(argv[1], ARG_TOUCH))
4694    {
4695        *pmCmd = kPMCommandTouch;
4696        return kIOReturnSuccess;
4697    } else if(0 == strcmp(argv[1], ARG_NOIDLE))
4698    {
4699        *pmCmd = kPMCommandNoIdle;
4700        return kIOReturnSuccess;
4701    } else if(0 == strcmp(argv[1], ARG_SLEEPNOW))
4702    {
4703        *pmCmd = kPMCommandSleepNow;
4704        return kIOReturnSuccess;
4705    } else if(0 == strcmp(argv[1], ARG_DISPLAYSLEEPNOW))
4706    {
4707        *pmCmd = kPMCommandDisplaySleepNow;
4708        return kIOReturnSuccess;
4709    } else if(0 == strcmp(argv[1], ARG_DEBUGTRIG))
4710    {
4711        *pmCmd = kPMCommandDebugTrig;
4712        return kIOReturnSuccess;
4713    } else if ((0 == strcmp(argv[1], ARG_RESETDISPLAYAMBIENTPARAMS))
4714              || (0 == strcmp(argv[1], ARG_RDAP)) )
4715    {
4716        #if PLATFORM_HAS_DISPLAYSERVICES
4717        {
4718            IOReturn ret = DisplayServicesResetAmbientLightAll();
4719
4720            if (kIOReturnSuccess == ret) {
4721                printf("Success.\n");
4722            } else if (kIOReturnNoDevice == ret) {
4723                printf("Error: No supported displays found for pmset argument \"%s\"\n", argv[1]);
4724            } else {
4725                printf("Error: Failure 0%08x setting display ambient parameters.\n", ret);
4726            }
4727        }
4728        #else
4729        {
4730            printf("Error: this command isn't supported on this platform (no DisplayServices).\n");
4731            exit (EX_UNAVAILABLE);
4732        }
4733        #endif
4734
4735        return kIOReturnSuccess;
4736    }
4737
4738
4739/***********
4740 * Setup mutable PM preferences
4741 ***********/
4742    tmp_settings = IOPMCopyActivePMPreferences();
4743    if(!tmp_settings) {
4744        ret = kParseInternalError;
4745        goto exit;
4746    }
4747    local_settings = CFDictionaryCreateMutableCopy(0, 0, tmp_settings);
4748    CFRelease(tmp_settings);
4749    if(!local_settings) {
4750        ret = kParseInternalError;
4751        goto exit;
4752    }
4753
4754    // Either battery or AC settings may not exist if the system doesn't support it.
4755    tmp_battery = isA_CFDictionary(CFDictionaryGetValue(local_settings, CFSTR(kIOPMBatteryPowerKey)));
4756    if(tmp_battery) {
4757        battery = CFDictionaryCreateMutableCopy(0, 0, tmp_battery);
4758        if(battery) {
4759            CFDictionarySetValue(local_settings, CFSTR(kIOPMBatteryPowerKey), battery);
4760            CFRelease(battery);
4761        }
4762    }
4763    tmp_ac = isA_CFDictionary(CFDictionaryGetValue(local_settings, CFSTR(kIOPMACPowerKey)));
4764    if(tmp_ac) {
4765        ac = CFDictionaryCreateMutableCopy(0, 0, tmp_ac);
4766        if(ac) {
4767            CFDictionarySetValue(local_settings, CFSTR(kIOPMACPowerKey), ac);
4768            CFRelease(ac);
4769        }
4770    }
4771    tmp_ups = isA_CFDictionary(CFDictionaryGetValue(local_settings, CFSTR(kIOPMUPSPowerKey)));
4772    if(tmp_ups) {
4773        ups = CFDictionaryCreateMutableCopy(0, 0, tmp_ups);
4774        if(ups) {
4775            CFDictionarySetValue(local_settings, CFSTR(kIOPMUPSPowerKey), ups);
4776            CFRelease(ups);
4777        }
4778    }
4779/***********
4780 * Setup mutable UPS thersholds
4781 ***********/
4782    tmp_ups_settings = IOPMCopyUPSShutdownLevels(CFSTR(kIOPMDefaultUPSThresholds));
4783    if(tmp_ups_settings) {
4784        local_ups_settings = CFDictionaryCreateMutableCopy(0, 0, tmp_ups_settings);
4785        CFRelease(tmp_ups_settings);
4786    }
4787
4788/***********
4789 * Setup mutable Active profiles
4790 ***********/
4791    tmp_profiles = IOPMCopyActivePowerProfiles();
4792    if(tmp_profiles) {
4793        local_profiles = CFDictionaryCreateMutableCopy(0, 0, tmp_profiles);
4794        CFRelease(tmp_profiles);
4795    }
4796
4797/************
4798 * Setup system power settings holder dictionary
4799 ************/
4800    local_system_power_settings = CFDictionaryCreateMutable(0, 0,
4801                                &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
4802
4803    // Unless specified, apply changes to both battery and AC
4804    if(battery) apply |= kApplyToBattery;
4805    if(ac) apply |= kApplyToCharger;
4806    if(ups) apply |= kApplyToUPS;
4807
4808    i=1;
4809    while(i < argc)
4810    {
4811		string_tolower(argv[i], argv[i]);	// in place
4812
4813        if( (argv[i][0] == '-')
4814            && ('1' != argv[i][1]) ) // don't try to process it as a abcg argument if it's a -1
4815                                     // the profiles parsing code below is expecting the -1
4816        {
4817        // Process -a/-b/-c/-g arguments
4818            apply = 0;
4819            switch (argv[i][1])
4820            {
4821                case 'a':
4822                    if(battery) apply |= kApplyToBattery;
4823                    if(ac) apply |= kApplyToCharger;
4824                    if(ups) apply |= kApplyToUPS;
4825                    break;
4826                case 'b':
4827                    if(battery) apply = kApplyToBattery;
4828                    break;
4829                case 'c':
4830                    if(ac) apply = kApplyToCharger;
4831                    break;
4832                case 'u':
4833                    if(ups) apply = kApplyToUPS;
4834                    break;
4835                case 'g':
4836                    // One of the "getters"
4837                    if('\0' != argv[i][2]) {
4838                        ret = kParseBadArgs;
4839                        goto exit;
4840                    }
4841                    i++;
4842
4843                    const char *canonical_arg = getCanonicalArgForSynonym(argv[i]);
4844                    if (!canonical_arg) {
4845                        printf("Error: invalid argument %s\n", argv[i]);
4846                        ret = kParseBadArgs;
4847                        goto exit;
4848                    }
4849
4850                    int getter_iterator;
4851                    bool handled_getter_arg = false;
4852                    for (getter_iterator=0; getter_iterator<the_getters_count; getter_iterator++)
4853                    {
4854                        if (!strncmp(the_getters[getter_iterator].arg, canonical_arg, kMaxArgStringLength))
4855                        {
4856                            the_getters[getter_iterator].action(&argv[i+1]);
4857                            handled_getter_arg = true;
4858                            break;
4859                        }
4860                    }
4861                    if (!handled_getter_arg)
4862                    {
4863                        printf("Error: unhandled argument %s\n", argv[i]);
4864                        ret = kParseBadArgs;
4865                        goto exit;
4866                    }
4867
4868                    // return immediately - don't handle any more setting arguments
4869                    ret = kParseSuccess;
4870                    goto exit;
4871                    break;
4872                default:
4873                    // bad!
4874                    ret = kParseBadArgs;
4875                    goto exit;
4876                    break;
4877            }
4878
4879            i++;
4880        } else if( (0 == strncmp(argv[i], ARG_SCHEDULE, kMaxArgStringLength))
4881                || (0 == strncmp(argv[i], ARG_SCHED, kMaxArgStringLength)) )
4882        {
4883            // Process rest of input as a cancel/schedule power event
4884            int args_parsed;
4885
4886            local_scheduled_event = scheduled_event_struct_create();
4887            if(!local_scheduled_event) {
4888                ret = kParseInternalError;
4889                goto exit;
4890            }
4891            i += 1;
4892            ret = parseScheduledEvent(
4893                            &(argv[i]),
4894                            &args_parsed,
4895                            local_scheduled_event,
4896                            &local_cancel_event,
4897                            false);
4898            if(kParseSuccess != ret)
4899            {
4900                printf("Error - invalid scheduled event.\n");
4901                goto exit;
4902            }
4903
4904            i += args_parsed;
4905            modified |= kModSched;
4906        } else if(0 == strncmp(argv[i], ARG_RELATIVE, kMaxArgStringLength))
4907        {
4908            // Process rest of input as a relative power event
4909            int args_parsed;
4910
4911            local_scheduled_event = scheduled_event_struct_create();
4912            if(!local_scheduled_event) {
4913                ret = kParseInternalError;
4914                goto exit;
4915            }
4916            i += 1;
4917            ret = parseScheduledEvent(
4918                            &(argv[i]),
4919                            &args_parsed,
4920                            local_scheduled_event,
4921                            &local_cancel_event,
4922                            true);
4923            if(kParseSuccess != ret)
4924            {
4925                printf("Error - invalid scheduled event.\n");
4926                goto exit;
4927            }
4928
4929            i += args_parsed;
4930            modified |= kModSched;
4931        } else if(0 == strncmp(argv[i], ARG_REPEAT, kMaxArgStringLength))
4932        {
4933            int args_parsed;
4934
4935            local_repeating_event = CFDictionaryCreateMutable(0, 0,
4936                &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
4937            if(!local_repeating_event) {
4938                ret = kParseInternalError;
4939                goto exit;
4940            }
4941            i+=1;
4942            ret = parseRepeatingEvent(
4943                            &(argv[i]),
4944                            &args_parsed,
4945                            local_repeating_event,
4946                            &local_cancel_repeating);
4947
4948            if(kParseSuccess == ret)
4949            {
4950                modified |= kModRepeat;
4951            } else {
4952                ret = kParseBadArgs;
4953            }
4954            goto exit;
4955        } else
4956        {
4957        // Process the settings
4958          if(!strncmp(argv[i], ARG_BOOKMARK, kMaxArgStringLength))
4959          {
4960            set_new_power_bookmark();
4961            goto exit;
4962          } else if(0 == strncmp(argv[i], ARG_DEBUGFLAGS, kMaxArgStringLength))
4963          {
4964             if (argv[i+1])
4965                set_debugFlags(&argv[i+1]);
4966              else
4967                  printf("Error: You need to specify debug flags value\n");
4968              goto exit;
4969          } else if(0 == strncmp(argv[i], ARG_BTINTERVAL, kMaxArgStringLength))
4970          {
4971              if(argv[i+1])
4972                set_btInterval(&argv[i+1]);
4973              else
4974                  printf("Error: You need to specify an interval in seconds\n");
4975              goto exit;
4976          } else if(0 == strncmp(argv[i], ARG_DWLINTERVAL, kMaxArgStringLength))
4977          {
4978              if(argv[i+1])
4979                  set_dwlInterval(&argv[i+1]);
4980              else
4981                  printf("Error: You need to specify an interval in seconds\n");
4982              goto exit;
4983          } else if(0 == strncmp(argv[i], ARG_DISABLEASSERTION, kMaxArgStringLength))
4984          {
4985              if(argc <= 2) {
4986                  printf("Error: Assertion type to disable is missing\n");
4987                  goto exit;
4988              }
4989              kr = IOPMCtlAssertionType(argv[i+1], kIOPMDisableAssertionType);
4990              if (kr == kIOReturnNotPrivileged)
4991                  printf("\'%s\' must be run as root to disable assertions\n", argv[0]);
4992              else if (kr != kIOReturnSuccess)
4993                  printf("Failed to disable assertions with err code 0x%x\n", kr);
4994              goto exit;
4995          } else if(0 == strncmp(argv[i], ARG_ENABLEASSERTION, kMaxArgStringLength))
4996          {
4997              if(argc <= 2) {
4998                  printf("Error: Assertion type to enable is missing\n");
4999                  goto exit;
5000              }
5001              kr = IOPMCtlAssertionType(argv[i+1], kIOPMEnableAssertionType);
5002              if (kr == kIOReturnNotPrivileged)
5003                  printf("\'%s\' must be run as root to enable assertions\n", argv[0]);
5004              else if (kr != kIOReturnSuccess)
5005                  printf("Failed to enable assertions with err code 0x%x\n", kr);
5006              goto exit;
5007
5008          } else if (0 == strncmp(argv[i], ARG_MT2BOOK, kMaxArgStringLength))
5009          {
5010              mt2bookmark();
5011              goto exit;
5012          } else if (0 == strncmp(argv[i], ARG_SETSAAFLAGS, kMaxArgStringLength))
5013          {
5014              if(argv[i+1])
5015                set_saaFlags(&argv[i+1]);
5016              else
5017                  printf("Error: You need to specify an integer flag value\n");
5018              goto exit;
5019          } else if (0 == strncmp(argv[i], ARG_NOPOLL, kMaxArgStringLength))
5020          {
5021              set_nopoll();
5022              goto exit;
5023         } else if(0 == strncmp(argv[i], ARG_BOOT, kMaxArgStringLength))
5024          {
5025              // Tell kernel power management that bootup is complete
5026              kr = setRootDomainProperty(CFSTR("System Boot Complete"), kCFBooleanTrue);
5027              if(kr == kIOReturnSuccess) {
5028                 printf("Setting boot completed.\n");
5029              } else {
5030                  fprintf(stderr, "pmset: Error 0x%x setting boot property\n", kr);
5031                  fflush(stderr);
5032              }
5033
5034                i++;
5035            } else if(0 == strncmp(argv[i], ARG_UNBOOT, kMaxArgStringLength))
5036            {
5037                // Tell kernel power management that bootup is complete
5038                kr = setRootDomainProperty(CFSTR("System Shutdown"), kCFBooleanTrue);
5039                if(kr == kIOReturnSuccess) {
5040                    printf("Setting shutdown true.\n");
5041                } else {
5042                    fprintf(stderr, "pmset: Error 0x%x setting boot property\n", kr);
5043                    fflush(stderr);
5044                }
5045
5046                i++;
5047            } else if (0 == strncmp(argv[i], ARG_POLLBOOT, kMaxArgStringLength)) {
5048                ret = IOPSRequestBatteryUpdate(kIOPSReadSystemBoot);
5049                if (kIOReturnSuccess != ret) {
5050                    fprintf(stderr, "pmset: Must be run as root.\n");
5051                }
5052                goto exit;
5053            } else if (0 == strncmp(argv[i], ARG_POLLALL, kMaxArgStringLength)) {
5054                ret = IOPSRequestBatteryUpdate(kIOPSReadAll);
5055                if (kIOReturnSuccess != ret) {
5056                    fprintf(stderr, "pmset: Must be run as root.\n");
5057                }
5058                goto exit;
5059            } else if (0 == strncmp(argv[i], ARG_POLLUSER, kMaxArgStringLength)) {
5060                ret = IOPSRequestBatteryUpdate(kIOPSReadUserVisible);
5061                if (kIOReturnSuccess != ret) {
5062                    fprintf(stderr, "pmset: Must be run as root.\n");
5063                }
5064                goto exit;
5065            } else if (0 == strncmp(argv[i], ARG_RESTOREDEFAULTS, kMaxArgStringLength))
5066            {
5067                ret = IOPMRevertPMPreferences(NULL);
5068
5069                if (kIOReturnSuccess == ret) {
5070                    printf("Restored Default settings.\n");
5071                } else if (kIOReturnNotPrivileged == ret) {
5072                    printf("You're not privileged.\n");
5073                } else {
5074                    printf("Restore Defaults Error: 0x%08x\n", ret);
5075                }
5076                goto exit;
5077
5078            } else if(0 == strncmp(argv[i], ARG_FORCE, kMaxArgStringLength))
5079            {
5080                *force_activate_settings = true;
5081                i++;
5082            } else if( (0 == strncmp(argv[i], ARG_DIM, kMaxArgStringLength)) ||
5083                       (0 == strncmp(argv[i], ARG_DISPLAYSLEEP, kMaxArgStringLength)) )
5084            {
5085                // either 'dim' or 'displaysleep' argument sets minutes until display dims
5086                if(-1 == checkAndSetIntValue( argv[i+1],
5087                                                CFSTR(kIOPMDisplaySleepKey),
5088                                                apply, false, kNoMultiplier,
5089                                                ac, battery, ups))
5090                {
5091                    ret = kParseBadArgs;
5092                    goto exit;
5093                }
5094                modified |= kModSettings;
5095                i+=2;
5096            } else if( (0 == strncmp(argv[i], ARG_SPINDOWN, kMaxArgStringLength)) ||
5097                       (0 == strncmp(argv[i], ARG_DISKSLEEP, kMaxArgStringLength)))
5098            {
5099                // either 'spindown' or 'disksleep' argument sets minutes until disk spindown
5100                if(-1 == checkAndSetIntValue( argv[i+1],
5101                                                CFSTR(kIOPMDiskSleepKey),
5102                                                apply, false, kNoMultiplier,
5103                                                ac, battery, ups))
5104                {
5105                    ret = kParseBadArgs;
5106                    goto exit;
5107                }
5108                modified |= kModSettings;
5109                i+=2;
5110            } else if(0 == strncmp(argv[i], ARG_SLEEP, kMaxArgStringLength))
5111            {
5112                if(-1 == checkAndSetIntValue( argv[i+1],
5113                                                CFSTR(kIOPMSystemSleepKey),
5114                                                apply, false, kNoMultiplier,
5115                                                ac, battery, ups))
5116                {
5117                    ret = kParseBadArgs;
5118                    goto exit;
5119                }
5120                modified |= kModSettings;
5121                i+=2;
5122            } else if(0 == strncmp(argv[i], ARG_WOMP, kMaxArgStringLength))
5123            {
5124                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMWakeOnLANKey),
5125                                                apply, true, kNoMultiplier,
5126                                                ac, battery, ups))
5127                {
5128                    ret = kParseBadArgs;
5129                    goto exit;
5130                }
5131                modified |= kModSettings;
5132                i+=2;
5133            } else if(0 == strncmp(argv[i], ARG_RING, kMaxArgStringLength))
5134            {
5135                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMWakeOnRingKey),
5136                                                apply, true, kNoMultiplier,
5137                                                ac, battery, ups))
5138                {
5139                    ret = kParseBadArgs;
5140                    goto exit;
5141                }
5142                modified |= kModSettings;
5143                i+=2;
5144            } else if(0 == strncmp(argv[i], ARG_AUTORESTART, kMaxArgStringLength))
5145            {
5146                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMRestartOnPowerLossKey),
5147                                                apply, true, kNoMultiplier,
5148                                                ac, battery, ups))
5149                {
5150                    ret = kParseBadArgs;
5151                    goto exit;
5152                }
5153                modified |= kModSettings;
5154                i+=2;
5155            } else if(0 == strncmp(argv[i], ARG_WAKEONACCHANGE, kMaxArgStringLength))
5156            {
5157                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMWakeOnACChangeKey),
5158                                                apply, true, kNoMultiplier,
5159                                                ac, battery, ups))
5160                {
5161                    ret = kParseBadArgs;
5162                    goto exit;
5163                }
5164                modified |= kModSettings;
5165                i+=2;
5166            }  else if(0 == strncmp(argv[i], ARG_LIDWAKE, kMaxArgStringLength))
5167            {
5168                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMWakeOnClamshellKey),
5169                                                apply, true, kNoMultiplier,
5170                                                ac, battery, ups))
5171                {
5172                    ret = kParseBadArgs;
5173                    goto exit;
5174                }
5175                modified |= kModSettings;
5176                i+=2;
5177            } else if(0 == strncmp(argv[i], ARG_REDUCEBRIGHT, kMaxArgStringLength))
5178            {
5179                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMReduceBrightnessKey),
5180                                                apply, true, kNoMultiplier,
5181                                                ac, battery, ups))
5182                {
5183                    ret = kParseBadArgs;
5184                    goto exit;
5185                }
5186                modified |= kModSettings;
5187                i+=2;
5188            } else if(0 == strncmp(argv[i], ARG_SLEEPUSESDIM, kMaxArgStringLength))
5189            {
5190                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMDisplaySleepUsesDimKey),
5191                                                apply, true, kNoMultiplier,
5192                                                ac, battery, ups))
5193                {
5194                    ret = kParseBadArgs;
5195                    goto exit;
5196                }
5197                modified |= kModSettings;
5198                i+=2;
5199            } else if((0 == strncmp(argv[i], ARG_MOTIONSENSOR, kMaxArgStringLength))
5200                   || (0 == strncmp(argv[i], ARG_MOTIONSENSOR2, kMaxArgStringLength)) )
5201            {
5202                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMMobileMotionModuleKey),
5203                                                apply, true, kNoMultiplier,
5204                                                ac, battery, ups))
5205                {
5206                    ret = kParseBadArgs;
5207                    goto exit;
5208                }
5209                modified |= kModSettings;
5210                i+=2;
5211            } else if(0 == strncmp(argv[i], ARG_TTYKEEPAWAKE, kMaxArgStringLength))
5212            {
5213                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMTTYSPreventSleepKey),
5214                                                apply, true, kNoMultiplier,
5215                                                ac, battery, ups))
5216                {
5217                    ret = kParseBadArgs;
5218                    goto exit;
5219                }
5220                modified |= kModSettings;
5221                i+=2;
5222            } else if(0 == strncmp(argv[i], ARG_DISABLESLEEP, kMaxArgStringLength))
5223            {
5224                char            *endptr = NULL;
5225                long            val;
5226
5227                if( argv[i+1] )
5228                {
5229                    val = strtol(argv[i+1], &endptr, 10);
5230
5231                    if(0 != *endptr)
5232                    {
5233                        // the string contained some non-numerical characters - bail
5234                        ret = kParseBadArgs;
5235                        goto exit;
5236                    }
5237
5238                    // Any non-zero value of val (preferably 1) means DISABLE sleep.
5239                    // A zero value means ENABLE sleep.
5240
5241                    CFDictionarySetValue( local_system_power_settings,
5242                                          kIOPMSleepDisabledKey,
5243                                          val ? kCFBooleanTrue : kCFBooleanFalse);
5244
5245                    modified |= kModSystemSettings;
5246                }
5247                i+=2;
5248            } else if(0 ==  strncmp(argv[i], ARG_DISABLEFDEKEYSTORE, kMaxArgStringLength))
5249            {
5250                char            *endptr = NULL;
5251                long            val;
5252
5253                if( argv[i+1] )
5254                {
5255                    val = strtol(argv[i+1], &endptr, 10);
5256
5257                    if(0 != *endptr)
5258                    {
5259                        // the string contained some non-numerical characters - bail
5260                        ret = kParseBadArgs;
5261                        goto exit;
5262                    }
5263
5264                    // Any non-zero value of val (preferably 1) means Allow storing
5265                    // FDE Keys to hardware
5266                    // A zero value means Avoid storing keys to hardware
5267
5268                    CFDictionarySetValue( local_system_power_settings,
5269                                          CFSTR(kIOPMDestroyFVKeyOnStandbyKey),
5270                                          val ? kCFBooleanTrue : kCFBooleanFalse );
5271
5272                    modified |= kModSystemSettings;
5273                }
5274                i+=2;
5275
5276            } else if(0 == strncmp(argv[i], ARG_HALTLEVEL, kMaxArgStringLength))
5277            {
5278                if(-1 == setUPSValue(argv[i+1], CFSTR(kIOPMDefaultUPSThresholds),
5279                                                CFSTR(kIOUPSShutdownAtLevelKey),
5280                                                apply, local_ups_settings))
5281                {
5282                    ret = kParseBadArgs;
5283                    goto exit;
5284                }
5285                modified |= kModUPSThresholds;
5286                i+=2;
5287            } else if(0 == strncmp(argv[i], ARG_HALTAFTER, kMaxArgStringLength))
5288            {
5289                if(-1 == setUPSValue(argv[i+1], CFSTR(kIOPMDefaultUPSThresholds),
5290                                                CFSTR(kIOUPSShutdownAfterMinutesOn),
5291                                                apply, local_ups_settings))
5292                {
5293                    ret = kParseBadArgs;
5294                    goto exit;
5295                }
5296                modified |= kModUPSThresholds;
5297                i+=2;
5298            } else if(0 == strncmp(argv[i], ARG_HALTREMAIN, kMaxArgStringLength))
5299            {
5300                if(-1 == setUPSValue(argv[i+1], CFSTR(kIOPMDefaultUPSThresholds),
5301                                                CFSTR(kIOUPSShutdownAtMinutesLeft),
5302                                                apply, local_ups_settings))
5303                {
5304                    ret = kParseBadArgs;
5305                    goto exit;
5306                }
5307                modified |= kModUPSThresholds;
5308                i+=2;
5309            } else if(0 == strncmp(argv[i], ARG_HIBERNATEMODE, kMaxArgStringLength))
5310            {
5311                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOHibernateModeKey),
5312                                                        apply, false, kNoMultiplier,
5313                                                        ac, battery, ups))
5314                {
5315                    ret = kParseBadArgs;
5316                    goto exit;
5317                }
5318                modified |= kModSettings;
5319                i+=2;
5320            } else if(0 == strncmp(argv[i], ARG_HIBERNATEFREERATIO, kMaxArgStringLength))
5321            {
5322                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOHibernateFreeRatioKey),
5323                                                        apply, false, kNoMultiplier,
5324                                                        ac, battery, ups))
5325                {
5326                    ret = kParseBadArgs;
5327                    goto exit;
5328                }
5329                modified |= kModSettings;
5330                i+=2;
5331            } else if(0 == strncmp(argv[i], ARG_HIBERNATEFREETIME, kMaxArgStringLength))
5332            {
5333                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOHibernateFreeTimeKey),
5334                                                        apply, false, kNoMultiplier,
5335                                                        ac, battery, ups))
5336                {
5337                    ret = kParseBadArgs;
5338                    goto exit;
5339                }
5340                modified |= kModSettings;
5341                i+=2;
5342            } else if(0 == strncmp(argv[i], ARG_HIBERNATEFILE, kMaxArgStringLength))
5343            {
5344                if(-1 == checkAndSetStrValue(argv[i+1], CFSTR(kIOHibernateFileKey),
5345                                                        apply, ac, battery, ups))
5346                {
5347                    ret = kParseBadArgs;
5348                    goto exit;
5349                }
5350                modified |= kModSettings;
5351                i+=2;
5352            } else if(0 == strncmp(argv[i], ARG_GPU, kMaxArgStringLength))
5353            {
5354                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMGPUSwitchKey),
5355                                                        apply, false, kNoMultiplier,
5356                                                        ac, battery, ups))
5357                {
5358                    ret = kParseBadArgs;
5359                    goto exit;
5360                }
5361                modified |= kModSettings;
5362                i+=2;
5363            } else if(0 == strncmp(argv[i], ARG_NETAVAILABLE, kMaxArgStringLength))
5364            {
5365                if(-1 == checkAndSetIntValue(argv[i+1],
5366                                     CFSTR(kIOPMPrioritizeNetworkReachabilityOverSleepKey),
5367                                     apply, false, kNoMultiplier,
5368                                     ac, battery, ups))
5369                {
5370                    ret = kParseBadArgs;
5371                    goto exit;
5372                }
5373                modified |= kModSettings;
5374                i+=2;
5375            } else if(0 == strncmp(argv[i], ARG_DEEPSLEEP, kMaxArgStringLength))
5376            {
5377                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMDeepSleepEnabledKey),
5378                                             apply, false, kNoMultiplier,
5379                                             ac, battery, ups))
5380                {
5381                    ret = kParseBadArgs;
5382                    goto exit;
5383                }
5384                modified |= kModSettings;
5385                i+=2;
5386            } else if(0 == strncmp(argv[i], ARG_DEEPSLEEPDELAY, kMaxArgStringLength))
5387            {
5388                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMDeepSleepDelayKey),
5389                                             apply, false, kNoMultiplier,
5390                                             ac, battery, ups))
5391                {
5392                    ret = kParseBadArgs;
5393                    goto exit;
5394                }
5395                modified |= kModSettings;
5396                i+=2;
5397            } else if(0 == strncmp(argv[i], ARG_DARKWAKES, kMaxArgStringLength))
5398            {
5399                if((-1 == checkAndSetIntValue(argv[i+1],
5400                            CFSTR(kIOPMDarkWakeBackgroundTaskKey), apply,
5401                            false, kNoMultiplier, ac, battery, ups)) ||
5402                    (-1 == checkAndSetIntValue(argv[i+1],
5403                             CFSTR(kIOPMSleepServicesKey), apply, false,
5404                             kNoMultiplier, ac, battery, ups)))
5405                {
5406                    ret = kParseBadArgs;
5407                    goto exit;
5408                }
5409                modified |= kModSettings;
5410                i+=2;
5411            } else if(0 == strncmp(argv[i], ARG_AUTOPOWEROFF, kMaxArgStringLength))
5412            {
5413                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMAutoPowerOffEnabledKey),
5414                                             apply, false, kNoMultiplier,
5415                                             ac, battery, ups))
5416                    return kParseBadArgs;
5417                modified |= kModSettings;
5418                i+=2;
5419            } else if(0 == strncmp(argv[i], ARG_AUTOPOWEROFFDELAY, kMaxArgStringLength))
5420            {
5421                if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMAutoPowerOffDelayKey),
5422                                             apply, false, kNoMultiplier,
5423                                             ac, battery, ups))
5424                    return kParseBadArgs;
5425                modified |= kModSettings;
5426                i+=2;
5427            } else {
5428                // Determine if this is a number.
5429                // If so, the user is setting the active power profile
5430                // for the power sources specified in applyTo
5431                // If not, bail with bad input.
5432                char                    *endptr = 0;
5433                long                    val;
5434                CFNumberRef             prof_val = 0;
5435
5436                if(!local_profiles) {
5437                    ret = kParseInternalError;
5438                    goto exit;
5439                }
5440
5441                val = strtol(argv[i], &endptr, 10);
5442
5443                if(0 != *endptr || (val < -1) || (val > 4) )
5444                {
5445                    // the string contained some non-numerical characters
5446                    // or the profile number was out of the expected range
5447                    ret = kParseBadArgs;
5448                    goto exit;
5449                }
5450                prof_val = CFNumberCreate(0, kCFNumberIntType, &val);
5451                if(!prof_val) {
5452                    ret = kParseInternalError;
5453                } else {
5454                    // setting a profile
5455                    if(kApplyToBattery & apply) {
5456                        CFDictionarySetValue(local_profiles, CFSTR(kIOPMBatteryPowerKey), prof_val);
5457                    }
5458                    if(kApplyToCharger & apply) {
5459                        CFDictionarySetValue(local_profiles, CFSTR(kIOPMACPowerKey), prof_val);
5460                    }
5461                    if(kApplyToUPS & apply) {
5462                        CFDictionarySetValue(local_profiles, CFSTR(kIOPMUPSPowerKey), prof_val);
5463                    }
5464                    CFRelease(prof_val);
5465
5466                    modified |= kModProfiles;
5467                }
5468                goto exit;
5469            }
5470        } // if
5471    } // while
5472
5473exit:
5474    if(modified & kModSettings) {
5475        *settings = local_settings;
5476        *modified_power_sources = apply;
5477    } else {
5478        if(local_settings) CFRelease(local_settings);
5479    }
5480
5481    if(modified & kModSystemSettings) {
5482        *system_power_settings = local_system_power_settings;
5483    } else {
5484        if(local_system_power_settings) CFRelease(local_system_power_settings);
5485    }
5486
5487    if(modified & kModProfiles) {
5488        *active_profiles = local_profiles;
5489    } else {
5490        if(local_profiles) CFRelease(local_profiles);
5491    }
5492
5493    if(modified & kModUPSThresholds) {
5494        if(ups_thresholds) *ups_thresholds = local_ups_settings;
5495    } else {
5496        if(local_ups_settings) CFRelease(local_ups_settings);
5497    }
5498
5499    if(modified & kModSched) {
5500        *scheduled_event = local_scheduled_event;
5501        *cancel_scheduled_event = local_cancel_event;
5502    }
5503
5504    if(modified & kModRepeat) {
5505        *repeating_event = local_repeating_event;
5506        *cancel_repeating_event = local_cancel_repeating;
5507    } else {
5508        if(local_repeating_event) CFRelease(local_repeating_event);
5509    }
5510
5511    return ret;
5512}
5513
5514// int arePowerSourceSettingsInconsistent(CFDictionaryRef)
5515// Function - determine if the settings will produce the "intended" idle sleep consequences
5516// Parameter - The CFDictionary contains energy saver settings of
5517//             CFStringRef keys and CFNumber/CFBoolean values
5518// Return - non-zero bitfield, each bit indicating a setting inconsistency
5519//          0 if settings will produce expected result
5520//         -1 in case of other error
5521static int arePowerSourceSettingsInconsistent(CFDictionaryRef set)
5522{
5523    int                 sleep_time, disk_time, dim_time;
5524    CFNumberRef         num;
5525    int                 ret = 0;
5526
5527    num = isA_CFNumber(CFDictionaryGetValue(set, CFSTR(kIOPMSystemSleepKey)));
5528    if(!num || !CFNumberGetValue(num, kCFNumberIntType, &sleep_time)) return -1;
5529
5530    num = isA_CFNumber(CFDictionaryGetValue(set, CFSTR(kIOPMDisplaySleepKey)));
5531    if(!num || !CFNumberGetValue(num, kCFNumberIntType, &dim_time)) return -1;
5532
5533    num = isA_CFNumber(CFDictionaryGetValue(set, CFSTR(kIOPMDiskSleepKey)));
5534    if(!num || !CFNumberGetValue(num, kCFNumberIntType, &disk_time)) return -1;
5535
5536    // For system sleep to occur around the time you set it to, the disk and display
5537    // sleep timers must conform to these rules:
5538    // 1. display sleep <= system sleep; except that in some systems, sleep_timer will
5539    //    be 1, to indicate that system sleep should occur 1 min after display sleep
5540    // 2. If system sleep != Never, then disk sleep can not be == Never
5541    //    2a. It is, however, OK for disk sleep > system sleep. A funky hack in
5542    //        the kernel IOPMrootDomain allows this.
5543    // and note: a time of zero means "never power down"
5544
5545    if(sleep_time != 0)
5546    {
5547        if ((sleep_time != 1) && (dim_time > sleep_time || dim_time == 0)) ret |= kInconsistentDisplaySetting;
5548
5549        if(disk_time == 0) ret |= kInconsistentDiskSetting;
5550    }
5551
5552    return ret;
5553}
5554
5555// void checkSettingConsistency(CFDictionaryRef)
5556// Checks ES settings profile by profile
5557// Prints a user warning if any idle timer settings violate the kernel's assumptions
5558// about idle, disk, and display sleep timers.
5559// Parameter - a CFDictionary of energy settings "profiles", usually one per power supply
5560static void checkSettingConsistency(CFDictionaryRef profiles)
5561{
5562    CFIndex             num_profiles;
5563    int                 i;
5564    int                 ret;
5565    char                buf[kMaxLongStringLength];
5566    CFStringRef         *keys;
5567    CFDictionaryRef     *values;
5568
5569    num_profiles = CFDictionaryGetCount(profiles);
5570    keys = (CFStringRef *)malloc(num_profiles * sizeof(CFStringRef *));
5571    values = (CFDictionaryRef *)malloc(num_profiles * sizeof(CFDictionaryRef *));
5572    if(!keys || !values) goto fail;
5573    CFDictionaryGetKeysAndValues(profiles, (const void **)keys, (const void **)values);
5574
5575// TODO: Warn user if 1) they have just changed the custom settings
5576//       2) their active profile is _NOT_ custom
5577
5578    for(i=0; i<num_profiles; i++)
5579    {
5580        // Check settings profile by profile
5581        if( isA_CFDictionary(values[i])
5582            && (ret = arePowerSourceSettingsInconsistent(values[i])) )
5583        {
5584            // get profile name
5585            if(!CFStringGetCString(keys[i], buf, kMaxLongStringLength, kCFStringEncodingMacRoman)) break;
5586
5587            fprintf(stderr, "Warning: Idle sleep timings for \"%s\" may not behave as expected.\n", buf);
5588            if(ret & kInconsistentDisplaySetting)
5589            {
5590                fprintf(stderr, "- Display sleep should have a lower timeout than system sleep.\n");
5591            }
5592            if(ret & kInconsistentDiskSetting)
5593            {
5594                fprintf(stderr, "- Disk sleep should be non-zero whenever system sleep is non-zero.\n");
5595            }
5596            fflush(stderr);
5597        }
5598    }
5599
5600fail:
5601    if (keys) {
5602        free(keys);
5603    }
5604    if (values) {
5605        free(values);
5606    }
5607}
5608
5609static ScheduledEventReturnType *scheduled_event_struct_create(void)
5610{
5611    ScheduledEventReturnType *ret = malloc(sizeof(ScheduledEventReturnType));
5612    if(!ret) return NULL;
5613    ret->who = 0;
5614    ret->when = 0;
5615    ret->which = 0;
5616    return ret;
5617}
5618
5619static void scheduled_event_struct_destroy(
5620    ScheduledEventReturnType *free_me)
5621{
5622    if( (0 == free_me) ) return;
5623    if(free_me->who) {
5624        CFRelease(free_me->who);
5625        free_me->who = 0;
5626    }
5627    if(free_me->when) {
5628        CFRelease(free_me->when);
5629        free_me->when = 0;
5630    }
5631    if((free_me)->which) {
5632        CFRelease(free_me->which);
5633        free_me->which = 0;
5634    }
5635    free(free_me);
5636}
5637
5638
5639static IOReturn _pm_connect(mach_port_t *newConnection)
5640{
5641    kern_return_t       kern_result = KERN_SUCCESS;
5642
5643    if(!newConnection) return kIOReturnBadArgument;
5644
5645    // open reference to PM configd
5646    kern_result = bootstrap_look_up2(bootstrap_port,
5647                                    kIOPMServerBootstrapName,
5648                                    newConnection,
5649                                    0,
5650                                    BOOTSTRAP_PRIVILEGED_SERVER);
5651
5652    if(KERN_SUCCESS != kern_result) {
5653        return kIOReturnError;
5654    }
5655    return kIOReturnSuccess;
5656}
5657
5658static IOReturn _pm_disconnect(mach_port_t connection)
5659{
5660    if(!connection) return kIOReturnBadArgument;
5661    mach_port_destroy(mach_task_self(), connection);
5662    return kIOReturnSuccess;
5663}
5664
5665/******************************************************************************/
5666/*                                                                            */
5667/*     ASL & MESSAGETRACER & HISTORY                                          */
5668/*                                                                            */
5669/******************************************************************************/
5670
5671/*
5672 * Cache the message in a temp ring buffer.
5673 */
5674static asl_object_t _cacheAndGetMsg(asl_object_t pmresponse)
5675{
5676   asl_object_t msg = NULL;
5677
5678   if (msgCache == NULL)
5679   {
5680      msgCache = calloc(1, sizeof(MsgCache));
5681      if (!msgCache) return NULL;
5682   }
5683
5684   if (((msgCache->writeIdx+1) % RING_SIZE) == msgCache->readIdx)
5685      return NULL; /* overflow */
5686
5687   msg = asl_next(pmresponse);
5688   if (!msg) return NULL;
5689
5690   msgCache->msgRing[msgCache->writeIdx] = msg;
5691
5692   msgCache->writeIdx = (msgCache->writeIdx+1) % RING_SIZE;
5693   return  msg;
5694}
5695
5696static asl_object_t _my_next_response(asl_object_t pmresponse)
5697{
5698    asl_object_t   next_msg = 0;
5699
5700    /*
5701     * _my_next_response returns messages from our cache
5702     * until there aren't any more messages in it.
5703     * Then it returns messages from the PM ASL store, via pmresponse.
5704     */
5705    if (msgCache && (msgCache->readIdx != msgCache->writeIdx))
5706    {
5707        next_msg = msgCache->msgRing[msgCache->readIdx];
5708        msgCache->readIdx = (msgCache->readIdx+1) % RING_SIZE;
5709    }
5710
5711    /*
5712     * If the cache is empty, then we pull messages straight from the ASL store.
5713     */
5714    if (0 == next_msg) {
5715        next_msg = asl_next(pmresponse);
5716    }
5717
5718    return next_msg;
5719}
5720
5721/*
5722 * Called when current event is 'Sleep', to find out
5723 * the time stamp of next wake event.
5724 *
5725 * Possible transitions:
5726 * Sleep -> Wake
5727 * Sleep -> DarkWake
5728 */
5729
5730static int32_t _getNextWakeTime(asl_object_t pmresponse)
5731{
5732   const char *domain = NULL;
5733   const char *timeStr = NULL;
5734   int32_t wakeTime = -1;
5735   asl_object_t next;
5736
5737   do {
5738
5739      if ((next = _cacheAndGetMsg(pmresponse)) == NULL) break;
5740
5741      domain = asl_get(next, kPMASLDomainKey);
5742      if (!domain) break;
5743
5744      if ( (!strncmp(kPMASLDomainPMWake, domain, sizeof(kPMASLDomainPMWake) )) ||
5745            (!strncmp(kPMASLDomainPMDarkWake, domain, sizeof(kPMASLDomainPMDarkWake) )) )
5746      {
5747         timeStr = asl_get(next, ASL_KEY_TIME);
5748         if (timeStr)
5749            wakeTime = (int32_t)strtol(timeStr, NULL ,0);
5750         break;
5751      }
5752      else if (!strncmp(kPMASLDomainPMSleep, domain, sizeof(kPMASLDomainPMSleep) ))
5753      {
5754          /* Came across another sleep trace. Wake trace is missing */
5755          break;
5756      }
5757   } while(1);
5758
5759   return wakeTime;
5760}
5761
5762/*
5763 * Called when current event is 'wake/darkWake', to find out
5764 * the time stamp of next sleep/wake event.
5765 *
5766 * Possible transitions:
5767 * Wake -> Sleep
5768 * DarkWake -> Sleep
5769 * DarkWake -> Wake
5770 */
5771static int32_t _getNextSleepTime(asl_object_t pmresponse, const char *curr_domain)
5772{
5773   const char *domain = NULL;
5774   const char *timeStr = NULL;
5775   int32_t sleepTime = -1;
5776   size_t sleepCnt = 0;
5777   asl_object_t next;
5778
5779   do {
5780
5781
5782      if ((next = _cacheAndGetMsg(pmresponse)) == NULL) break;
5783      domain = asl_get(next, kPMASLDomainKey);
5784      if (!domain) continue;
5785
5786      /* Check for events with unexpected transitions */
5787      if (( !strncmp(kPMASLDomainPMWake, curr_domain, sizeof(kPMASLDomainPMWake) )) &&
5788          ( (!strncmp(kPMASLDomainPMWake, domain, sizeof(kPMASLDomainPMWake) )) ||
5789            (!strncmp(kPMASLDomainPMDarkWake, domain, sizeof(kPMASLDomainPMDarkWake)) )
5790          ))
5791      {
5792          /* Wake -> Wake or Wake -> DarkWake is unexpected */
5793          break;
5794      }
5795
5796      else if ((!strncmp(kPMASLDomainPMDarkWake, curr_domain, sizeof(kPMASLDomainPMDarkWake))) &&
5797               (!strncmp(kPMASLDomainPMDarkWake, domain, sizeof(kPMASLDomainPMDarkWake)) ))
5798      {
5799          /* DarkWake ->  DarkWake is unexpected */
5800          break;
5801      }
5802
5803      if ( (!strncmp(kPMASLDomainPMSleep, domain, sizeof(kPMASLDomainPMSleep) )) ||
5804               (!strncmp(kPMASLDomainPMWake, domain, sizeof(kPMASLDomainPMWake) )) )
5805      {
5806         const char *value1 = asl_get(next, kPMASLValueKey);
5807         if (value1) {
5808            sleepCnt = strtol(value1, NULL, 0);
5809
5810            if (sleepCnt == 1)
5811               break;  /* System rebooted at this point */
5812         }
5813
5814         timeStr = asl_get(next, ASL_KEY_TIME);
5815         if (timeStr)
5816            sleepTime = (int32_t)strtol(timeStr, NULL ,0);
5817         break;
5818      }
5819   } while(1);
5820
5821   return sleepTime;
5822}
5823
5824#define kPMASLStorePath                 "/var/log/powermanagement"
5825
5826static asl_object_t open_pm_asl_store(void)
5827{
5828    asl_object_t        response = NULL;
5829    size_t              endMessageID;
5830
5831    asl_object_t query = asl_new(ASL_TYPE_LIST);
5832    if (query != NULL)
5833    {
5834		asl_object_t cq = asl_new(ASL_TYPE_QUERY);
5835		if (cq != NULL)
5836		{
5837			asl_set_query(cq, ASL_KEY_FACILITY, kPMFacility, ASL_QUERY_OP_EQUAL);
5838			asl_append(query, cq);
5839			asl_release(cq);
5840
5841			asl_object_t pmstore = asl_open_path(kPMASLStorePath, 0);
5842			if (pmstore != NULL) {
5843				response = asl_match(pmstore, query, &endMessageID, 0, 0, 0, ASL_MATCH_DIRECTION_FORWARD);
5844			}
5845			asl_release(pmstore);
5846		}
5847
5848		asl_release(query);
5849    }
5850
5851    return response;
5852}
5853
5854static void pmlog_print_claimedwakes(CFAbsoluteTime  abs_time, asl_object_t m)
5855{
5856    int i=0;
5857    char key[255];
5858    const char *claimed;
5859
5860    do {
5861        snprintf(key, sizeof(key), "%s-%d", kPMASLClaimedEventKey, i);
5862        claimed = asl_get(m, key);
5863        if (!claimed) {
5864            break;
5865        }
5866        if (i == 0) {
5867            print_pretty_date(abs_time, false);
5868            printf("%-20s\t",  "WakeDetails"); // domain
5869        }
5870        i++;
5871        printf("%-75s\n", claimed);
5872
5873    } while (true);
5874
5875    return;
5876}
5877
5878static void printWakeReqMsg(asl_object_t m)
5879{
5880    int chosen = -1, cnt = 0;
5881    char    key[50];
5882    const char    *appName, *wakeType, *delta, *str;
5883
5884    if ((str = asl_get(m, kPMASLWakeReqChosenIdx))) {
5885        chosen = strtol(str, NULL, 0);
5886    }
5887    while (true) {
5888
5889        snprintf(key, sizeof(key), "%s%d", KPMASLWakeReqAppNamePrefix, cnt);
5890        if (!(appName = asl_get(m, key)))
5891            break;
5892
5893        snprintf(key, sizeof(key), "%s%d", kPMASLWakeReqTimeDeltaPrefix, cnt);
5894        if (!(delta = asl_get(m, key)))
5895            break;
5896
5897        snprintf(key, sizeof(key), "%s%d", kPMASLWakeReqTypePrefix, cnt);
5898        if (!(wakeType = asl_get(m, key)))
5899            break;
5900
5901        snprintf(key, sizeof(key), "%s%d", kPMASLWakeReqClientInfoPrefix, cnt);
5902        str = asl_get(m, key); // Optional client info
5903
5904        printf("[%sproc=%s request=%s inDelta=%s%s%s%s] ",
5905               (cnt == chosen) ? "*" : "",
5906               appName, wakeType, delta,
5907               (str) ? " info=\"" : "",
5908               (str) ? str : "",
5909               (str) ? "\"" : "");
5910
5911        cnt++;
5912    }
5913
5914}
5915static void printStatsMsg(asl_object_t m)
5916{
5917    int     cnt = 0;
5918    const char    *appName, *responseType, *delay;
5919    const char    *transition = NULL;
5920    char    *str, buf[128];
5921    const char    *ps, *msg;
5922
5923    while (true) {
5924
5925
5926        snprintf(buf, sizeof(buf), "%s%d",kPMASLResponseAppNamePrefix, cnt);
5927        if (!(appName = asl_get(m, buf)))
5928            break;
5929
5930        snprintf(buf, sizeof(buf), "%s%d", kPMASLResponseRespTypePrefix, cnt);
5931        if (!(responseType = asl_get(m, buf)))
5932            break;
5933
5934        snprintf(buf, sizeof(buf), "%s%d", kPMASLResponseDelayPrefix, cnt);
5935        if (!(delay = asl_get(m, buf)))
5936            break;
5937
5938        if (!strncmp(responseType, kIOPMStatsResponseTimedOut, sizeof(kIOPMStatsResponseTimedOut)))
5939            str = "timed out";
5940        else if (!strncmp(responseType, kIOPMStatsResponseSlow, sizeof(kIOPMStatsResponseSlow)))
5941            str = "is slow";
5942        else if (!strncmp(responseType, kIOPMStatsResponsePrompt, sizeof(kIOPMStatsResponsePrompt)))
5943            str = "is prompt";
5944        else if (!strncmp(responseType, kIOPMStatsDriverPSChangeSlow, sizeof(kIOPMStatsDriverPSChangeSlow)))  {
5945            ps = NULL;
5946            snprintf(buf, sizeof(buf), "%s%d",kPMASLResponsePSCapsPrefix, cnt);
5947            ps = asl_get(m, buf);
5948
5949            msg = NULL;
5950            snprintf(buf, sizeof(buf), "%s%d",kPMASLResponseMessagePrefix, cnt);
5951            msg = asl_get(m, buf);
5952
5953            str = "driver is slow for ";
5954            snprintf(buf, sizeof(buf), "driver is slow(msg: %s to %s)",
5955                     (msg) ? msg : "", (ps) ? ps : "");
5956            str = buf;
5957        }
5958        else
5959            break;
5960
5961        transition = asl_get(m, kPMASLResponseSystemTransition);
5962        if (cnt == 0 && transition)
5963            printf("Delays to %s notifications: ", transition);
5964
5965        printf("[%s %s(%s ms)] ", appName, str, delay);
5966        cnt++;
5967    }
5968}
5969
5970/* All PM messages in ASL log */
5971static void show_log(void)
5972{
5973    asl_object_t        m = NULL;
5974    char                uuid[100];
5975    long                sleep_cnt = 0;
5976    long                dark_wake_cnt = 0;
5977    bool                first_iter = true;
5978    CFAbsoluteTime      boot_time = 0;
5979
5980    asl_object_t        response = NULL;
5981
5982    response = open_pm_asl_store();
5983    if (!response)
5984    {
5985        printf("Error - no messages found in PM ASL data store at: %s\n", kPMASLStorePath);
5986        return;
5987    } else {
5988        printf("PM ASL data store: %s\n", kPMASLStorePath);
5989    }
5990
5991    uuid[0] = 0;
5992
5993    while ((m = _my_next_response(response)))
5994    {
5995        const char  *val = NULL;
5996        int32_t     print_duration_time = -1;
5997        long        time_read = 0;
5998        char        buf[40];
5999        bool        new_boot_cycle = false;
6000        bool        isAwakening = false;
6001        bool        kerStats = false, pmStats = false;
6002        bool        wakeReq = false;
6003        CFAbsoluteTime  abs_time ;
6004
6005        if ((val = asl_get(m, kPMASLDomainKey)))
6006        {
6007            if (!strncmp(val, kPMASLDomainPMStart, sizeof(kPMASLDomainPMStart)-1)) {
6008                new_boot_cycle = true;
6009            }
6010        }
6011
6012        if (((val = asl_get(m, kPMASLUUIDKey)) && (strncmp( val, uuid, sizeof(uuid)) != 0)) || new_boot_cycle )
6013        {
6014            // New Sleep cycle is about to begin
6015            // Print Sleep cnt and dark wake cnt of previous sleep/wake cycle
6016            if ( !first_iter )
6017            {
6018               printf("Sleep/Wakes since boot");
6019               if (boot_time) {
6020                  printf(" at ");
6021                  print_pretty_date(boot_time, false);
6022
6023               }
6024               printf(":%ld   Dark Wake Count in this sleep cycle:%ld\n", sleep_cnt, dark_wake_cnt);
6025            }
6026            first_iter = false;
6027
6028            printf("\n");   // Extra line to seperate from previous sleep/wake cycles
6029            dark_wake_cnt = 0;
6030
6031            // Print the header for each column
6032            printf("%-25s %-20s\t%-75s\t%-10s\t%-10s\n", "Time stamp", "Domain", "Message", "Duration", "Delay");
6033            printf("%-25s %-20s\t%-75s\t%-10s\t%-10s\n", "==========", "======", "=======", "========", "=====");
6034
6035            // Print and save UUID of the new cycle
6036            snprintf(uuid, sizeof(uuid), "%s", val);
6037            printf("UUID: %s\n", val);
6038            sleep_cnt = 0;
6039        }
6040
6041        // Time
6042        if ((val = asl_get(m, ASL_KEY_TIME)))
6043        {
6044            time_read = atol(val);
6045            abs_time = (CFAbsoluteTime)(time_read - kCFAbsoluteTimeIntervalSince1970);
6046            print_pretty_date(abs_time, false);
6047            if (new_boot_cycle)
6048               boot_time = abs_time;
6049        }
6050
6051
6052        // Domain
6053        if ((val = asl_get(m, kPMASLDomainKey)))
6054        {
6055            const char *value1 = asl_get(m, kPMASLValueKey);
6056
6057            if (strnstr(val, "Response.", strlen(val))) {
6058               printf("%-20s\t",  ((char *)val + (uintptr_t)strlen("Response.")));
6059            }
6060            else if (!strncmp(val, kPMASLDomainKernelClientStats, sizeof(kPMASLDomainKernelClientStats))) {
6061                printf("%-20s\t", "Kernel Client Acks");
6062                kerStats = true;
6063            }
6064            else if (!strncmp(val, kPMASLDomainPMClientStats, sizeof(kPMASLDomainPMClientStats))) {
6065                printf("%-20s\t", "PM Client Acks");
6066                pmStats = true;
6067            }
6068            else if (!strncmp(val, kPMASLDomainClientWakeRequests, sizeof(kPMASLDomainClientWakeRequests))) {
6069                printf("%-20s\t", "Wake Requests");
6070                wakeReq = true;
6071            }
6072            else {
6073                printf("%-20s\t",  (char *)val);
6074            }
6075
6076
6077            if (!strncmp(kPMASLDomainPMSleep, val, sizeof(kPMASLDomainPMSleep) ))
6078            {
6079                if ( (print_duration_time = _getNextWakeTime(response)) != -1) {
6080                    print_duration_time -= time_read;
6081                }
6082
6083               if (value1) {
6084                   sleep_cnt = strtol(value1, NULL, 0);
6085                }
6086            }
6087            else if (!strncmp(kPMASLDomainPMWake, val, sizeof(kPMASLDomainPMWake)) ||
6088                     !strncmp(kPMASLDomainPMDarkWake, val, sizeof(kPMASLDomainPMDarkWake)))
6089            {
6090                isAwakening = true;
6091                if ( (print_duration_time = _getNextSleepTime(response, val)) != -1) {
6092                    print_duration_time -= time_read;
6093                }
6094
6095                if (value1 &&
6096                    !strncmp(kPMASLDomainPMDarkWake, val, sizeof(kPMASLDomainPMDarkWake) ))
6097                {
6098                    dark_wake_cnt = strtol(value1, NULL, 0);
6099                }
6100            }
6101        }
6102        else
6103        {
6104            printf("%-20s\t",  " ");
6105        }
6106
6107        // Message
6108        if (pmStats || kerStats) {
6109            printStatsMsg(m);
6110        }
6111        else if (wakeReq) {
6112            printWakeReqMsg(m);
6113        }
6114        else if ((val = asl_get(m, ASL_KEY_MSG))) {
6115            printf("%-75s\t", val);
6116        } else {
6117            printf("%-75s\t",  " ");
6118        }
6119
6120        // Duration/Delay
6121        if (-1 != print_duration_time) {
6122            snprintf(buf, sizeof(buf), "%d secs", print_duration_time);
6123        } else {
6124            buf[0] = 0;
6125        }
6126        printf("%-10s", buf);
6127
6128        if ((val = asl_get(m, kPMASLDelayKey)))
6129        {
6130            printf("%-10s\t", val);
6131        }
6132
6133        printf("\n");
6134
6135        if (isAwakening) {
6136            pmlog_print_claimedwakes(abs_time, m);
6137        }
6138
6139    }
6140
6141    if (sleep_cnt || dark_wake_cnt) {
6142        printf("\nTotal Sleep/Wakes since boot");
6143        if (boot_time) {
6144            printf(" at ");
6145            print_pretty_date(boot_time, false);
6146        }
6147        printf(":%ld\n", sleep_cnt);
6148    }
6149    printf("\n");
6150    show_assertions("Showing all currently held IOKit power assertions");
6151}
6152
6153
6154static void show_power_event_history(void)
6155{
6156    IOReturn        ret;
6157    CFArrayRef      powpowHistory = NULL;
6158    CFStringRef     uuid = NULL;
6159    CFDictionaryRef uuid_details;
6160    char            uuid_cstr[255];
6161    int             uuid_index;
6162    CFIndex         uuid_count;
6163    //CFAbsoluteTime  set_time = 0.0;
6164    //CFAbsoluteTime  clear_time = 0.0;
6165    //CFNumberRef     timestamp;
6166    CFStringRef     timestamp;
6167    char            st[60];
6168    char            ct[60];
6169
6170    ret = IOPMCopyPowerHistory(&powpowHistory);
6171
6172    if (kIOReturnSuccess != ret || NULL == powpowHistory)
6173    {
6174        printf("Error - no power history found. (IOPMCopyPowerHistory error = 0x%08x)\n", ret);
6175        goto exit;
6176    }
6177
6178    uuid_count = CFArrayGetCount(powpowHistory);
6179    printf("Power History Summary (%ld UUIDs)\n", uuid_count);
6180
6181    int i = 0;
6182    for(; i < 9; i++)
6183      printf("----------");
6184    printf("\n");
6185
6186    printf("%-40s|%-24s|%-24s|\n", "UUID", "Set Time", "Clear Time");
6187
6188    i = 0;
6189    for(; i < 9; i++)
6190      printf("----------");
6191    printf("\n");
6192
6193    for (uuid_index = 0; uuid_index < uuid_count; uuid_index++)
6194    {
6195        uuid_details = isA_CFDictionary(CFArrayGetValueAtIndex(powpowHistory, uuid_index));
6196        if (uuid_details) {
6197            uuid = CFDictionaryGetValue(
6198                                uuid_details,
6199                                CFSTR(kIOPMPowerHistoryUUIDKey));
6200            CFStringGetCString(uuid, uuid_cstr, sizeof(uuid_cstr), kCFStringEncodingUTF8);
6201
6202            printf("%-40s|", uuid_cstr);
6203
6204            timestamp = CFDictionaryGetValue(uuid_details,
6205                                       CFSTR(kIOPMPowerHistoryTimestampKey));
6206            CFStringGetCString(timestamp, st, sizeof(st), kCFStringEncodingUTF8);
6207
6208            timestamp = CFDictionaryGetValue(uuid_details,
6209                                       CFSTR(kIOPMPowerHistoryTimestampCompletedKey));
6210            CFStringGetCString(timestamp, ct, sizeof(ct), kCFStringEncodingUTF8);
6211
6212            printf("%-24.24s|%-24.24s|\n", st, ct);
6213        }
6214    }
6215    i = 0;
6216    for(; i < 9; i++)
6217      printf("----------");
6218    printf("\n");
6219exit:
6220    return;
6221}
6222
6223
6224static void printHistoryDetailedEventDictionary(CFDictionaryRef event)
6225{
6226    CFStringRef     evTypeString = NULL;
6227    CFNumberRef     evReasonNum = NULL;
6228    CFNumberRef     evResultNum = NULL;
6229    CFStringRef     evDeviceNameString = NULL;
6230    CFStringRef     evUUIDString = NULL;
6231    CFStringRef     evInterestedDeviceNameString = NULL;
6232    CFNumberRef     evTimestampAbsTime = NULL;
6233    CFNumberRef     evElapsedTimeMicroSec = NULL;
6234    CFNumberRef     evOldState = NULL;
6235    CFNumberRef     evNewState = NULL;
6236
6237    CFAbsoluteTime  ts = 0.0;
6238    int             foo = 0;
6239    int             bar = 0;
6240    char            buf_cstr[40];
6241    char            *display_cstr = NULL;
6242
6243    evTypeString = isA_CFString(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryEventTypeKey)));
6244    evReasonNum = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryEventReasonKey)));
6245    evResultNum = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryEventResultKey)));
6246    evDeviceNameString = isA_CFString(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryDeviceNameKey)));
6247    evUUIDString = isA_CFString(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryUUIDKey)));
6248    evInterestedDeviceNameString = isA_CFString(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryInterestedDeviceNameKey)));
6249    evTimestampAbsTime = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryTimestampKey)));
6250    evOldState = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryOldStateKey)));
6251    evNewState = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryNewStateKey)));
6252    evElapsedTimeMicroSec = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryElapsedTimeUSKey)));
6253
6254    // Timestamp
6255    if (evTimestampAbsTime) {
6256        CFNumberGetValue(evTimestampAbsTime, kCFNumberDoubleType, &ts);
6257        print_pretty_date(ts, false);
6258        printf("|");
6259    }
6260    else
6261      printf("\t");
6262
6263    bool systemEvent = false;
6264
6265    //Event Type
6266    if (evTypeString) {
6267        if (CFStringGetCString(evTypeString, buf_cstr, sizeof(buf_cstr), kCFStringEncodingUTF8)) {
6268            display_cstr = buf_cstr;
6269        } else {
6270            display_cstr = "String encoding error";
6271        }
6272
6273        if(   !strcmp(display_cstr, "UUIDSet")
6274           || !strcmp(display_cstr, "UUIDClear")
6275           || !strcmp(display_cstr, "Sleep")
6276           || !strcmp(display_cstr, "SleepDone")
6277           || !strcmp(display_cstr, "Wake")
6278           || !strcmp(display_cstr, "WakeDone") ) {
6279
6280          systemEvent = true;
6281
6282          // Prints bold lettering on supported systems
6283          printf("%c[1m", (char)27);
6284        }
6285        printf("%-25.25s", display_cstr);
6286        if( systemEvent ) {
6287          printf("%c[0m", (char)27);
6288        }
6289        printf("|");
6290    }
6291    else {
6292        printf("%-25s", " ");
6293    }
6294
6295    // Power State Change
6296    if (evOldState && evNewState) {
6297        CFNumberGetValue(evOldState, kCFNumberIntType, &foo);
6298        CFNumberGetValue(evNewState, kCFNumberIntType, &bar);
6299        printf("%d to %d |", foo, bar);
6300    }
6301    else
6302      printf("%-7s|", " ");
6303
6304    // Reason number
6305    if (evReasonNum) {
6306        CFNumberGetValue(evReasonNum, kCFNumberIntType, &foo);
6307        printf("%-7d|", foo);
6308    }
6309    else
6310      printf("%-7s|", " ");
6311
6312    // Result Number
6313    if (evResultNum) {
6314        CFNumberGetValue(evResultNum, kCFNumberIntType, &foo);
6315        printf("%-7d|", foo);
6316    }
6317    else
6318      printf("%-7s|", " ");
6319
6320    // Device Name
6321    if (evDeviceNameString) {
6322        if (CFStringGetCString(evDeviceNameString, buf_cstr, sizeof(buf_cstr), kCFStringEncodingUTF8)) {
6323            display_cstr = buf_cstr;
6324        } else {
6325            display_cstr = "String encoding error";
6326        }
6327
6328        printf("%-30.30s|", display_cstr);
6329    }
6330    else {
6331      if ( !systemEvent ) {
6332        printf("%-30s|", " ");
6333      }
6334    }
6335
6336    // Event UUID, for system events
6337    if (evUUIDString) {
6338        if (CFStringGetCString(evUUIDString, buf_cstr, sizeof(buf_cstr), kCFStringEncodingUTF8)) {
6339            display_cstr = buf_cstr;
6340        } else {
6341            display_cstr = "String encoding error";
6342        }
6343        // Bold lettering, in supported systems
6344        printf("%c[1m", (char)27);
6345        printf("%-61s", display_cstr);
6346        printf("%c[0m", (char)27);
6347
6348        printf("|");
6349    }
6350
6351    // Interested Device
6352    if (evInterestedDeviceNameString) {
6353        if (CFStringGetCString(evInterestedDeviceNameString, buf_cstr, sizeof(buf_cstr), kCFStringEncodingUTF8)) {
6354            display_cstr = buf_cstr;
6355        } else {
6356            display_cstr = "String encoding error";
6357        }
6358
6359        printf("%-30.30s|", display_cstr);
6360    }
6361    else {
6362      if( !systemEvent ) {
6363        printf("%-30s|", " ");
6364      }
6365    }
6366
6367    // Time Elapsed
6368    if (evElapsedTimeMicroSec) {
6369        CFNumberGetValue(evElapsedTimeMicroSec, kCFNumberIntType, &foo);
6370        printf("%-7d |", foo);
6371    }
6372    else
6373      printf("%-7s|", " ");
6374
6375    printf("\n");
6376}
6377
6378static void mt2bookmark(void)
6379{
6380    mach_port_t     connectIt = MACH_PORT_NULL;
6381    int disregard;
6382
6383    if (kIOReturnSuccess == _pm_connect(&connectIt))
6384    {
6385        io_pm_get_value_int(connectIt, kIOPMMT2Bookmark, &disregard);
6386        _pm_disconnect(connectIt);
6387    }
6388    return;
6389}
6390
6391
6392static void show_power_event_history_detailed(void)
6393{
6394    IOReturn        ret;
6395    CFArrayRef      powpowHistory = NULL;
6396    CFStringRef     uuid = NULL;
6397    char            uuid_cstr[50];
6398    CFDictionaryRef uuid_details;
6399    int             uuid_index;
6400    CFIndex         uuid_count;
6401
6402    ret = IOPMCopyPowerHistory(&powpowHistory);
6403
6404    if (kIOReturnSuccess == kIOReturnNotFound)
6405    {
6406        printf("No power management history to display. (See 'man pmset' to turn on history logging.)\n");
6407        goto exit;
6408    } else if (kIOReturnSuccess != ret)
6409    {
6410        printf("Error reading power management history (0x%08x)\n", ret);
6411        goto exit;
6412    }
6413
6414    uuid_count = CFArrayGetCount(powpowHistory);
6415
6416    //Bold lettering, on supported systems
6417    printf("%c[1m", (char)27);
6418    printf("Power History Detailed:\n");
6419    printf("%c[0m", (char)27);
6420
6421    for (uuid_index = 0; uuid_index < uuid_count; uuid_index++)
6422    {
6423        uuid_details = isA_CFDictionary(CFArrayGetValueAtIndex(powpowHistory, uuid_index));
6424        assert(uuid_details);
6425        if (!uuid_details) {
6426            continue;
6427        }
6428
6429        uuid = CFDictionaryGetValue(uuid_details,
6430                                    CFSTR(kIOPMPowerHistoryUUIDKey));
6431        CFStringGetCString(uuid, uuid_cstr,
6432                           sizeof(uuid_cstr), kCFStringEncodingUTF8);
6433        show_details_for_UUID( (char **)&uuid_cstr );
6434    }
6435
6436    CFRelease(powpowHistory);
6437exit:
6438    return;
6439}
6440
6441static void set_debugFlags(char **argv)
6442{
6443    uint32_t  newFlags, oldFlags;
6444    IOReturn err;
6445
6446    newFlags = (uint32_t)strtol(argv[0], NULL, 0);
6447    if (errno == EINVAL ) {
6448        printf("Invalid argument\n");
6449        return;
6450    }
6451    err = IOPMSetDebugFlags(newFlags, &oldFlags);
6452    if (err == kIOReturnSuccess)
6453        printf("Debug flags changed from 0x%x to 0x%x\n",
6454                oldFlags, newFlags);
6455    else
6456        printf("Failed to change debugFlags. err=0x%x\n", err);
6457
6458}
6459
6460static void set_btInterval(char **argv)
6461{
6462    uint32_t  newInterval, oldInterval;
6463    IOReturn err;
6464
6465    newInterval = (uint32_t)strtol(argv[0], NULL, 0);
6466    if (errno == EINVAL) {
6467        printf("Invalid argument\n");
6468        return;
6469    }
6470    err = IOPMSetBTWakeInterval(newInterval, &oldInterval);
6471    if (err == kIOReturnSuccess)
6472        printf("Background task wake interval changed from %d secs to %d secs\n",
6473                oldInterval, newInterval);
6474    else
6475        printf("Failed to change Background task wake interval. err=0x%x\n", err);
6476
6477}
6478
6479static void set_dwlInterval(char **argv)
6480{
6481    uint32_t newInterval, oldInterval;
6482    IOReturn err;
6483
6484    newInterval = (uint32_t)strtol(argv[0], NULL, 0);
6485    if(errno == EINVAL) {
6486        printf("Invalid argument\n");
6487        return;
6488    }
6489    err = IOPMSetDWLingerInterval(newInterval, &oldInterval);
6490    if(err == kIOReturnSuccess)
6491        printf("DarkWake linger interval changed from %d secs to %d secs\n",
6492                oldInterval, newInterval);
6493    else
6494        printf("Failed to change DarkWake linger interval. err=0x%x\n", err);
6495}
6496
6497static void set_saaFlags(char **argv)
6498{
6499    uint32_t newFlags, oldFlags;
6500    IOReturn err;
6501
6502    newFlags = (uint32_t)strtol(argv[0], NULL, 0);
6503    if(errno == EINVAL) {
6504        printf("Invalid argument\n");
6505        return;
6506    }
6507
6508    err = IOPMChangeSystemActivityAssertionBehavior(newFlags, &oldFlags);
6509    if(err == kIOReturnSuccess)
6510        printf("System activity assertion behavior changed from %u to %d\n",
6511                oldFlags, newFlags);
6512    else
6513        printf("Failed to change system activity assertion behavior. err=0x%x\n", err);
6514}
6515
6516static bool isBatteryPollingStopped(void)
6517{
6518    int                 myNotifyToken = 0;
6519    uint64_t            packedBatteryData = 0;
6520    int                 myNotifyStatus = 0;
6521
6522    myNotifyStatus = notify_register_check(kIOPSTimeRemainingNotificationKey, &myNotifyToken);
6523
6524    if (NOTIFY_STATUS_OK == myNotifyStatus) {
6525        notify_get_state(myNotifyToken, &packedBatteryData);
6526        notify_cancel(myNotifyToken);
6527    }
6528
6529    return (packedBatteryData & kPSTimeRemainingNotifyNoPollBit) ? 1:0;
6530}
6531
6532static void set_nopoll(void)
6533{
6534    mach_port_t     connectIt = MACH_PORT_NULL;
6535    bool            old_nopoll = isBatteryPollingStopped();
6536    int             rc = kIOReturnSuccess;
6537
6538    if (kIOReturnSuccess == _pm_connect(&connectIt))
6539    {
6540        printf("Turning battery polling: %s\n", old_nopoll ? "On":"Off");
6541        io_pm_set_value_int(connectIt, kIOPMSetNoPoll, old_nopoll ? 0:1, &rc);
6542        _pm_disconnect(connectIt);
6543    } else {
6544        printf("Error: could not connect to powerd.\n");
6545    }
6546
6547    if (!old_nopoll) {
6548        printf("Battery updates are stopped. Run \"pmset nopoll\" again, or reboot the system to resume.\n");
6549    }
6550}
6551
6552static void set_new_power_bookmark(void) {
6553  printf("Bookmarked: Deprecated. Did not set a bookmark. \n");
6554}
6555
6556static void show_details_for_UUID( char **argv ) {
6557
6558  char *uuid_cstr = argv[0];
6559
6560  if (!uuid_cstr) return;
6561
6562  string_toupper(uuid_cstr, uuid_cstr);
6563  CFStringRef uuid = CFStringCreateWithCString( kCFAllocatorDefault,
6564                                                uuid_cstr,
6565                                                kCFStringEncodingUTF8);
6566  if( uuid == NULL )
6567    return;
6568
6569  CFArrayRef event_array;
6570  CFDictionaryRef uuid_details;
6571
6572  IOReturn ret = IOPMCopyPowerHistoryDetailed(uuid, &uuid_details);
6573  if (kIOReturnSuccess != ret)
6574  {
6575    printf("No power management history to display for this UUID! \n");
6576      CFRelease(uuid);
6577    return;
6578  }
6579  if (!uuid_details)
6580  {
6581    printf("No power management history available for this UUID! \n");
6582    CFRelease(uuid);
6583    return;
6584  }
6585
6586  CFNumberRef timestamp;
6587  CFAbsoluteTime set_time   = 0.0;
6588  CFAbsoluteTime clear_time = 0.0;
6589
6590  timestamp = isA_CFNumber(
6591                  CFDictionaryGetValue(uuid_details,
6592                                       CFSTR(kIOPMPowerHistoryTimestampKey)));
6593
6594  CFNumberGetValue(timestamp, kCFNumberDoubleType, &set_time);
6595
6596  timestamp = isA_CFNumber(
6597                  CFDictionaryGetValue(
6598                              uuid_details,
6599                              CFSTR(kIOPMPowerHistoryTimestampCompletedKey)));
6600
6601  CFNumberGetValue(timestamp, kCFNumberDoubleType, &clear_time);
6602  //Bold lettering, on supported systems
6603
6604  printf("%c[1m", (char)27);
6605
6606  // Hacky way of centering the UUID title
6607  printf("\t\t\t\t\t *UUID =  %s\n", uuid_cstr);
6608  // No more bold lettering
6609  printf("%c[0m", (char)27);
6610
6611  // Print column headers, make nice table to display
6612  // power events under this UUID
6613  int i = 0;
6614  for(; i < 144; i+= 12)
6615    printf("------------");
6616  printf("--\n");
6617
6618  printf("%-24s|", "Timestamp");
6619  printf("%-25s|", "Event Type");
6620  printf("%-7s|", "Change");
6621  printf("%-7s|", "Reason");
6622  printf("%-7s|", "Result");
6623  printf("%-30s|","Device Name");
6624  printf("%-30s|","Interested Device");
6625  printf("Time(uS)|");
6626  printf("\n");
6627
6628  i = 0;
6629  for(; i < 144; i+= 12)
6630    printf("------------");
6631  printf("--\n");
6632
6633  event_array = CFDictionaryGetValue(uuid_details,
6634                                     CFSTR(kIOPMPowerHistoryEventArrayKey));
6635  CFIndex event_count = CFArrayGetCount(event_array);
6636  int event_index;
6637  CFDictionaryRef an_event;
6638
6639  // Print out individual event details
6640  for (event_index = 0; event_index < event_count; event_index++)
6641  {
6642    an_event = isA_CFDictionary(CFArrayGetValueAtIndex(event_array, event_index));
6643    assert(an_event);
6644    if (!an_event)
6645      continue;
6646    printHistoryDetailedEventDictionary(an_event);
6647  }
6648
6649  i = 0;
6650  for(; i < 144; i+= 12)
6651    printf("------------");
6652  printf("--\n");
6653
6654  printf("\t Total of ");
6655
6656  printf("%c[1m", (char)27); // Bold letters
6657  printf("%ld ", event_count);
6658  printf("%c[0m", (char)27); // Un-bold letters
6659
6660  printf("events under UUID ");
6661
6662  printf("%c[1m", (char)27); // Bold letters
6663  printf("%s ", uuid_cstr);
6664  printf("%c[0m", (char)27); // Un-bold letters
6665  printf("from ");
6666  printf("%c[1m", (char)27);
6667  print_pretty_date(set_time, false);
6668  printf("%c[0m", (char)27);
6669  printf("to ");
6670  printf("%c[1m", (char)27);
6671  print_pretty_date(clear_time, true);
6672  printf("%c[0m", (char)27);
6673
6674  // Done with our CFObjects. Don't want to own them anymore
6675  CFRelease(event_array);
6676  CFRelease(uuid);
6677}
6678
6679static void _print_uuid_string(){
6680    CFStringRef     _uuid = IOPMSleepWakeCopyUUID();
6681    char            str[kMaxLongStringLength];
6682
6683    if (!_uuid) {
6684        printf("(NULL)\n");
6685        return;
6686    }
6687
6688    CFStringGetCString(_uuid, str, sizeof(str), kCFStringEncodingUTF8);
6689    printf("%s\n", str);
6690    CFRelease(_uuid);
6691}
6692static void _show_uuid_handler(
6693    void *refcon,
6694    io_service_t batt,
6695    natural_t messageType,
6696    void *messageArgument)
6697{
6698    if (messageType != kIOPMMessageSleepWakeUUIDChange)
6699        return;
6700
6701    print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
6702
6703    if (messageArgument == (void *)kIOPMMessageSleepWakeUUIDCleared) {
6704        printf("Cleared.\n");
6705    } else if (messageArgument == (void *)kIOPMMessageSleepWakeUUIDSet) {
6706        _print_uuid_string();
6707    }
6708}
6709
6710static void show_uuid(bool keep_running)
6711{
6712    if (!keep_running) {
6713        _print_uuid_string();
6714        return;
6715    }
6716
6717    io_registry_entry_t     rd = copyRootDomainRef();
6718    IONotificationPortRef   notify = NULL;
6719    io_object_t             notification_ref = IO_OBJECT_NULL;
6720
6721    notify = IONotificationPortCreate(kIOMasterPortDefault);
6722    IONotificationPortSetDispatchQueue(notify, dispatch_get_main_queue());
6723
6724    IOServiceAddInterestNotification(notify, rd,
6725                                     kIOGeneralInterest, _show_uuid_handler,
6726                                     NULL, &notification_ref);
6727     install_listen_IORegisterForSystemPower();
6728     printf("Logging UUID changes.\n");
6729
6730    print_pretty_date(CFAbsoluteTimeGetCurrent(), false);
6731    _print_uuid_string();
6732
6733    CFRunLoopRun();
6734}
6735
6736
6737#if !TARGET_OS_EMBEDDED
6738static void show_NULL_HID_events(void)
6739{
6740    CFArrayRef          systemHIDEvents = NULL;
6741    IOReturn            ret;
6742    CFIndex             topLevelCount = 0;
6743
6744    ret = IOPMCopyHIDPostEventHistory(&systemHIDEvents);
6745    if (kIOReturnNotFound == ret) {
6746        // System is not collecting HID event history.
6747        // Assuming this is a setting that you can turn off with a hidden pmset flag,
6748        // then kIOReturnNotFound indicates it's turned off.
6749        printf("FAIL: ret=0x%08x kIOReturnNotFound - HID event capturing is OFF\n", ret);
6750        goto exit;
6751    } else if (kIOReturnSuccess != ret) {
6752        // Any other non-success return indicates a failure.
6753        printf("FAIL: ret=0x%08x - unexpected error\n", ret);
6754        return;
6755    }
6756
6757    if (!systemHIDEvents || (0 == (topLevelCount = CFArrayGetCount(systemHIDEvents))))
6758    {
6759        printf("PASS: kIOReturnSuccess with %s\n", systemHIDEvents?"zero events":"no returned dictionary");
6760        goto exit;
6761    }
6762
6763    int i;
6764    for (i=0; i<topLevelCount; i++)
6765    {
6766        CFDictionaryRef     d = CFArrayGetValueAtIndex(systemHIDEvents, i);
6767        char                app_path_string[1024];
6768        CFStringRef         appPathString = NULL;
6769        CFArrayRef          dataList = NULL;
6770        CFDataRef           dataChunk = NULL;
6771        IOPMHIDPostEventActivityWindow  *bucket = NULL;
6772        CFNumberRef         pidNum = NULL;
6773        int                 _pid = 0;
6774
6775        printf("\n");
6776
6777        pidNum = CFDictionaryGetValue(d, kIOPMHIDAppPIDKey);
6778        CFNumberGetValue(pidNum, kCFNumberIntType, &_pid);
6779        printf("* PID = %d\n", _pid);
6780
6781        appPathString = CFDictionaryGetValue(d, kIOPMHIDAppPathKey);
6782        if (appPathString
6783            && CFStringGetCString(appPathString, app_path_string, sizeof(app_path_string), kCFStringEncodingMacRoman))
6784        {
6785            printf(" Name = %s\n", app_path_string);
6786        } else {
6787            printf(" Name = unknown\n");
6788        }
6789
6790        dataList = CFDictionaryGetValue(d, kIOPMHIDHistoryArrayKey);
6791        int j;
6792        for (j=0; j<CFArrayGetCount(dataList); j++)
6793        {
6794            dataChunk = CFArrayGetValueAtIndex(dataList, j);
6795            bucket = (IOPMHIDPostEventActivityWindow *)CFDataGetBytePtr(dataChunk);
6796            printf(" Bucket (5 minute) starts: ");
6797            print_pretty_date(bucket->eventWindowStart, true);
6798            printf("   NULL events = %d\n", bucket->nullEventCount);
6799            printf("   Non-NULL events = %d\n", bucket->hidEventCount);
6800        }
6801
6802    }
6803
6804exit:
6805    if (systemHIDEvents)
6806        CFRelease(systemHIDEvents);
6807    return;
6808}
6809#endif
6810
6811static bool is_display_dim_captured(void)
6812{
6813    io_registry_entry_t disp_wrangler = IO_OBJECT_NULL;
6814    CFBooleanRef dimCaptured          = NULL;
6815    bool ret                          = false;
6816
6817    disp_wrangler = IORegistryEntryFromPath(
6818                            kIOMasterPortDefault,
6819                            kIOServicePlane ":/IOResources/IODisplayWrangler");
6820    if(!disp_wrangler)
6821        return false;
6822
6823    dimCaptured = IORegistryEntryCreateCFProperty(
6824                        disp_wrangler,
6825                        CFSTR("DimCaptured"),
6826                        kCFAllocatorDefault,
6827                        kNilOptions);
6828
6829    if(dimCaptured)
6830    {
6831        ret = (kCFBooleanTrue == dimCaptured);
6832        CFRelease(dimCaptured);
6833    }
6834
6835    IOObjectRelease(disp_wrangler);
6836
6837    return ret;
6838}
6839#define kRootDomainUserClientClass 	"RootDomainUserClient"
6840static void show_root_domain_user_clients(void)
6841{
6842	io_registry_entry_t		_rootdomain = copyRootDomainRef();
6843	io_iterator_t			_matchingUserClients = IO_OBJECT_NULL;
6844	io_registry_entry_t		_iter = IO_OBJECT_NULL;
6845	kern_return_t			kr;
6846
6847	if (!_rootdomain) {
6848		printf("Internal Error - can't find root domain.");
6849		return;
6850	}
6851
6852	kr = IORegistryEntryGetChildIterator(_rootdomain, kIOServicePlane, &_matchingUserClients);
6853	if (kr != KERN_SUCCESS || !_matchingUserClients) {
6854		printf("Internal Error - can't find user clients. (kern_return_t error = %d)", kr);
6855		return;
6856	}
6857
6858	while ( ( _iter = IOIteratorNext(_matchingUserClients) ) )
6859	{
6860		io_name_t 			objectClass;
6861
6862		IOObjectGetClass((io_object_t)_iter, objectClass);
6863		if (!strncmp(objectClass, kRootDomainUserClientClass, strlen(kRootDomainUserClientClass)))
6864		{
6865			CFStringRef 	creatorString = NULL;
6866			char			stringBuf[kMaxLongStringLength];
6867
6868			creatorString = (CFStringRef)IORegistryEntryCreateCFProperty(_iter, CFSTR(kIOUserClientCreatorKey), 0, 0);
6869			if (creatorString
6870			&& CFStringGetCString(creatorString, stringBuf, sizeof(stringBuf), kCFStringEncodingMacRoman))
6871			{
6872				printf(" - %s\n", stringBuf);
6873			}
6874
6875            if(creatorString)
6876                CFRelease(creatorString);
6877		}
6878	}
6879
6880	IOObjectRelease(_matchingUserClients);
6881	IOObjectRelease(_rootdomain);
6882
6883	return;
6884}
6885
6886static void show_getters(void)
6887{
6888    int i = 0;
6889    for (i=0; i<the_getters_count; i++)
6890    {
6891        if (the_getters[i].actionType == kActionGetOnceNoArgs) {
6892            printf("%s\n", the_getters[i].arg);
6893        }
6894    }
6895}
6896
6897void fetchChannelData( char     *object,
6898    uint64_t                channel_id,
6899    bool                    print_error,
6900    void                    (^processChannelData)(uint64_t, CFStringRef))
6901{
6902    CFMutableDictionaryRef  desiredChs = NULL, subbedChs = NULL;
6903    CFDictionaryRef 		mdict  = NULL;
6904    IOReportSubscriptionRef iorsub = NULL;
6905    CFDictionaryRef         samples = NULL;
6906
6907
6908    if (!(mdict = IOServiceMatching(object))) {
6909        printf("Failed to match an object with name %s in registry\n", object);
6910        goto exit;
6911    }
6912    desiredChs = IOReportCopyChannelsWithID(mdict, channel_id, NULL);
6913    if (!desiredChs) {
6914        if (print_error)
6915            printf("Failed to find channel reporting power state for the object %s\n", object);
6916        goto exit;
6917    }
6918    if (!(iorsub = IOReportCreateSubscription(nil, desiredChs, &subbedChs, 0, NULL))) {
6919            if (print_error)
6920                printf("Internal failure: Failed to get power state information\n");
6921        goto exit;
6922    }
6923
6924
6925    if ((samples = IOReportCreateSamples(iorsub, subbedChs, NULL))) {
6926        IOReportIterate(samples, ^(IOReportSampleRef ch) {
6927
6928            uint64_t curstate = IOReportSimpleGetIntegerValue(ch, NULL);
6929            CFStringRef drv_name = IOReportChannelGetDriverName(ch);
6930
6931            processChannelData(curstate, drv_name);
6932            return kIOReportIterOk;
6933        });
6934	}
6935    else {
6936        if (print_error)
6937            printf("Internal failure: Failed to get power state information\n");
6938        goto exit;
6939    }
6940
6941
6942exit:
6943    if (iorsub) CFRelease(iorsub);
6944    if (subbedChs)  CFRelease(subbedChs);
6945    if (desiredChs) CFRelease(desiredChs);
6946    if (mdict) CFRelease(mdict);
6947
6948
6949    return;
6950
6951}
6952
6953
6954void display_powerstate( char *object, bool print_error)
6955{
6956    static  bool            row1 = true;
6957
6958
6959    if (row1) {
6960        printf("\n%15s  %13s  %9s  %s\n", "Driver ID", "Current State", "Max State", "Current State Description");
6961        row1= false;
6962    }
6963
6964    fetchChannelData(object, kPMCurrStateChID, print_error,  ^(uint64_t state_id, CFStringRef drv_name) {
6965        bool is_on = false, is_usable = false, is_lowpower = false;
6966        uint32_t cur_st=0, max_st=0;
6967        CFNumberRef objRef = NULL;
6968        const char *dname_cstr;
6969        char dname_buf[25], *spcptr;
6970
6971        // making this name useful is one reason this code might be better
6972        // in ioreg :P
6973        dname_cstr = CFStringGetCStringPtr(drv_name, kCFStringEncodingUTF8);
6974        if (!dname_cstr)    dname_cstr = "missing";
6975        snprintf(dname_buf, sizeof(dname_buf), "%s", dname_cstr);
6976        if ((spcptr = strchr(dname_buf, ' ')))        *spcptr = '\0';
6977
6978
6979        CFDictionaryRef dict = IOPMCopyPowerStateInfo(state_id);
6980        if (!dict) {
6981            printf("Internal error: Failed to obtain power state information for driver %s\n", dname_cstr);
6982            return ;
6983        }
6984        objRef = CFDictionaryGetValue(dict, kIOPMNodeCurrentState);
6985        if (objRef)
6986            CFNumberGetValue(objRef, kCFNumberIntType, &cur_st);
6987
6988        objRef = CFDictionaryGetValue(dict, kIOPMNodeMaxState);
6989        if (objRef)
6990            CFNumberGetValue(objRef, kCFNumberIntType, &max_st);
6991
6992        is_on = (CFDictionaryGetValue(dict, kIOPMNodeIsPowerOn) == kCFBooleanTrue) ? true : false;
6993        is_usable = (CFDictionaryGetValue(dict, kIOPMNodeIsDeviceUsable) == kCFBooleanTrue) ? true : false;
6994        is_lowpower = (CFDictionaryGetValue(dict, kIOPMNodeIsLowPower) == kCFBooleanTrue) ? true : false;
6995
6996
6997
6998        printf("%-25s %3d  %9d  ", dname_buf, cur_st, max_st);
6999        if ( (is_on || is_usable || is_lowpower) == false) printf("None\n");
7000        else {
7001            bool comma = false;
7002            if (is_on) {
7003                printf("ON");
7004                comma = true;
7005            }
7006            if (is_usable) {
7007                if (comma) printf(",");
7008                printf("USEABLE");
7009                comma = true;
7010            }
7011            if (is_lowpower) {
7012                if (comma) printf(",");
7013                printf("LOW_POWER");
7014            }
7015            printf("\n");
7016        }
7017        if (dict) CFRelease(dict);
7018        return ;
7019    });
7020
7021
7022    return;
7023}
7024
7025
7026
7027void scan_powerplane(io_registry_entry_t service)
7028{
7029    io_registry_entry_t child       = 0; // (needs release)
7030    io_registry_entry_t childUpNext = 0; // (don't release)
7031    io_iterator_t       children    = 0; // (needs release)
7032    io_name_t           name;
7033    kern_return_t       status      = KERN_SUCCESS;
7034
7035
7036    status = IORegistryEntryGetChildIterator(service, "IOPower", &children);
7037    if (status != KERN_SUCCESS) {
7038        return;
7039    }
7040
7041    childUpNext = IOIteratorNext(children);
7042
7043    status = IORegistryEntryGetNameInPlane(service, "IOPower", name);
7044
7045    if (strncmp(name, "IOPowerConnection", sizeof("IOPowerConnection"))) {
7046
7047        display_powerstate(name, false);
7048    }
7049
7050
7051    while (childUpNext) {
7052        child       = childUpNext;
7053        childUpNext = IOIteratorNext(children);
7054
7055        scan_powerplane(child);
7056
7057        IOObjectRelease(child);
7058    }
7059
7060    IOObjectRelease(children);
7061
7062}
7063static void show_power_state(char **argv)
7064{
7065    char                    *object = NULL;
7066    int                     i = 0, cnt = 0;
7067    io_registry_entry_t     service  = 0;
7068
7069    if (argv[i] != NULL) {
7070        object = argv[i++];
7071
7072        do {
7073            display_powerstate(object, true);
7074            cnt++;
7075        } while ((object = argv[i++]) != NULL);
7076        if (cnt == 0) goto exit;
7077    }
7078    else if ((service = IORegistryGetRootEntry(kIOMasterPortDefault)) != 0) {
7079        scan_powerplane(service);
7080        IOObjectRelease(service);
7081        goto exit;
7082    }
7083    else {
7084        printf("Internal failure: Failed to get the registry root entry\n");
7085        goto exit;
7086    }
7087
7088exit:
7089    ;   // C doesn't allow labels at the end of functions?
7090}
7091
7092static void display_statelog(IOReportChannelRef ch, int nobjects)
7093{
7094    uint32_t nstates, i;
7095    uint64_t state_id, transitions, ticks;
7096    uint64_t drv_name = IOReportChannelGetDriverName(ch);
7097    const char *dname_cstr;
7098    char dname_buf[22], *spcptr;
7099    uint32_t max_st=0;
7100    CFNumberRef objRef = NULL;
7101    CFDictionaryRef dict;
7102    static int max_states = 0;
7103    static int cnt = 0;
7104    int cur_state;
7105
7106
7107    nstates = IOReportStateGetCount(ch);
7108    if (cnt < nobjects) {
7109        for (i=0; i<nstates; i++) {
7110            state_id = IOReportStateGetIDForIndex(ch, i);
7111
7112            dict = IOPMCopyPowerStateInfo(state_id);
7113            if (!dict) continue;
7114
7115            objRef = CFDictionaryGetValue(dict, kIOPMNodeMaxState);
7116            if (objRef) {
7117                CFNumberGetValue(objRef, kCFNumberIntType, &max_st);
7118                if (max_st+1 > max_states) max_states=max_st+1;
7119            }
7120
7121            CFRelease(dict);
7122        }
7123
7124        cnt++;
7125        return;
7126    }
7127
7128    cur_state = IOReportStateGetCurrent(ch);
7129    if ((cnt-nobjects) % (10*nobjects) == 0) {
7130        printf("\n");
7131        print_pretty_date(CFAbsoluteTimeGetCurrent(), true);
7132        printf("%-18s ", "    Driver");
7133        for (i=0; i < max_states; i++) {
7134            printf("%8s[%d] ", "Time", i);
7135        }
7136        printf("       ");
7137        for (i=0; i < max_states; i++) {
7138            printf("%8s[%d] ", "Entries", i);
7139        }
7140        printf("\n");
7141    }
7142
7143    // making this name useful is one reason this code might be better
7144    // in ioreg :P
7145    dname_cstr = CFStringGetCStringPtr(drv_name, kCFStringEncodingUTF8);
7146    if (!dname_cstr)    dname_cstr = "missing";
7147    snprintf(dname_buf, sizeof(dname_buf), "%s", dname_cstr);
7148    if ((spcptr = strchr(dname_buf, ' ')))        *spcptr = '\0';
7149
7150
7151    printf("%-22s ", dname_buf);
7152    for (i=0; i<nstates; i++) {
7153        ticks = IOReportStateGetResidency(ch, i);
7154        if (cur_state == i)
7155            printf("*%#-11llx", ticks);
7156        else
7157            printf("%#-12llx", ticks);
7158    }
7159    for (;i < max_states; i++) {
7160        printf("%-12s ", " ");
7161    }
7162    printf("    ");
7163    for (i=0; i<nstates; i++) {
7164        transitions = IOReportStateGetInTransitions(ch, i);
7165        printf("%-11lld ", transitions);
7166    }
7167    for (;i < max_states; i++) {
7168        printf("%-11s ", " ");
7169    }
7170
7171    printf("\n");
7172
7173    cnt++;
7174}
7175
7176
7177static void show_power_statelog(char **argv)
7178{
7179    CFDictionaryRef 		mdict = NULL;
7180    IOReportSubscriptionRef sub = NULL;
7181    CFMutableDictionaryRef  desiredChs = NULL, subbedChs = NULL;
7182    CFDictionaryRef         current = NULL, diff = NULL;
7183    CFDictionaryRef         prev = NULL;
7184    char                    *object = NULL;
7185    int                     i = 0, nobjects = 0;
7186    long                    interval = 0;
7187
7188    if (argv[i] != NULL) {
7189        if (!strncmp(argv[i], "-i", sizeof("-i"))) {
7190            interval = strtol(argv[i+1], NULL, 0);
7191            i += 2;
7192        }
7193    }
7194
7195    if (argv[i] != NULL)
7196        object = argv[i++];
7197    else
7198        object = "IOPMrootDomain";
7199
7200    if (!interval) interval = 5;
7201    do {
7202        if (!(mdict = IOServiceMatching(object))) {
7203            printf("Failed to match an object with name %s in registry\n", object);
7204            continue;
7205        }
7206
7207        desiredChs = IOReportCopyChannelsWithID(mdict, kPMPowerStatesChID, NULL);
7208        CFRelease(mdict); mdict = NULL;
7209
7210        if (!desiredChs) {
7211            printf("Failed to find channel reporting power state for the object %s\n", object);
7212            continue;
7213        }
7214        nobjects++;
7215    } while ((object = argv[i++]) != NULL);
7216
7217    if (nobjects == 0) goto exit;
7218
7219	if (!(sub = IOReportCreateSubscription(nil, desiredChs, &subbedChs, 0, NULL))) {
7220        printf("Internal failure: Failed to get power state information\n");
7221        goto exit;
7222	}
7223
7224    printf("Polling at %ld secs interval\n", interval);
7225    while ((current = IOReportCreateSamples(sub, subbedChs, NULL))) {
7226        if (prev) {
7227            diff = IOReportCreateSamplesDelta(prev, current, NULL);
7228            if (!diff) {
7229                printf("failed to compare power state to previous state");
7230                goto exit;
7231            }
7232            CFRelease(prev);
7233            prev = current;
7234            // samples = diff;
7235        }
7236        else {
7237            prev = current;
7238        }
7239        IOReportIterate(diff, ^(IOReportChannelRef ch) {
7240            display_statelog(ch, nobjects);
7241
7242            return kIOReportIterOk;
7243        });
7244
7245        sleep((int)interval);
7246	}
7247
7248exit:
7249    if (sub) CFRelease(sub);
7250    if (desiredChs) CFRelease(desiredChs);
7251    if (subbedChs) CFRelease(subbedChs);
7252}
7253
7254static void show_rdStats(char **argv)
7255{
7256
7257    fetchChannelData("IOPMrootDomain", kSleepCntChID, true,
7258            ^(uint64_t state_id, CFStringRef drv_name){ printf("Sleep Count:%lld\n", state_id); } );
7259
7260    fetchChannelData("IOPMrootDomain", kDarkWkCntChID, true,
7261            ^(uint64_t state_id, CFStringRef drv_name){ printf("Dark Wake Count:%lld\n", state_id); } );
7262
7263    fetchChannelData("IOPMrootDomain", kUserWkCntChID, true,
7264            ^(uint64_t state_id, CFStringRef drv_name){ printf("User Wake Count:%lld\n", state_id); } );
7265
7266}
7267
7268static void cancelAggregates( int param )
7269{
7270    IOPMSetAssertionActivityAggregate(false);
7271    exit(0);
7272}
7273
7274static void show_sleep_blockers(char **argv)
7275{
7276    IOReturn ret;
7277    CFDictionaryRef basis = NULL;
7278    CFDictionaryRef update = NULL;
7279    IOReportSampleRef   delta;
7280    int iter_cnt = 0;
7281    __block int cnt = 0;
7282    long    interval = 0;
7283
7284    if (argv[0] != NULL) {
7285        if (!strncmp(argv[0], "-i", sizeof("-i"))) {
7286            interval = strtol(argv[1], NULL, 0);
7287        }
7288    }
7289    if (!interval) interval = 60;
7290
7291    ret = IOPMSetAssertionActivityAggregate(true);
7292    if (ret != kIOReturnSuccess) {
7293        printf("Failed to enable aggregation of assertion activity\n");
7294        return;
7295    }
7296
7297    signal(SIGINT, cancelAggregates);
7298
7299    printf("Polling for sleep blockers at %ld secs interval\n", interval);
7300    basis = IOPMCopyAssertionActivityAggregate( );
7301    while (true) {
7302
7303        if((iter_cnt++ % 5) == 0) {
7304            printf("\n%-25s %15s %15s %15s\n", "Process(PID)", "Idle Sleep", "Demand Sleep", "Display Sleep");
7305        }
7306
7307        sleep(interval);
7308        printf("\n");
7309        print_compact_date(CFAbsoluteTimeGetCurrent(), true);
7310        update = IOPMCopyAssertionActivityAggregate( );
7311
7312        if (basis && update) {
7313            delta = IOReportCreateSamplesDelta(basis, update, NULL);
7314        }
7315        else if (update) {
7316            delta = CFDictionaryCreateMutableCopy(NULL, 0, update);
7317        }
7318        else if (basis) {
7319            // Can't have basis without update unless there is some error
7320            printf("Failed to get updated aggregate assertion activity\n");
7321            continue;
7322        }
7323        else {
7324            printf("--- No blockers ---\n");
7325            continue;
7326        }
7327        if (!delta) {
7328            printf("Failed to get delta\n");
7329            continue;
7330        }
7331
7332        cnt = 0;
7333        IOReportIterate(delta, ^(IOReportChannelRef ch) {
7334            int64_t     eff1, eff2, eff3;
7335            char name[2*MAXCOMLEN];
7336            pid_t pid;
7337
7338            eff1 = IOReportArrayGetValueAtIndex(ch, 1); // Idle Sleep
7339            eff2 = IOReportArrayGetValueAtIndex(ch, 2); // Demand Sleep
7340            eff3 = IOReportArrayGetValueAtIndex(ch, 3); // Display Sleep
7341
7342            if (eff1 < 0 || eff2 < 0 ||eff3 < 0) {
7343                // We shouldn't be getting negative values
7344                cnt++;
7345                return kIOReportIterOk;
7346            }
7347
7348            if (eff1 || eff2 || eff3) {
7349
7350                pid = IOReportChannelGetChannelID(ch);
7351                name[0] = 0;
7352                proc_name(pid, name, sizeof(name));
7353                snprintf(name, MAXCOMLEN, "%s", name);
7354                snprintf(name, sizeof(name), "%s(%d)", name, pid);
7355                printf("%-25s ", name);
7356                printf("%15lld %15lld %15lld\n", eff1, eff2, eff3);
7357                cnt++;
7358            }
7359            return kIOReportIterOk;
7360        });
7361
7362        if (cnt == 0) {
7363            printf("--- No blockers ---\n");
7364            cnt++;
7365        }
7366
7367        CFRelease(delta);
7368        if (basis) CFRelease(basis);
7369        basis = update;
7370    }
7371
7372    IOPMSetAssertionActivityAggregate(false);
7373}
7374
7375#define kIOPMSystemCapabilitiesKey  "System Capabilities"
7376#define kPwrMgtKey                  "IOPowerManagement"
7377static void show_sysstate(char **argv)
7378{
7379    CFMutableDictionaryRef  rdProps = NULL;
7380    CFDictionaryRef  states = NULL;
7381    io_registry_entry_t rootDomain = copyRootDomainRef();
7382    CFNumberRef caps_cf = NULL, currSt_cf = NULL, desiredSt_cf = NULL;
7383    uint32_t caps;
7384    unsigned long currSt, desiredSt;
7385
7386    IORegistryEntryCreateCFProperties(rootDomain, &rdProps, 0, 0);
7387
7388    if (!rdProps) {
7389        printf("Internal error: Failed to get IOPMrootDomain properties\n");
7390        goto exit;
7391    }
7392
7393    caps_cf = CFDictionaryGetValue(rdProps, CFSTR(kIOPMSystemCapabilitiesKey));
7394    if (caps_cf) {
7395        CFNumberGetValue(caps_cf, kCFNumberIntType, &caps);
7396        printf("Current System Capabilities are: ");
7397        if (caps) {
7398            if (caps & kIOPMSystemCapabilityCPU) printf("CPU ");
7399            if (caps & kIOPMSystemCapabilityGraphics) printf("Graphics ");
7400            if (caps & kIOPMSystemCapabilityAudio) printf("Audio ");
7401            if (caps & kIOPMSystemCapabilityNetwork) printf("Network ");
7402        }
7403        else {
7404            printf("None");
7405        }
7406        printf("\n");
7407    }
7408
7409    states = CFDictionaryGetValue(rdProps, CFSTR(kPwrMgtKey));
7410    if (!states) goto exit;
7411
7412    currSt_cf = CFDictionaryGetValue(states, CFSTR("CurrentPowerState"));
7413    if (currSt_cf) {
7414        CFNumberGetValue(currSt_cf, kCFNumberLongType, &currSt);
7415        printf("Current Power State: %lu\n", currSt);
7416    }
7417    desiredSt_cf = CFDictionaryGetValue(states, CFSTR("DesiredPowerState"));
7418    if (desiredSt_cf) {
7419        CFNumberGetValue(desiredSt_cf, kCFNumberLongType, &desiredSt);
7420        if (desiredSt != currSt) {
7421            printf("Desired State: %lu\n", desiredSt);
7422            if (desiredSt == 1)
7423                printf("System restart is in progress\n");
7424            else if(desiredSt == 2)
7425                printf("System State is changing to Sleep\n");
7426            else if (desiredSt == 3)
7427                printf("System is waking from sleep\n");
7428        }
7429    }
7430
7431exit:
7432    if (rootDomain) IOObjectRelease(rootDomain);
7433    if (rdProps) CFRelease(rdProps);
7434
7435}
7436
7437#if !TARGET_OS_EMBEDDED
7438
7439static void get_sw_failure_string(long boottime, char *failure, size_t len)
7440{
7441    asl_object_t        msg, store, msgList = NULL;
7442    char    timestr[20];
7443    const char    *str;
7444    size_t  cnt;
7445
7446    snprintf(timestr, sizeof(timestr), "%ld", boottime);
7447
7448    store = open_pm_asl_store();
7449    asl_object_t cq = asl_new(ASL_TYPE_QUERY);
7450    if (cq == NULL)  return;
7451
7452    asl_set_query(cq, kPMASLDomainKey, kPMASLDomainSWFailure, ASL_QUERY_OP_EQUAL);
7453    asl_set_query(cq, ASL_KEY_TIME, timestr, ASL_QUERY_OP_GREATER_EQUAL);
7454
7455    msgList = asl_search(store, cq);
7456
7457    cnt = asl_count(msgList);
7458    if (cnt == 0) {
7459        goto exit;
7460    }
7461
7462    msg = asl_get_index(msgList, cnt-1);
7463    str = asl_get(msg, ASL_KEY_MSG);
7464    strncpy(failure, str, len);
7465exit:
7466
7467    asl_release(cq);
7468
7469}
7470
7471void get_sw_stackshot_fname(long boottime, char *str, size_t len)
7472{
7473    DIR *dirp;
7474    struct dirent *dp;
7475    char fname[128];
7476    struct stat fstats;
7477
7478    dirp = opendir("/Library/Logs/DiagnosticReports");
7479    if (dirp == NULL) {
7480        return ;
7481    }
7482
7483    while ((dp = readdir(dirp)) != NULL) {
7484        char *filename      = "Sleep Wake Failure";
7485        size_t filename_len = sizeof("Sleep Wake Failure");
7486
7487        if ((strnstr(dp->d_name, filename, filename_len) == dp->d_name)
7488                    && (dp->d_type == DT_REG)) {
7489            snprintf(fname, sizeof(fname), "/Library/Logs/DiagnosticReports/%s", dp->d_name);
7490            stat(fname, &fstats);
7491
7492            if (S_ISREG(fstats.st_mode) && (fstats.st_birthtime > boottime)) {
7493               snprintf(str, len, "%s", dp->d_name);
7494               break;
7495            }
7496        }
7497    }
7498
7499}
7500
7501
7502static void print_fba(char **argv)
7503{
7504    char str[200];
7505    struct timeval ts_boot;
7506    size_t  size;
7507
7508    memset(&ts_boot, 0, sizeof(ts_boot));
7509    size = sizeof(ts_boot);
7510    sysctlbyname("kern.boottime", &ts_boot, &size, NULL, 0);
7511
7512    printf("{\n");
7513    str[0] = 0;
7514    size = sizeof(str);
7515    sysctlbyname("hw.model", &str, &size, NULL, 0);
7516    if (str[0] != 0) {
7517        printf("\t\"Model\" : \"%s\",\n", str);
7518    }
7519
7520    str[0] = 0;
7521    get_sw_failure_string(ts_boot.tv_sec, str, sizeof(str));
7522    if (str[0] != 0) {
7523        printf("\t\"sleep_wake_failure_code\" : \"%s\",\n", str);
7524    }
7525    str[0] = 0;
7526    get_sw_stackshot_fname(ts_boot.tv_sec, str, sizeof(str));
7527    if (str[0] != 0) {
7528        printf("\t\"sleep_wake_failure_stackshot\" : \"%s\",\n", str);
7529    }
7530
7531    show_assertions_individually(^(char *pname, char *assertionType, char *assertionName, int createdSince)
7532                    {
7533                        printf("\t\"%s_%s_%s\" : \"%d\",\n",
7534                                 assertionName, assertionType, pname, createdSince);
7535                    });
7536    printf("}\n");
7537
7538}
7539
7540#endif
7541static void show_everything(char **argv)
7542{
7543    printf("pmset is invoking all non-blocking -g arguments");
7544    int i=0;
7545	for (i=0; i<the_getters_count; i++) {
7546	    if (the_getters[i].actionType == kActionGetOnceNoArgs) {
7547            printf("\nINVOKE: pmset -g %s\n", the_getters[i].arg);
7548            the_getters[i].action(argv);
7549        }
7550    }
7551}
7552
7553