1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
25 */
26
27#include <stdio.h>			/* Standard */
28#include <stdlib.h>
29#include <fcntl.h>
30#include <sys/types.h>
31#include <time.h>
32#include <string.h>
33#include <errno.h>
34#include <pwd.h>
35#include <dirent.h>
36#include <thread.h>
37#include <limits.h>
38#include <sys/todio.h>			/* Time-Of-Day chip */
39#include <sys/stat.h>
40#include <sys/wait.h>
41#include <sys/ipc.h>			/* IPC functions */
42#include <signal.h>			/* signal handling */
43#include <syslog.h>
44#include <unistd.h>
45#include <libdevinfo.h>
46#include <poll.h>
47#include <sys/pm.h>			/* power management driver */
48#include <sys/uadmin.h>
49#include <sys/openpromio.h>		/* for prom access */
50#include <sys/sysmacros.h>		/* for MIN & MAX macros */
51#include <sys/modctl.h>
52#include <sys/stropts.h>		/* for INFTIM */
53#include <sys/pbio.h>
54#include <sys/cpr.h>
55#include <sys/srn.h>
56#include <stdarg.h>
57
58#include "powerd.h"
59
60/* External Functions */
61extern struct tm *localtime_r(const time_t *, struct tm *);
62extern void sysstat_init(void);
63extern int check_tty(hrtime_t *, int);
64extern int check_disks(hrtime_t *, int);
65extern int check_load_ave(hrtime_t *, float);
66extern int check_nfs(hrtime_t *, int);
67extern int last_disk_activity(hrtime_t *, int);
68extern int last_tty_activity(hrtime_t *, int);
69extern int last_load_ave_activity(hrtime_t *);
70extern int last_nfs_activity(hrtime_t *, int);
71
72#define	PM		"/dev/pm"
73#define	TOD		"/dev/tod"
74#define	PROM		"/dev/openprom"
75#define	PB		"/dev/power_button"
76#define	SRN		"/dev/srn"
77#define	LOGFILE		"./powerd.log"
78
79#define	PBM_THREAD	0
80#define	ATTACH_THREAD	1
81#define	NUM_THREADS	2
82
83#define	CHECK_INTERVAL	5
84#define	IDLECHK_INTERVAL	15
85#define	MINS_TO_SECS	60
86#define	HOURS_TO_SECS	(60 * 60)
87#define	DAYS_TO_SECS	(24 * 60 * 60)
88#define	HOURS_TO_MINS	60
89#define	DAYS_TO_MINS	(24 * 60)
90
91#define	LIFETIME_SECS			(7 * 365 * DAYS_TO_SECS)
92#define	DEFAULT_POWER_CYCLE_LIMIT	10000
93#define	DEFAULT_SYSTEM_BOARD_DATE	804582000	/* July 1, 1995 */
94
95#define	LLEN 80
96
97typedef	enum {root, options} prom_node_t;
98
99/* State Variables */
100static struct cprconfig	asinfo;
101static time_t		shutdown_time;	/* Time for next shutdown check */
102static time_t		checkidle_time;	/* Time for next idleness check */
103static time_t		last_resume;
104pwr_info_t		*info;		/* private as config data buffer */
105static int		pb_fd;		/* power button driver */
106static int		broadcast;	/* Enables syslog messages */
107static int		start_calc;
108static int		autoshutdown_en;
109static int		do_idlecheck;
110static int		got_sighup;
111static int		estar_v2_prop;
112static int		estar_v3_prop;
113static int		log_power_cycles_error = 0;
114static int		log_system_board_date_error = 0;
115static int		log_no_autoshutdown_warning = 0;
116static mutex_t		poweroff_mutex;
117
118static char *autoshutdown_cmd[] = {
119	"/usr/bin/sys-suspend",
120	"-n", "-d", ":0", NULL
121};
122
123static char *power_button_cmd[] = {
124	"/usr/bin/sys-suspend",
125	"-h", "-d", ":0", NULL
126};
127
128#ifdef __x86
129static char *autoS3_cmd[] = {
130	"/usr/bin/sys-suspend",
131	"-n", "-d", ":0", NULL
132};
133#endif
134
135static char pidpath[] = PIDPATH;
136static char scratch[PATH_MAX];
137static char *prog;
138
139/* Local Functions */
140static void alarm_handler(int);
141static void thaw_handler(int);
142static void kill_handler(int);
143static void work_handler(int);
144static void check_shutdown(time_t *, hrtime_t *);
145static void check_idleness(time_t *, hrtime_t *);
146static int last_system_activity(hrtime_t *);
147static int run_idlecheck(void);
148static void set_alarm(time_t);
149static int poweroff(const char *, char **);
150static int is_ok2shutdown(time_t *);
151static int get_prom(int, prom_node_t, char *, char *, size_t);
152static void *power_button_monitor(void *);
153static int open_pidfile(char *);
154static int write_pidfile(int, pid_t);
155static int read_cpr_config(void);
156static void *system_activity_monitor(void *);
157#ifdef __x86
158static void *autos3_monitor(void *);
159#endif
160static void do_attach(void);
161static void *attach_devices(void *);
162static int powerd_debug;
163
164/* PRINTFLIKE1 */
165static void
166logerror(const char *fmt, ...)
167{
168	va_list args;
169
170	va_start(args, fmt);
171	if (broadcast)
172		vsyslog(LOG_ERR, fmt, args);
173	va_end(args);
174}
175
176
177static void
178estrcpy(char *dst, char *src, size_t dlen)
179{
180	size_t slen;
181
182	slen = strlcpy(dst, src, dlen);
183	if (slen >= dlen) {
184		logerror("%s: string too long \"%s ...\"\n"
185		    "(len %d, max %d)\n", prog, dst, slen, dlen - 1);
186		exit(EXIT_FAILURE);
187	}
188}
189
190
191int
192main(int argc, char *argv[])
193{
194	pid_t		pid;
195	int		pm_fd;
196	struct sigaction act;
197	sigset_t	sigmask;
198	int		c;
199	char		errmsg[PATH_MAX + 64];
200	int		pid_fd;
201
202	prog = argv[0];
203	if (geteuid() != 0) {
204		(void) fprintf(stderr, "%s: Must be root\n", prog);
205		exit(EXIT_FAILURE);
206	}
207
208	if ((pid_fd = open_pidfile(prog)) ==  -1)
209		exit(EXIT_FAILURE);
210
211	/*
212	 * Process options
213	 */
214	broadcast = 1;
215	while ((c = getopt(argc, argv, "nd")) != EOF) {
216		switch (c) {
217		case 'd':
218			powerd_debug = 1;
219			break;
220		case 'n':
221			broadcast = 0;
222			break;
223		case '?':
224			(void) fprintf(stderr, "Usage: %s [-n]\n", prog);
225			exit(EXIT_FAILURE);
226		}
227	}
228
229	pm_fd = open(PM, O_RDWR);
230	if (pm_fd == -1) {
231		(void) snprintf(errmsg, sizeof (errmsg), "%s: %s", prog, PM);
232		perror(errmsg);
233		exit(EXIT_FAILURE);
234	}
235	(void) close(pm_fd);
236
237	/*
238	 * Initialize mutex lock used to insure only one command to
239	 * run at a time.
240	 */
241	if (mutex_init(&poweroff_mutex, USYNC_THREAD, NULL) != 0) {
242		(void) fprintf(stderr,
243		    "%s: Unable to initialize mutex lock\n", prog);
244		exit(EXIT_FAILURE);
245	}
246
247	if ((info = (pwr_info_t *)malloc(sizeof (pwr_info_t))) == NULL) {
248		(void) snprintf(errmsg, sizeof (errmsg), "%s: malloc", prog);
249		perror(errmsg);
250		exit(EXIT_FAILURE);
251	}
252
253	/*
254	 * Daemon is set to go...
255	 */
256	if ((pid = fork()) < 0)
257		exit(EXIT_FAILURE);
258	else if (pid != 0)
259		exit(EXIT_SUCCESS);
260
261	pid = getpid();
262	openlog(prog, 0, LOG_DAEMON);
263	if (write_pidfile(pid_fd, pid) == -1)	/* logs errors on failure */
264		exit(EXIT_FAILURE);
265	(void) close(pid_fd);
266
267	/*
268	 * Close all the parent's file descriptors (Bug 1225843).
269	 */
270	closefrom(0);
271	(void) setsid();
272	(void) chdir("/");
273	(void) umask(0);
274#ifdef DEBUG
275	/*
276	 * Connect stdout to the console.
277	 */
278	if (dup2(open("/dev/console", O_WRONLY|O_NOCTTY), 1) == -1) {
279		logerror("Unable to connect to the console.");
280	}
281#endif
282	info->pd_flags = PD_AC;
283	info->pd_idle_time = -1;
284	info->pd_start_time = 0;
285	info->pd_finish_time = 0;
286
287	/*
288	 * Allow SIGQUIT, SIGINT and SIGTERM signals to terminate us
289	 * any time
290	 */
291	act.sa_handler = kill_handler;
292	(void) sigemptyset(&act.sa_mask);
293	act.sa_flags = 0;
294	(void) sigaction(SIGQUIT, &act, NULL);
295	(void) sigaction(SIGINT, &act, NULL);
296	(void) sigaction(SIGTERM, &act, NULL);
297
298	(void) sigfillset(&sigmask);
299	(void) sigdelset(&sigmask, SIGQUIT);
300	(void) sigdelset(&sigmask, SIGINT);
301	(void) sigdelset(&sigmask, SIGTERM);
302	(void) thr_sigsetmask(SIG_SETMASK, &sigmask, NULL);
303
304	/*
305	 * If "power_button" device node can be opened, create a new
306	 * thread to monitor the power button.
307	 */
308	if ((pb_fd = open(PB, O_RDONLY)) != -1) {
309		if (powerd_debug)
310			logerror("powerd starting power button monitor.");
311		if (thr_create(NULL, 0, power_button_monitor, NULL,
312		    THR_DAEMON, NULL) != 0) {
313			logerror("Unable to monitor system's power button.");
314		}
315	}
316
317	do_attach();
318
319	/*
320	 * Create a new thread to monitor system activity and suspend
321	 * system if idle.
322	 */
323	if (powerd_debug)
324		logerror("powerd starting system activity monitor.");
325	if (thr_create(NULL, 0, system_activity_monitor, NULL,
326	    THR_DAEMON, NULL) != 0) {
327		logerror("Unable to create thread to monitor system activity.");
328	}
329
330#ifdef __x86
331	/*
332	 * Create a new thread to handle autos3 trigger
333	 */
334	if (powerd_debug)
335		logerror("powerd starting autos3 monitor.");
336	if (thr_create(NULL, 0, autos3_monitor, NULL, THR_DAEMON,
337	    NULL) != 0) {
338		logerror("Unable to create thread to monitor autos3 activity.");
339	}
340#endif
341
342	/*
343	 * Block until we receive an explicit terminate signal
344	 */
345	(void) sigsuspend(&sigmask);
346
347	return (1);
348}
349
350static void *
351system_activity_monitor(void *arg __unused)
352{
353	struct sigaction act;
354	sigset_t sigmask;
355
356	/*
357	 * Setup for gathering system's statistic.
358	 */
359	sysstat_init();
360
361	/*
362	 * In addition to the SIGQUIT, SIGINT and SIGTERM signals already
363	 * being handled, this thread also needs to handle SIGHUP, SIGALRM
364	 * and SIGTHAW signals.
365	 */
366	(void) sigemptyset(&act.sa_mask);
367	act.sa_flags = 0;
368	act.sa_handler = alarm_handler;
369	(void) sigaction(SIGALRM, &act, NULL);
370	act.sa_handler = work_handler;
371	(void) sigaction(SIGHUP, &act, NULL);
372	act.sa_handler = thaw_handler;
373	(void) sigaction(SIGTHAW, &act, NULL);
374
375	/*
376	 * Invoke work_handler with a dummy SIGHUP signal to read
377	 * cpr config file, get autoshutdown properties and schedule
378	 * an alarm if needed.
379	 */
380	work_handler(SIGHUP);
381
382	/*
383	 * Wait for signal to read file
384	 */
385	(void) thr_sigsetmask(0, 0, &sigmask);
386	(void) sigdelset(&sigmask, SIGHUP);
387	(void) sigdelset(&sigmask, SIGALRM);
388	(void) sigdelset(&sigmask, SIGTHAW);
389	(void) thr_sigsetmask(SIG_SETMASK, &sigmask, NULL);
390	do {
391		(void) sigsuspend(&sigmask);
392	} while (errno == EINTR);
393	return (NULL);
394}
395
396#ifdef __x86
397static void *
398autos3_monitor(void *arg __unused)
399{
400	struct pollfd poll_fd;
401	srn_event_info_t srn_event;		/* contains suspend type */
402	int fd, ret;
403
404	fd = open(SRN, O_RDWR|O_EXCL|O_NDELAY);
405	if (fd == -1) {
406		logerror("Unable to open %s: %s", SRN, strerror(errno));
407		thr_exit((void *)(intptr_t)errno);
408	}
409
410	/*
411	 * Tell device we want the special sauce
412	 */
413	ret = ioctl(fd, SRN_IOC_AUTOSX, NULL);
414	if (ret == -1) {
415		logerror("Ioctl SRN_IOC_AUTOSX failed: %s", strerror(errno));
416		(void) close(fd);
417		thr_exit((void *)(intptr_t)errno);
418	}
419	poll_fd.fd = fd;
420	/*CONSTCOND*/
421	while (1) {
422		poll_fd.revents = 0;
423		poll_fd.events = POLLIN;
424		if (poll(&poll_fd, 1, -1) < 0) {
425			switch (errno) {
426			case EINTR:
427			case EAGAIN:
428				continue;
429			default:
430				logerror("Poll error: %s", strerror(errno));
431				(void) close(fd);
432				thr_exit((void *)(intptr_t)errno);
433			}
434		}
435
436		ret = ioctl(fd, SRN_IOC_NEXTEVENT, &srn_event);
437		if (ret == -1) {
438			logerror("ioctl error: %s", strerror(errno));
439			(void) close(fd);
440			thr_exit((void *)(intptr_t)errno);
441		}
442		switch (srn_event.ae_type) {
443		case 3:			/* S3 */
444			if (powerd_debug)
445				logerror("ioctl returns type: %d",
446				    srn_event.ae_type);
447			break;
448		default:
449			logerror("Unsupported target state %d",
450			    srn_event.ae_type);
451			continue;
452		}
453		(void) poweroff("AutoS3", autoS3_cmd);
454		continue;
455	}
456	return (NULL);
457}
458#endif
459
460static int
461read_cpr_config(void)
462{
463	int	asfd;
464
465	if ((asfd = open(CPR_CONFIG, O_RDONLY)) < 0) {
466		logerror("Unable to open CPR config file '%s'", CPR_CONFIG);
467		return (-1);
468	}
469
470	if (read(asfd, (void *)&asinfo, sizeof (asinfo)) != sizeof (asinfo)) {
471		logerror("Unable to read CPR config file '%s'", CPR_CONFIG);
472		(void) close(asfd);
473		return (-1);
474	}
475
476	(void) close(asfd);
477
478	return (0);
479}
480
481/*ARGSUSED*/
482static void
483thaw_handler(int sig)
484{
485	start_calc  = 0;
486	last_resume = time(NULL);
487}
488
489/*ARGSUSED*/
490static void
491kill_handler(int sig)
492{
493	int ret_code = EXIT_SUCCESS;
494
495	/*
496	 * Free resources
497	 */
498
499	free(info);
500	if (pb_fd != -1) {
501		(void) close(pb_fd);
502	}
503	(void) mutex_destroy(&poweroff_mutex);
504	(void) unlink(pidpath);
505	closelog();
506	exit(ret_code);
507}
508
509/*ARGSUSED*/
510static void
511alarm_handler(int sig)
512{
513	time_t		now;
514	hrtime_t	hr_now;
515
516	now = time(NULL);
517	hr_now = gethrtime();
518	if (checkidle_time <= now && checkidle_time != 0)
519		check_idleness(&now, &hr_now);
520	if (shutdown_time <= now && shutdown_time != 0)
521		check_shutdown(&now, &hr_now);
522
523	set_alarm(now);
524}
525
526/*ARGSUSED*/
527static void
528work_handler(int sig)
529{
530	time_t		now;
531	hrtime_t	hr_now;
532	struct stat	stat_buf;
533
534	do_idlecheck = 0;
535	info->pd_flags = PD_AC;
536
537	/*
538	 * Parse the config file for autoshutdown and idleness entries.
539	 */
540	if (read_cpr_config() < 0)
541		return;
542
543	/*
544	 * Since Oct. 1, 1995, any new system shipped had root
545	 * property "energystar-v2" defined in its prom.  Systems
546	 * shipped after July 1, 1999, will have "energystar-v3"
547	 * property.
548	 */
549	estar_v2_prop = asinfo.is_cpr_default;
550
551	info->pd_flags |= asinfo.is_autowakeup_capable;
552
553	if (strlen(asinfo.idlecheck_path) > 0) {
554		if (stat(asinfo.idlecheck_path, &stat_buf) != 0) {
555			logerror("unable to access idlecheck program \"%s\".",
556			    asinfo.idlecheck_path);
557		} else if (!(stat_buf.st_mode & S_IXUSR)) {
558			logerror("idlecheck program \"%s\" is not executable.",
559			    asinfo.idlecheck_path);
560		} else {
561			do_idlecheck = 1;
562		}
563	}
564
565	if (strlen(asinfo.as_behavior) == 0 ||
566	    strcmp(asinfo.as_behavior, "noshutdown") == 0 ||
567	    strcmp(asinfo.as_behavior, "unconfigured") == 0) {
568		info->pd_autoshutdown = 0;
569	} else if (strcmp(asinfo.as_behavior, "default") == 0) {
570		info->pd_autoshutdown = estar_v2_prop;
571	} else if (strcmp(asinfo.as_behavior, "shutdown") == 0 ||
572	    strcmp(asinfo.as_behavior, "autowakeup") == 0) {
573		info->pd_autoshutdown = asinfo.is_cpr_capable;
574	} else {
575		logerror("autoshutdown behavior \"%s\" unrecognized.",
576		    asinfo.as_behavior);
577		info->pd_autoshutdown = 0;
578	}
579
580	if (info->pd_autoshutdown) {
581		info->pd_idle_time = asinfo.as_idle;
582		info->pd_start_time =
583		    (asinfo.as_sh * 60 + asinfo.as_sm) % DAYS_TO_MINS;
584		info->pd_finish_time =
585		    (asinfo.as_fh * 60 + asinfo.as_fm) % DAYS_TO_MINS;
586		info->pd_autoresume =
587		    (strcmp(asinfo.as_behavior, "autowakeup") == 0) ? 1 : 0;
588	}
589	autoshutdown_en = (asinfo.as_idle >= 0 && info->pd_autoshutdown)
590	    ? 1 : 0;
591
592#ifdef DEBUG
593	(void) fprintf(stderr, "autoshutdown_en = %d, as_idle = %d, "
594	    "pd_autoresume = %d\n",
595	    autoshutdown_en, asinfo.as_idle, info->pd_autoresume);
596
597	(void) fprintf(stderr, " pd_start_time=%d, pd_finish_time=%d\n",
598	    info->pd_start_time, info->pd_finish_time);
599#endif
600
601	got_sighup = 1;
602	now = last_resume = time(NULL);
603	hr_now = gethrtime();
604	check_idleness(&now, &hr_now);
605	check_shutdown(&now, &hr_now);
606	set_alarm(now);
607}
608
609static void
610check_shutdown(time_t *now, hrtime_t *hr_now)
611{
612	int		tod_fd = -1;
613	int		kbd, mouse, system, least_idle, idlecheck_time;
614	int		next_time;
615	int		s, f;
616	struct tm	tmp_time;
617	time_t		start_of_day, time_since_last_resume;
618	time_t		wakeup_time;
619	extern long	conskbd_idle_time(void);
620	extern long	consms_idle_time(void);
621	static int	warned_kbd, warned_ms; /* print error msg one time */
622
623	if (!autoshutdown_en) {
624		shutdown_time = 0;
625		return;
626	}
627
628	(void) localtime_r(now, &tmp_time);
629	tmp_time.tm_sec = 0;
630	tmp_time.tm_min = 0;
631	tmp_time.tm_hour = 0;
632	start_of_day = mktime(&tmp_time);
633	s = start_of_day + info->pd_start_time * 60;
634	f = start_of_day + info->pd_finish_time * 60;
635	if ((s < f && *now >= s && *now < f) ||
636	    (s >= f && (*now < f || *now >= s))) {
637		if ((mouse = (int)consms_idle_time()) < 0) {
638			if (! warned_ms) {
639				warned_ms = 1;
640				logerror("powerd: failed to get "
641				    "idle time for console mouse");
642			}
643			return;
644		}
645		if ((kbd = (int)conskbd_idle_time()) < 0) {
646			if (! warned_kbd) {
647				warned_kbd = 1;
648				logerror("powerd: failed to get "
649				    "idle time for console keyboard");
650			}
651			return;
652		}
653
654		system = last_system_activity(hr_now);
655		/* who is the last to go idle */
656		least_idle = MIN(system, MIN(kbd, mouse));
657
658		/*
659		 * Calculate time_since_last_resume and the next_time
660		 * to auto suspend.
661		 */
662		start_calc = 1;
663		time_since_last_resume = time(NULL) - last_resume;
664		next_time = info->pd_idle_time * 60 -
665		    MIN(least_idle, time_since_last_resume);
666
667#ifdef DEBUG
668		fprintf(stderr, " check_shutdown: next_time=%d\n", next_time);
669#endif
670
671		/*
672		 * If we have get the SIGTHAW signal at this point - our
673		 * calculation of time_since_last_resume is wrong  so
674		 * - we need to recalculate.
675		 */
676		while (start_calc == 0) {
677			/* need to redo calculation */
678			start_calc = 1;
679			time_since_last_resume = time(NULL) - last_resume;
680			next_time = info->pd_idle_time * 60 -
681			    MIN(least_idle, time_since_last_resume);
682		}
683
684		/*
685		 * Only when everything else is idle, run the user's idlecheck
686		 * script.
687		 */
688		if (next_time <= 0 && do_idlecheck) {
689			got_sighup = 0;
690			idlecheck_time = run_idlecheck();
691			next_time = info->pd_idle_time * 60 -
692			    MIN(idlecheck_time, MIN(least_idle,
693			    time_since_last_resume));
694			/*
695			 * If we have caught SIGTHAW or SIGHUP, need to
696			 * recalculate.
697			 */
698			while (start_calc == 0 || got_sighup == 1) {
699				start_calc = 1;
700				got_sighup = 0;
701				idlecheck_time = run_idlecheck();
702				time_since_last_resume = time(NULL) -
703				    last_resume;
704				next_time = info->pd_idle_time * 60 -
705				    MIN(idlecheck_time, MIN(least_idle,
706				    time_since_last_resume));
707			}
708		}
709
710		if (next_time <= 0) {
711			if (is_ok2shutdown(now)) {
712				/*
713				 * Setup the autowakeup alarm.  Clear it
714				 * right after poweroff, just in case if
715				 * shutdown doesn't go through.
716				 */
717				if (info->pd_autoresume)
718					tod_fd = open(TOD, O_RDWR);
719				if (info->pd_autoresume && tod_fd != -1) {
720					wakeup_time = (*now < f) ? f :
721					    (f + DAYS_TO_SECS);
722					/*
723					 * A software fix for hardware
724					 * bug 1217415.
725					 */
726					if ((wakeup_time - *now) < 180) {
727						logerror(
728		"Since autowakeup time is less than 3 minutes away, "
729		"autoshutdown will not occur.");
730						shutdown_time = *now + 180;
731						(void) close(tod_fd);
732						return;
733					}
734					if (ioctl(tod_fd, TOD_SET_ALARM,
735					    &wakeup_time) == -1) {
736						logerror("Unable to program TOD"
737						    " alarm for autowakeup.");
738						(void) close(tod_fd);
739						return;
740					}
741				}
742
743				(void) poweroff("Autoshutdown",
744				    autoshutdown_cmd);
745
746				if (info->pd_autoresume && tod_fd != -1) {
747					if (ioctl(tod_fd, TOD_CLEAR_ALARM,
748					    NULL) == -1)
749						logerror("Unable to clear "
750						    "alarm in TOD device.");
751					(void) close(tod_fd);
752				}
753
754				(void) time(now);
755				/* wait at least 5 mins */
756				shutdown_time = *now +
757				    ((info->pd_idle_time * 60) > 300 ?
758				    (info->pd_idle_time * 60) : 300);
759			} else {
760				/* wait 5 mins */
761				shutdown_time = *now + 300;
762			}
763		} else
764			shutdown_time = *now + next_time;
765	} else if (s < f && *now >= f) {
766		shutdown_time = s + DAYS_TO_SECS;
767	} else
768		shutdown_time = s;
769}
770
771static int
772is_ok2shutdown(time_t *now)
773{
774	int	prom_fd = -1;
775	char	power_cycles_st[LLEN];
776	char	power_cycle_limit_st[LLEN];
777	char	system_board_date_st[LLEN];
778	int	power_cycles, power_cycle_limit, free_cycles, scaled_cycles;
779	time_t	life_began, life_passed;
780	int	no_power_cycles = 0;
781	int	no_system_board_date = 0;
782	int	ret = 1;
783
784	/* CONSTCOND */
785	while (1) {
786		if ((prom_fd = open(PROM, O_RDWR)) == -1 &&
787		    (errno == EAGAIN))
788			continue;
789		break;
790	}
791
792	/*
793	 * when #power-cycles property does not exist
794	 * power cycles are unlimited.
795	 */
796	if (get_prom(prom_fd, options, "#power-cycles",
797	    power_cycles_st, sizeof (power_cycles_st)) == 0)
798		goto ckdone;
799
800	if (get_prom(prom_fd, root, "power-cycle-limit",
801	    power_cycle_limit_st, sizeof (power_cycle_limit_st)) == 0) {
802		power_cycle_limit = DEFAULT_POWER_CYCLE_LIMIT;
803	} else {
804		power_cycle_limit = atoi(power_cycle_limit_st);
805	}
806
807	/*
808	 * Allow 10% of power_cycle_limit as free cycles.
809	 */
810	free_cycles = power_cycle_limit / 10;
811
812	power_cycles = atoi(power_cycles_st);
813	if (power_cycles < 0)
814		no_power_cycles++;
815	else if (power_cycles <= free_cycles)
816		goto ckdone;
817
818	if (no_power_cycles && log_power_cycles_error == 0) {
819		logerror("Invalid PROM property \"#power-cycles\" was found.");
820		log_power_cycles_error++;
821	}
822
823	if (get_prom(prom_fd, options, "system-board-date",
824	    system_board_date_st, sizeof (system_board_date_st)) == 0) {
825		no_system_board_date++;
826	} else {
827		life_began = strtol(system_board_date_st, (char **)NULL, 16);
828		if (life_began > *now) {
829			no_system_board_date++;
830		}
831	}
832	if (no_system_board_date) {
833		if (log_system_board_date_error == 0) {
834			logerror("No or invalid PROM property "
835			    "\"system-board-date\" was found.");
836			log_system_board_date_error++;
837		}
838		life_began = DEFAULT_SYSTEM_BOARD_DATE;
839	}
840
841	life_passed = *now - life_began;
842
843	/*
844	 * Since we don't keep the date that last free_cycle is ended, we
845	 * need to spread (power_cycle_limit - free_cycles) over the entire
846	 * 7-year life span instead of (lifetime - date free_cycles ended).
847	 */
848	scaled_cycles = (int)(((float)life_passed / (float)LIFETIME_SECS) *
849	    (power_cycle_limit - free_cycles));
850
851	if (no_power_cycles)
852		goto ckdone;
853
854#ifdef DEBUG
855	(void) fprintf(stderr, "Actual power_cycles = %d\t"
856	    "Scaled power_cycles = %d\n", power_cycles, scaled_cycles);
857#endif
858	if (power_cycles > scaled_cycles) {
859		if (log_no_autoshutdown_warning == 0) {
860			logerror("Automatic shutdown has been temporarily "
861			    "suspended in order to preserve the reliability "
862			    "of this system.");
863			log_no_autoshutdown_warning++;
864		}
865		ret = 0;
866		goto ckdone;
867	}
868
869ckdone:
870	if (prom_fd != -1)
871		(void) close(prom_fd);
872	return (ret);
873}
874
875static void
876check_idleness(time_t *now, hrtime_t *hr_now)
877{
878
879	/*
880	 * Check idleness only when autoshutdown is enabled.
881	 */
882	if (!autoshutdown_en) {
883		checkidle_time = 0;
884		return;
885	}
886
887	info->pd_ttychars_idle = check_tty(hr_now, asinfo.ttychars_thold);
888	info->pd_loadaverage_idle =
889	    check_load_ave(hr_now, asinfo.loadaverage_thold);
890	info->pd_diskreads_idle = check_disks(hr_now, asinfo.diskreads_thold);
891	info->pd_nfsreqs_idle = check_nfs(hr_now, asinfo.nfsreqs_thold);
892
893#ifdef DEBUG
894	(void) fprintf(stderr, "Idle ttychars for %d secs.\n",
895	    info->pd_ttychars_idle);
896	(void) fprintf(stderr, "Idle loadaverage for %d secs.\n",
897	    info->pd_loadaverage_idle);
898	(void) fprintf(stderr, "Idle diskreads for %d secs.\n",
899	    info->pd_diskreads_idle);
900	(void) fprintf(stderr, "Idle nfsreqs for %d secs.\n",
901	    info->pd_nfsreqs_idle);
902#endif
903
904	checkidle_time = *now + IDLECHK_INTERVAL;
905}
906
907static int
908last_system_activity(hrtime_t *hr_now)
909{
910	int	act_idle, latest;
911
912	latest = info->pd_idle_time * 60;
913	act_idle = last_tty_activity(hr_now, asinfo.ttychars_thold);
914	latest = MIN(latest, act_idle);
915	act_idle = last_load_ave_activity(hr_now);
916	latest = MIN(latest, act_idle);
917	act_idle = last_disk_activity(hr_now, asinfo.diskreads_thold);
918	latest = MIN(latest, act_idle);
919	act_idle = last_nfs_activity(hr_now, asinfo.nfsreqs_thold);
920	latest = MIN(latest, act_idle);
921
922	return (latest);
923}
924
925static int
926run_idlecheck()
927{
928	char		pm_variable[LLEN];
929	char		*cp;
930	int		status;
931	pid_t		child;
932
933	/*
934	 * Reap any child process which has been left over.
935	 */
936	while (waitpid((pid_t)-1, &status, WNOHANG) > 0)
937		;
938
939	/*
940	 * Execute the user's idlecheck script and set variable PM_IDLETIME.
941	 * Returned exit value is the idle time in minutes.
942	 */
943	if ((child = fork1()) == 0) {
944		(void) sprintf(pm_variable, "PM_IDLETIME=%d",
945		    info->pd_idle_time);
946		(void) putenv(pm_variable);
947		cp = strrchr(asinfo.idlecheck_path, '/');
948		if (cp == NULL)
949			cp = asinfo.idlecheck_path;
950		else
951			cp++;
952		(void) execl(asinfo.idlecheck_path, cp, NULL);
953		exit(-1);
954	} else if (child == -1) {
955		return (info->pd_idle_time * 60);
956	}
957
958	/*
959	 * Wait until the idlecheck program completes.
960	 */
961	if (waitpid(child, &status, 0) != child) {
962		/*
963		 * We get here if the calling process gets a signal.
964		 */
965		return (info->pd_idle_time * 60);
966	}
967
968	if (WEXITSTATUS(status) < 0) {
969		return (info->pd_idle_time * 60);
970	} else {
971		return (WEXITSTATUS(status) * 60);
972	}
973}
974
975static void
976set_alarm(time_t now)
977{
978	time_t	itime, stime, next_time, max_time;
979	int	next_alarm;
980
981	max_time = MAX(checkidle_time, shutdown_time);
982	if (max_time == 0) {
983		(void) alarm(0);
984		return;
985	}
986	itime = (checkidle_time == 0) ? max_time : checkidle_time;
987	stime = (shutdown_time == 0) ? max_time : shutdown_time;
988	next_time = MIN(itime, stime);
989	next_alarm = (next_time <= now) ? 1 : (next_time - now);
990	(void) alarm(next_alarm);
991
992#ifdef DEBUG
993	(void) fprintf(stderr, "Currently @ %s", ctime(&now));
994	(void) fprintf(stderr, "Checkidle in %d secs\n", checkidle_time - now);
995	(void) fprintf(stderr, "Shutdown  in %d secs\n", shutdown_time - now);
996	(void) fprintf(stderr, "Next alarm goes off in %d secs\n", next_alarm);
997	(void) fprintf(stderr, "************************************\n");
998#endif
999}
1000
1001static int
1002poweroff(const char *msg, char **cmd_argv)
1003{
1004	struct stat	statbuf;
1005	pid_t		pid, child;
1006	struct passwd	*pwd;
1007	char		*home, *user;
1008	char		ehome[] = "HOME=";
1009	char		euser[] = "LOGNAME=";
1010	int		status;
1011	char		**ca;
1012
1013	if (mutex_trylock(&poweroff_mutex) != 0)
1014		return (0);
1015
1016	if (stat("/dev/console", &statbuf) == -1 ||
1017	    (pwd = getpwuid(statbuf.st_uid)) == NULL) {
1018		(void) mutex_unlock(&poweroff_mutex);
1019		return (1);
1020	}
1021
1022	if (msg)
1023		syslog(LOG_NOTICE, msg);
1024
1025	if (*cmd_argv == NULL) {
1026		logerror("No command to run.");
1027		(void) mutex_unlock(&poweroff_mutex);
1028		return (1);
1029	}
1030
1031	home = malloc(strlen(pwd->pw_dir) + sizeof (ehome));
1032	user = malloc(strlen(pwd->pw_name) + sizeof (euser));
1033	if (home == NULL || user == NULL) {
1034		free(home);
1035		free(user);
1036		logerror("No memory.");
1037		(void) mutex_unlock(&poweroff_mutex);
1038		return (1);
1039	}
1040	(void) strcpy(home, ehome);
1041	(void) strcat(home, pwd->pw_dir);
1042	(void) strcpy(user, euser);
1043	(void) strcat(user, pwd->pw_name);
1044
1045	/*
1046	 * Need to simulate the user enviroment, minimaly set HOME, and USER.
1047	 */
1048	if ((child = fork1()) == 0) {
1049		(void) putenv(home);
1050		(void) putenv(user);
1051		(void) setgid(pwd->pw_gid);
1052		(void) setuid(pwd->pw_uid);
1053
1054		/*
1055		 * check for shutdown flag and set environment
1056		 */
1057		for (ca = cmd_argv; *ca; ca++) {
1058			if (strcmp("-h", *ca) == 0) {
1059				(void) putenv("SYSSUSPENDDODEFAULT=");
1060				break;
1061			}
1062		}
1063
1064		(void) execv(cmd_argv[0], cmd_argv);
1065		exit(EXIT_FAILURE);
1066	} else {
1067		free(home);
1068		free(user);
1069		if (child == -1) {
1070			(void) mutex_unlock(&poweroff_mutex);
1071			return (1);
1072		}
1073	}
1074	pid = 0;
1075	while (pid != child)
1076		pid = wait(&status);
1077	if (WEXITSTATUS(status)) {
1078		(void) syslog(LOG_ERR, "Failed to exec \"%s\".", cmd_argv[0]);
1079		(void) mutex_unlock(&poweroff_mutex);
1080		return (1);
1081	}
1082
1083	(void) mutex_unlock(&poweroff_mutex);
1084	return (0);
1085}
1086
1087#define	PBUFSIZE	256
1088
1089/*
1090 * Gets the value of a prom property at either root or options node.  It
1091 * returns 1 if it is successful, otherwise it returns 0 .
1092 */
1093static int
1094get_prom(int prom_fd, prom_node_t node_name,
1095    char *property_name, char *property_value, size_t len)
1096{
1097	union {
1098		char buf[PBUFSIZE + sizeof (uint_t)];
1099		struct openpromio opp;
1100	} oppbuf;
1101	register struct openpromio *opp = &(oppbuf.opp);
1102	int	got_it = 0;
1103
1104	if (prom_fd == -1) {
1105		return (0);
1106	}
1107
1108	switch (node_name) {
1109	case root:
1110		(void *) memset(oppbuf.buf, 0, PBUFSIZE);
1111		opp->oprom_size = PBUFSIZE;
1112		if (ioctl(prom_fd, OPROMNEXT, opp) < 0) {
1113			return (0);
1114		}
1115
1116		/*
1117		 * Passing null string will give us the first property.
1118		 */
1119		(void *) memset(oppbuf.buf, 0, PBUFSIZE);
1120		do {
1121			opp->oprom_size = PBUFSIZE;
1122			if (ioctl(prom_fd, OPROMNXTPROP, opp) < 0) {
1123				return (0);
1124			}
1125			if (strcmp(opp->oprom_array, property_name) == 0) {
1126				got_it++;
1127				break;
1128			}
1129		} while (opp->oprom_size > 0);
1130
1131		if (!got_it) {
1132			return (0);
1133		}
1134		if (got_it && property_value == NULL) {
1135			return (1);
1136		}
1137		opp->oprom_size = PBUFSIZE;
1138		if (ioctl(prom_fd, OPROMGETPROP, opp) < 0) {
1139			return (0);
1140		}
1141		if (opp->oprom_size == 0) {
1142			*property_value = '\0';
1143		} else {
1144			estrcpy(property_value, opp->oprom_array, len);
1145		}
1146		break;
1147	case options:
1148		estrcpy(opp->oprom_array, property_name, PBUFSIZE);
1149		opp->oprom_size = PBUFSIZE;
1150		if (ioctl(prom_fd, OPROMGETOPT, opp) < 0) {
1151			return (0);
1152		}
1153		if (opp->oprom_size == 0) {
1154			return (0);
1155		}
1156		if (property_value != NULL) {
1157			estrcpy(property_value, opp->oprom_array, len);
1158		}
1159		break;
1160	default:
1161		logerror("Only root node and options node are supported.\n");
1162		return (0);
1163	}
1164
1165	return (1);
1166}
1167
1168#define	isspace(ch)	((ch) == ' ' || (ch) == '\t')
1169#define	iseol(ch)	((ch) == '\n' || (ch) == '\r' || (ch) == '\f')
1170
1171/*ARGSUSED*/
1172static void *
1173power_button_monitor(void *arg)
1174{
1175	struct pollfd pfd;
1176	int events, ret;
1177
1178	if (ioctl(pb_fd, PB_BEGIN_MONITOR, NULL) == -1) {
1179		logerror("Failed to monitor the power button.");
1180		thr_exit((void *) 0);
1181	}
1182
1183	pfd.fd = pb_fd;
1184	pfd.events = POLLIN;
1185
1186	/*CONSTCOND*/
1187	while (1) {
1188		if (poll(&pfd, 1, INFTIM) == -1) {
1189			logerror("Failed to poll for power button events.");
1190			thr_exit((void *) 0);
1191		}
1192
1193		if (!(pfd.revents & POLLIN))
1194			continue;
1195
1196		/*
1197		 * Monitor the power button, but only take action if
1198		 * gnome-power-manager is not running.
1199		 *
1200		 * ret greater than 0 means could not find process.
1201		 */
1202		ret = system("/usr/bin/pgrep -fx gnome-power-manager");
1203
1204		if (ioctl(pfd.fd, PB_GET_EVENTS, &events) == -1) {
1205			logerror("Failed to get power button events.");
1206			thr_exit((void *) 0);
1207		}
1208
1209		if ((ret > 0) && (events & PB_BUTTON_PRESS) &&
1210		    (poweroff(NULL, power_button_cmd) != 0)) {
1211			logerror("Power button is pressed, powering "
1212			    "down the system!");
1213
1214			/*
1215			 * Send SIGPWR signal to the init process to
1216			 * shut down the system.
1217			 */
1218			if (kill(1, SIGPWR) == -1)
1219				(void) uadmin(A_SHUTDOWN, AD_POWEROFF, 0);
1220		}
1221
1222		/*
1223		 * Clear any power button event that has happened
1224		 * meanwhile we were busy processing the last one.
1225		 */
1226		if (ioctl(pfd.fd, PB_GET_EVENTS, &events) == -1) {
1227			logerror("Failed to get power button events.");
1228			thr_exit((void *) 0);
1229		}
1230	}
1231	return (NULL);
1232}
1233
1234static void
1235do_attach(void)
1236{
1237	if (read_cpr_config() < 0)
1238		return;
1239
1240	/*
1241	 * If autopm behavior is explicitly enabled for energystar-v2, or
1242	 * set to default for energystar-v3, create a new thread to attach
1243	 * all devices.
1244	 */
1245	estar_v3_prop = asinfo.is_autopm_default;
1246	if ((strcmp(asinfo.apm_behavior, "enable") == 0) ||
1247	    (estar_v3_prop && strcmp(asinfo.apm_behavior, "default") == 0)) {
1248		if (powerd_debug)
1249			logerror("powerd starting device attach thread.");
1250		if (thr_create(NULL, 0, attach_devices, NULL,
1251		    THR_DAEMON, NULL) != 0) {
1252			logerror("Unable to create thread to attach devices.");
1253		}
1254	}
1255}
1256
1257/*ARGSUSED*/
1258static void *
1259attach_devices(void *arg)
1260{
1261	di_node_t root_node;
1262
1263	(void) sleep(60);	/* let booting finish first */
1264
1265	if ((root_node = di_init("/", DINFOFORCE)) == DI_NODE_NIL) {
1266		logerror("Failed to attach devices.");
1267		return (NULL);
1268	}
1269	di_fini(root_node);
1270
1271	/*
1272	 * Unload all the modules.
1273	 */
1274	(void) modctl(MODUNLOAD, 0);
1275
1276	return (NULL);
1277}
1278
1279
1280/*
1281 * Create a file which will contain our pid.  Pmconfig will check this file
1282 * to see if we are running and can use the pid to signal us.  Returns the
1283 * file descriptor if successful, -1 otherwise.
1284 *
1285 * Note: Deal with attempt to launch multiple instances and also with existence
1286 * of an obsolete pid file caused by an earlier abort.
1287 */
1288static int
1289open_pidfile(char *me)
1290{
1291	int fd;
1292	const char *e1 = "%s: Cannot open pid file for read: ";
1293	const char *e2 = "%s: Cannot unlink obsolete pid file: ";
1294	const char *e3 = "%s: Either another daemon is running or the"
1295	    " process is defunct (pid %d). \n";
1296	const char *e4 = "%s: Cannot create pid file: ";
1297
1298again:
1299	if ((fd = open(pidpath, O_CREAT | O_EXCL | O_WRONLY, 0444)) == -1) {
1300		if (errno  == EEXIST) {
1301			FILE *fp;
1302			pid_t pid;
1303
1304			if ((fp = fopen(pidpath, "r")) == NULL) {
1305				(void) fprintf(stderr, e1, me);
1306				perror(NULL);
1307				return (-1);
1308			}
1309
1310			/* Read the pid */
1311			pid = (pid_t)-1;
1312			(void) fscanf(fp, "%ld", &pid);
1313			(void) fclose(fp);
1314			if (pid == -1) {
1315				if (unlink(pidpath) == -1) {
1316					(void) fprintf(stderr, e2, me);
1317					perror(NULL);
1318					return (-1);
1319				} else /* try without corrupted file */
1320					goto again;
1321			}
1322
1323			/* Is pid for a running process */
1324			if (kill(pid, 0) == -1) {
1325				if (errno == ESRCH) {
1326					if (unlink(pidpath) == -1) {
1327						(void) fprintf(stderr, e2, me);
1328						perror(NULL);
1329						return (-1);
1330					} else	/* try without obsolete file */
1331						goto again;
1332				}
1333			} else {    /* powerd deamon still running or defunct */
1334				(void) fprintf(stderr, e3, me, pid);
1335				return (-1);
1336			}
1337
1338		} else {	/* create failure not due to existing file */
1339			(void) fprintf(stderr, e4, me);
1340			perror(NULL);
1341			return (-1);
1342		}
1343	}
1344
1345	(void) fchown(fd, (uid_t)-1, (gid_t)0);
1346	return (fd);
1347}
1348
1349/*
1350 * Write a pid to the pid file.  Report errors to syslog.
1351 *
1352 */
1353static int
1354write_pidfile(int fd, pid_t pid)
1355{
1356	int	len;
1357	int	rc = 0;			/* assume success */
1358
1359	len = sprintf(scratch, "%ld\n", pid);
1360	if (write(fd, scratch, len) != len) {
1361		logerror("Cannot write pid file: %s", strerror(errno));
1362		rc = -1;
1363	}
1364
1365	return (rc);
1366}
1367