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