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 *)(intptr_t)errno);
 401         }
 402 
 403         /*
 404          * Tell device we want the special sauce
 405          */
 406         ret = ioctl(fd, SRN_IOC_AUTOSX, NULL);
 407         if (ret == -1) {
 408                 logerror("Ioctl SRN_IOC_AUTOSX failed: %s", strerror(errno));
 409                 (void) close(fd);
 410                 thr_exit((void *)(intptr_t)errno);
 411         }
 412         poll_fd.fd = fd;
 413         /*CONSTCOND*/
 414         while (1) {
 415                 poll_fd.revents = 0;
 416                 poll_fd.events = POLLIN;
 417                 if (poll(&poll_fd, 1, -1) < 0) {
 418                         switch (errno) {
 419                         case EINTR:
 420                         case EAGAIN:
 421                                 continue;
 422                         default:
 423                                 logerror("Poll error: %s", strerror(errno));
 424                                 (void) close(fd);
 425                                 thr_exit((void *)(intptr_t)errno);
 426                         }
 427                 }
 428 
 429                 ret = ioctl(fd, SRN_IOC_NEXTEVENT, &srn_event);
 430                 if (ret == -1) {
 431                         logerror("ioctl error: %s", strerror(errno));
 432                         (void) close(fd);
 433                         thr_exit((void *)(intptr_t)errno);
 434                 }
 435                 switch (srn_event.ae_type) {
 436                 case 3:                 /* S3 */
 437                         if (powerd_debug)
 438                                 logerror("ioctl returns type: %d",
 439                                     srn_event.ae_type);
 440                         break;
 441                 default:
 442                         logerror("Unsupported target state %d",
 443                             srn_event.ae_type);
 444                         continue;
 445                 }
 446                 (void) poweroff("AutoS3", autoS3_cmd);
 447                 continue;
 448         }
 449 }
 450 
 451 static int
 452 read_cpr_config(void)
 453 {
 454         int     asfd;
 455 
 456         if ((asfd = open(CPR_CONFIG, O_RDONLY)) < 0) {
 457                 logerror("Unable to open CPR config file '%s'", CPR_CONFIG);
 458                 return (-1);
 459         }
 460 
 461         if (read(asfd, (void *)&asinfo, sizeof (asinfo)) != sizeof (asinfo)) {
 462                 logerror("Unable to read CPR config file '%s'", CPR_CONFIG);
 463                 (void) close(asfd);
 464                 return (-1);
 465         }
 466 
 467         (void) close(asfd);
 468 
 469         return (0);
 470 }
 471 
 472 /*ARGSUSED*/
 473 static void
 474 thaw_handler(int sig)
 475 {
 476         start_calc  = 0;
 477         last_resume = time(NULL);
 478 }
 479 
 480 /*ARGSUSED*/
 481 static void
 482 kill_handler(int sig)
 483 {
 484         int ret_code = EXIT_SUCCESS;
 485 
 486         /*
 487          * Free resources
 488          */
 489 
 490         free(info);
 491         if (pb_fd != -1) {
 492                 (void) close(pb_fd);
 493         }
 494         (void) mutex_destroy(&poweroff_mutex);
 495         (void) unlink(pidpath);
 496         closelog();
 497         exit(ret_code);
 498 }
 499 
 500 /*ARGSUSED*/
 501 static void
 502 alarm_handler(int sig)
 503 {
 504         time_t          now;
 505         hrtime_t        hr_now;
 506 
 507         now = time(NULL);
 508         hr_now = gethrtime();
 509         if (checkidle_time <= now && checkidle_time != 0)
 510                 check_idleness(&now, &hr_now);
 511         if (shutdown_time <= now && shutdown_time != 0)
 512                 check_shutdown(&now, &hr_now);
 513 
 514         set_alarm(now);
 515 }
 516 
 517 /*ARGSUSED*/
 518 static void
 519 work_handler(int sig)
 520 {
 521         time_t          now;
 522         hrtime_t        hr_now;
 523         struct stat     stat_buf;
 524 
 525         do_idlecheck = 0;
 526         info->pd_flags = PD_AC;
 527 
 528         /*
 529          * Parse the config file for autoshutdown and idleness entries.
 530          */
 531         if (read_cpr_config() < 0)
 532                 return;
 533 
 534         /*
 535          * Since Oct. 1, 1995, any new system shipped had root
 536          * property "energystar-v2" defined in its prom.  Systems
 537          * shipped after July 1, 1999, will have "energystar-v3"
 538          * property.
 539          */
 540         estar_v2_prop = asinfo.is_cpr_default;
 541 
 542         info->pd_flags |= asinfo.is_autowakeup_capable;
 543 
 544         if (strlen(asinfo.idlecheck_path) > 0) {
 545                 if (stat(asinfo.idlecheck_path, &stat_buf) != 0) {
 546                         logerror("unable to access idlecheck program \"%s\".",
 547                             asinfo.idlecheck_path);
 548                 } else if (!(stat_buf.st_mode & S_IXUSR)) {
 549                         logerror("idlecheck program \"%s\" is not executable.",
 550                             asinfo.idlecheck_path);
 551                 } else {
 552                         do_idlecheck = 1;
 553                 }
 554         }
 555 
 556         if (strlen(asinfo.as_behavior) == 0 ||
 557             strcmp(asinfo.as_behavior, "noshutdown") == 0 ||
 558             strcmp(asinfo.as_behavior, "unconfigured") == 0) {
 559                 info->pd_autoshutdown = 0;
 560         } else if (strcmp(asinfo.as_behavior, "default") == 0) {
 561                 info->pd_autoshutdown = estar_v2_prop;
 562         } else if (strcmp(asinfo.as_behavior, "shutdown") == 0 ||
 563             strcmp(asinfo.as_behavior, "autowakeup") == 0) {
 564                 info->pd_autoshutdown = asinfo.is_cpr_capable;
 565         } else {
 566                 logerror("autoshutdown behavior \"%s\" unrecognized.",
 567                     asinfo.as_behavior);
 568                 info->pd_autoshutdown = 0;
 569         }
 570 
 571         if (info->pd_autoshutdown) {
 572                 info->pd_idle_time = asinfo.as_idle;
 573                 info->pd_start_time =
 574                     (asinfo.as_sh * 60 + asinfo.as_sm) % DAYS_TO_MINS;
 575                 info->pd_finish_time =
 576                     (asinfo.as_fh * 60 + asinfo.as_fm) % DAYS_TO_MINS;
 577                 info->pd_autoresume =
 578                     (strcmp(asinfo.as_behavior, "autowakeup") == 0) ? 1 : 0;
 579         }
 580         autoshutdown_en = (asinfo.as_idle >= 0 && info->pd_autoshutdown)
 581             ? 1 : 0;
 582 
 583 #ifdef DEBUG
 584         (void) fprintf(stderr, "autoshutdown_en = %d, as_idle = %d, "
 585             "pd_autoresume = %d\n",
 586             autoshutdown_en, asinfo.as_idle, info->pd_autoresume);
 587 
 588         (void) fprintf(stderr, " pd_start_time=%d, pd_finish_time=%d\n",
 589             info->pd_start_time, info->pd_finish_time);
 590 #endif
 591 
 592         got_sighup = 1;
 593         now = last_resume = time(NULL);
 594         hr_now = gethrtime();
 595         check_idleness(&now, &hr_now);
 596         check_shutdown(&now, &hr_now);
 597         set_alarm(now);
 598 }
 599 
 600 static void
 601 check_shutdown(time_t *now, hrtime_t *hr_now)
 602 {
 603         int             tod_fd = -1;
 604         int             kbd, mouse, system, least_idle, idlecheck_time;
 605         int             next_time;
 606         int             s, f;
 607         struct tm       tmp_time;
 608         time_t          start_of_day, time_since_last_resume;
 609         time_t          wakeup_time;
 610         extern long     conskbd_idle_time(void);
 611         extern long     consms_idle_time(void);
 612         static int      warned_kbd, warned_ms; /* print error msg one time */
 613 
 614         if (!autoshutdown_en) {
 615                 shutdown_time = 0;
 616                 return;
 617         }
 618 
 619         (void) localtime_r(now, &tmp_time);
 620         tmp_time.tm_sec = 0;
 621         tmp_time.tm_min = 0;
 622         tmp_time.tm_hour = 0;
 623         start_of_day = mktime(&tmp_time);
 624         s = start_of_day + info->pd_start_time * 60;
 625         f = start_of_day + info->pd_finish_time * 60;
 626         if ((s < f && *now >= s && *now < f) ||
 627             (s >= f && (*now < f || *now >= s))) {
 628                 if ((mouse = (int)consms_idle_time()) < 0) {
 629                         if (! warned_ms) {
 630                                 warned_ms = 1;
 631                                 logerror("powerd: failed to get "
 632                                     "idle time for console mouse");
 633                         }
 634                         return;
 635                 }
 636                 if ((kbd = (int)conskbd_idle_time()) < 0) {
 637                         if (! warned_kbd) {
 638                                 warned_kbd = 1;
 639                                 logerror("powerd: failed to get "
 640                                     "idle time for console keyboard");
 641                         }
 642                         return;
 643                 }
 644 
 645                 system = last_system_activity(hr_now);
 646                 /* who is the last to go idle */
 647                 least_idle = MIN(system, MIN(kbd, mouse));
 648 
 649                 /*
 650                  * Calculate time_since_last_resume and the next_time
 651                  * to auto suspend.
 652                  */
 653                 start_calc = 1;
 654                 time_since_last_resume = time(NULL) - last_resume;
 655                 next_time = info->pd_idle_time * 60 -
 656                     MIN(least_idle, time_since_last_resume);
 657 
 658 #ifdef DEBUG
 659                 fprintf(stderr, " check_shutdown: next_time=%d\n", next_time);
 660 #endif
 661 
 662                 /*
 663                  * If we have get the SIGTHAW signal at this point - our
 664                  * calculation of time_since_last_resume is wrong  so
 665                  * - we need to recalculate.
 666                  */
 667                 while (start_calc == 0) {
 668                         /* need to redo calculation */
 669                         start_calc = 1;
 670                         time_since_last_resume = time(NULL) - last_resume;
 671                         next_time = info->pd_idle_time * 60 -
 672                             MIN(least_idle, time_since_last_resume);
 673                 }
 674 
 675                 /*
 676                  * Only when everything else is idle, run the user's idlecheck
 677                  * script.
 678                  */
 679                 if (next_time <= 0 && do_idlecheck) {
 680                         got_sighup = 0;
 681                         idlecheck_time = run_idlecheck();
 682                         next_time = info->pd_idle_time * 60 -
 683                             MIN(idlecheck_time, MIN(least_idle,
 684                             time_since_last_resume));
 685                         /*
 686                          * If we have caught SIGTHAW or SIGHUP, need to
 687                          * recalculate.
 688                          */
 689                         while (start_calc == 0 || got_sighup == 1) {
 690                                 start_calc = 1;
 691                                 got_sighup = 0;
 692                                 idlecheck_time = run_idlecheck();
 693                                 time_since_last_resume = time(NULL) -
 694                                     last_resume;
 695                                 next_time = info->pd_idle_time * 60 -
 696                                     MIN(idlecheck_time, MIN(least_idle,
 697                                     time_since_last_resume));
 698                         }
 699                 }
 700 
 701                 if (next_time <= 0) {
 702                         if (is_ok2shutdown(now)) {
 703                                 /*
 704                                  * Setup the autowakeup alarm.  Clear it
 705                                  * right after poweroff, just in case if
 706                                  * shutdown doesn't go through.
 707                                  */
 708                                 if (info->pd_autoresume)
 709                                         tod_fd = open(TOD, O_RDWR);
 710                                 if (info->pd_autoresume && tod_fd != -1) {
 711                                         wakeup_time = (*now < f) ? f :
 712                                             (f + DAYS_TO_SECS);
 713                                         /*
 714                                          * A software fix for hardware
 715                                          * bug 1217415.
 716                                          */
 717                                         if ((wakeup_time - *now) < 180) {
 718                                                 logerror(
 719                 "Since autowakeup time is less than 3 minutes away, "
 720                 "autoshutdown will not occur.");
 721                                                 shutdown_time = *now + 180;
 722                                                 (void) close(tod_fd);
 723                                                 return;
 724                                         }
 725                                         if (ioctl(tod_fd, TOD_SET_ALARM,
 726                                             &wakeup_time) == -1) {
 727                                                 logerror("Unable to program TOD"
 728                                                     " alarm for autowakeup.");
 729                                                 (void) close(tod_fd);
 730                                                 return;
 731                                         }
 732                                 }
 733 
 734                                 (void) poweroff("Autoshutdown",
 735                                     autoshutdown_cmd);
 736 
 737                                 if (info->pd_autoresume && tod_fd != -1) {
 738                                         if (ioctl(tod_fd, TOD_CLEAR_ALARM,
 739                                             NULL) == -1)
 740                                                 logerror("Unable to clear "
 741                                                     "alarm in TOD device.");
 742                                         (void) close(tod_fd);
 743                                 }
 744 
 745                                 (void) time(now);
 746                                 /* wait at least 5 mins */
 747                                 shutdown_time = *now +
 748                                     ((info->pd_idle_time * 60) > 300 ?
 749                                     (info->pd_idle_time * 60) : 300);
 750                         } else {
 751                                 /* wait 5 mins */
 752                                 shutdown_time = *now + 300;
 753                         }
 754                 } else
 755                         shutdown_time = *now + next_time;
 756         } else if (s < f && *now >= f) {
 757                 shutdown_time = s + DAYS_TO_SECS;
 758         } else
 759                 shutdown_time = s;
 760 }
 761 
 762 static int
 763 is_ok2shutdown(time_t *now)
 764 {
 765         int     prom_fd = -1;
 766         char    power_cycles_st[LLEN];
 767         char    power_cycle_limit_st[LLEN];
 768         char    system_board_date_st[LLEN];
 769         int     power_cycles, power_cycle_limit, free_cycles, scaled_cycles;
 770         time_t  life_began, life_passed;
 771         int     no_power_cycles = 0;
 772         int     no_system_board_date = 0;
 773         int     ret = 1;
 774 
 775         /* CONSTCOND */
 776         while (1) {
 777                 if ((prom_fd = open(PROM, O_RDWR)) == -1 &&
 778                     (errno == EAGAIN))
 779                         continue;
 780                 break;
 781         }
 782 
 783         /*
 784          * when #power-cycles property does not exist
 785          * power cycles are unlimited.
 786          */
 787         if (get_prom(prom_fd, options, "#power-cycles",
 788             power_cycles_st, sizeof (power_cycles_st)) == 0)
 789                 goto ckdone;
 790 
 791         if (get_prom(prom_fd, root, "power-cycle-limit",
 792             power_cycle_limit_st, sizeof (power_cycle_limit_st)) == 0) {
 793                 power_cycle_limit = DEFAULT_POWER_CYCLE_LIMIT;
 794         } else {
 795                 power_cycle_limit = atoi(power_cycle_limit_st);
 796         }
 797 
 798         /*
 799          * Allow 10% of power_cycle_limit as free cycles.
 800          */
 801         free_cycles = power_cycle_limit / 10;
 802 
 803         power_cycles = atoi(power_cycles_st);
 804         if (power_cycles < 0)
 805                 no_power_cycles++;
 806         else if (power_cycles <= free_cycles)
 807                 goto ckdone;
 808 
 809         if (no_power_cycles && log_power_cycles_error == 0) {
 810                 logerror("Invalid PROM property \"#power-cycles\" was found.");
 811                 log_power_cycles_error++;
 812         }
 813 
 814         if (get_prom(prom_fd, options, "system-board-date",
 815             system_board_date_st, sizeof (system_board_date_st)) == 0) {
 816                 no_system_board_date++;
 817         } else {
 818                 life_began = strtol(system_board_date_st, (char **)NULL, 16);
 819                 if (life_began > *now) {
 820                         no_system_board_date++;
 821                 }
 822         }
 823         if (no_system_board_date) {
 824                 if (log_system_board_date_error == 0) {
 825                         logerror("No or invalid PROM property "
 826                             "\"system-board-date\" was found.");
 827                         log_system_board_date_error++;
 828                 }
 829                 life_began = DEFAULT_SYSTEM_BOARD_DATE;
 830         }
 831 
 832         life_passed = *now - life_began;
 833 
 834         /*
 835          * Since we don't keep the date that last free_cycle is ended, we
 836          * need to spread (power_cycle_limit - free_cycles) over the entire
 837          * 7-year life span instead of (lifetime - date free_cycles ended).
 838          */
 839         scaled_cycles = (int)(((float)life_passed / (float)LIFETIME_SECS) *
 840             (power_cycle_limit - free_cycles));
 841 
 842         if (no_power_cycles)
 843                 goto ckdone;
 844 
 845 #ifdef DEBUG
 846         (void) fprintf(stderr, "Actual power_cycles = %d\t"
 847             "Scaled power_cycles = %d\n", power_cycles, scaled_cycles);
 848 #endif
 849         if (power_cycles > scaled_cycles) {
 850                 if (log_no_autoshutdown_warning == 0) {
 851                         logerror("Automatic shutdown has been temporarily "
 852                             "suspended in order to preserve the reliability "
 853                             "of this system.");
 854                         log_no_autoshutdown_warning++;
 855                 }
 856                 ret = 0;
 857                 goto ckdone;
 858         }
 859 
 860 ckdone:
 861         if (prom_fd != -1)
 862                 (void) close(prom_fd);
 863         return (ret);
 864 }
 865 
 866 static void
 867 check_idleness(time_t *now, hrtime_t *hr_now)
 868 {
 869 
 870         /*
 871          * Check idleness only when autoshutdown is enabled.
 872          */
 873         if (!autoshutdown_en) {
 874                 checkidle_time = 0;
 875                 return;
 876         }
 877 
 878         info->pd_ttychars_idle = check_tty(hr_now, asinfo.ttychars_thold);
 879         info->pd_loadaverage_idle =
 880             check_load_ave(hr_now, asinfo.loadaverage_thold);
 881         info->pd_diskreads_idle = check_disks(hr_now, asinfo.diskreads_thold);
 882         info->pd_nfsreqs_idle = check_nfs(hr_now, asinfo.nfsreqs_thold);
 883 
 884 #ifdef DEBUG
 885         (void) fprintf(stderr, "Idle ttychars for %d secs.\n",
 886             info->pd_ttychars_idle);
 887         (void) fprintf(stderr, "Idle loadaverage for %d secs.\n",
 888             info->pd_loadaverage_idle);
 889         (void) fprintf(stderr, "Idle diskreads for %d secs.\n",
 890             info->pd_diskreads_idle);
 891         (void) fprintf(stderr, "Idle nfsreqs for %d secs.\n",
 892             info->pd_nfsreqs_idle);
 893 #endif
 894 
 895         checkidle_time = *now + IDLECHK_INTERVAL;
 896 }
 897 
 898 static int
 899 last_system_activity(hrtime_t *hr_now)
 900 {
 901         int     act_idle, latest;
 902 
 903         latest = info->pd_idle_time * 60;
 904         act_idle = last_tty_activity(hr_now, asinfo.ttychars_thold);
 905         latest = MIN(latest, act_idle);
 906         act_idle = last_load_ave_activity(hr_now);
 907         latest = MIN(latest, act_idle);
 908         act_idle = last_disk_activity(hr_now, asinfo.diskreads_thold);
 909         latest = MIN(latest, act_idle);
 910         act_idle = last_nfs_activity(hr_now, asinfo.nfsreqs_thold);
 911         latest = MIN(latest, act_idle);
 912 
 913         return (latest);
 914 }
 915 
 916 static int
 917 run_idlecheck()
 918 {
 919         char            pm_variable[LLEN];
 920         char            *cp;
 921         int             status;
 922         pid_t           child;
 923 
 924         /*
 925          * Reap any child process which has been left over.
 926          */
 927         while (waitpid((pid_t)-1, &status, WNOHANG) > 0)
 928                 ;
 929 
 930         /*
 931          * Execute the user's idlecheck script and set variable PM_IDLETIME.
 932          * Returned exit value is the idle time in minutes.
 933          */
 934         if ((child = fork1()) == 0) {
 935                 (void) sprintf(pm_variable, "PM_IDLETIME=%d",
 936                     info->pd_idle_time);
 937                 (void) putenv(pm_variable);
 938                 cp = strrchr(asinfo.idlecheck_path, '/');
 939                 if (cp == NULL)
 940                         cp = asinfo.idlecheck_path;
 941                 else
 942                         cp++;
 943                 (void) execl(asinfo.idlecheck_path, cp, NULL);
 944                 exit(-1);
 945         } else if (child == -1) {
 946                 return (info->pd_idle_time * 60);
 947         }
 948 
 949         /*
 950          * Wait until the idlecheck program completes.
 951          */
 952         if (waitpid(child, &status, 0) != child) {
 953                 /*
 954                  * We get here if the calling process gets a signal.
 955                  */
 956                 return (info->pd_idle_time * 60);
 957         }
 958 
 959         if (WEXITSTATUS(status) < 0) {
 960                 return (info->pd_idle_time * 60);
 961         } else {
 962                 return (WEXITSTATUS(status) * 60);
 963         }
 964 }
 965 
 966 static void
 967 set_alarm(time_t now)
 968 {
 969         time_t  itime, stime, next_time, max_time;
 970         int     next_alarm;
 971 
 972         max_time = MAX(checkidle_time, shutdown_time);
 973         if (max_time == 0) {
 974                 (void) alarm(0);
 975                 return;
 976         }
 977         itime = (checkidle_time == 0) ? max_time : checkidle_time;
 978         stime = (shutdown_time == 0) ? max_time : shutdown_time;
 979         next_time = MIN(itime, stime);
 980         next_alarm = (next_time <= now) ? 1 : (next_time - now);
 981         (void) alarm(next_alarm);
 982 
 983 #ifdef DEBUG
 984         (void) fprintf(stderr, "Currently @ %s", ctime(&now));
 985         (void) fprintf(stderr, "Checkidle in %d secs\n", checkidle_time - now);
 986         (void) fprintf(stderr, "Shutdown  in %d secs\n", shutdown_time - now);
 987         (void) fprintf(stderr, "Next alarm goes off in %d secs\n", next_alarm);
 988         (void) fprintf(stderr, "************************************\n");
 989 #endif
 990 }
 991 
 992 static int
 993 poweroff(const char *msg, char **cmd_argv)
 994 {
 995         struct stat     statbuf;
 996         pid_t           pid, child;
 997         struct passwd   *pwd;
 998         char            *home, *user;
 999         char            ehome[] = "HOME=";
1000         char            euser[] = "LOGNAME=";
1001         int             status;
1002         char            **ca;
1003 
1004         if (mutex_trylock(&poweroff_mutex) != 0)
1005                 return (0);
1006 
1007         if (stat("/dev/console", &statbuf) == -1 ||
1008             (pwd = getpwuid(statbuf.st_uid)) == NULL) {
1009                 (void) mutex_unlock(&poweroff_mutex);
1010                 return (1);
1011         }
1012 
1013         if (msg)
1014                 syslog(LOG_NOTICE, msg);
1015 
1016         if (*cmd_argv == NULL) {
1017                 logerror("No command to run.");
1018                 (void) mutex_unlock(&poweroff_mutex);
1019                 return (1);
1020         }
1021 
1022         home = malloc(strlen(pwd->pw_dir) + sizeof (ehome));
1023         user = malloc(strlen(pwd->pw_name) + sizeof (euser));
1024         if (home == NULL || user == NULL) {
1025                 free(home);
1026                 free(user);
1027                 logerror("No memory.");
1028                 (void) mutex_unlock(&poweroff_mutex);
1029                 return (1);
1030         }
1031         (void) strcpy(home, ehome);
1032         (void) strcat(home, pwd->pw_dir);
1033         (void) strcpy(user, euser);
1034         (void) strcat(user, pwd->pw_name);
1035 
1036         /*
1037          * Need to simulate the user enviroment, minimaly set HOME, and USER.
1038          */
1039         if ((child = fork1()) == 0) {
1040                 (void) putenv(home);
1041                 (void) putenv(user);
1042                 (void) setgid(pwd->pw_gid);
1043                 (void) setuid(pwd->pw_uid);
1044 
1045                 /*
1046                  * check for shutdown flag and set environment
1047                  */
1048                 for (ca = cmd_argv; *ca; ca++) {
1049                         if (strcmp("-h", *ca) == 0) {
1050                                 (void) putenv("SYSSUSPENDDODEFAULT=");
1051                                 break;
1052                         }
1053                 }
1054 
1055                 (void) execv(cmd_argv[0], cmd_argv);
1056                 exit(EXIT_FAILURE);
1057         } else {
1058                 free(home);
1059                 free(user);
1060                 if (child == -1) {
1061                         (void) mutex_unlock(&poweroff_mutex);
1062                         return (1);
1063                 }
1064         }
1065         pid = 0;
1066         while (pid != child)
1067                 pid = wait(&status);
1068         if (WEXITSTATUS(status)) {
1069                 (void) syslog(LOG_ERR, "Failed to exec \"%s\".", cmd_argv[0]);
1070                 (void) mutex_unlock(&poweroff_mutex);
1071                 return (1);
1072         }
1073 
1074         (void) mutex_unlock(&poweroff_mutex);
1075         return (0);
1076 }
1077 
1078 #define PBUFSIZE        256
1079 
1080 /*
1081  * Gets the value of a prom property at either root or options node.  It
1082  * returns 1 if it is successful, otherwise it returns 0 .
1083  */
1084 static int
1085 get_prom(int prom_fd, prom_node_t node_name,
1086         char *property_name, char *property_value, size_t len)
1087 {
1088         union {
1089                 char buf[PBUFSIZE + sizeof (uint_t)];
1090                 struct openpromio opp;
1091         } oppbuf;
1092         register struct openpromio *opp = &(oppbuf.opp);
1093         int     got_it = 0;
1094 
1095         if (prom_fd == -1) {
1096                 return (0);
1097         }
1098 
1099         switch (node_name) {
1100         case root:
1101                 (void *) memset(oppbuf.buf, 0, PBUFSIZE);
1102                 opp->oprom_size = PBUFSIZE;
1103                 if (ioctl(prom_fd, OPROMNEXT, opp) < 0) {
1104                         return (0);
1105                 }
1106 
1107                 /*
1108                  * Passing null string will give us the first property.
1109                  */
1110                 (void *) memset(oppbuf.buf, 0, PBUFSIZE);
1111                 do {
1112                         opp->oprom_size = PBUFSIZE;
1113                         if (ioctl(prom_fd, OPROMNXTPROP, opp) < 0) {
1114                                 return (0);
1115                         }
1116                         if (strcmp(opp->oprom_array, property_name) == 0) {
1117                                 got_it++;
1118                                 break;
1119                         }
1120                 } while (opp->oprom_size > 0);
1121 
1122                 if (!got_it) {
1123                         return (0);
1124                 }
1125                 if (got_it && property_value == NULL) {
1126                         return (1);
1127                 }
1128                 opp->oprom_size = PBUFSIZE;
1129                 if (ioctl(prom_fd, OPROMGETPROP, opp) < 0) {
1130                         return (0);
1131                 }
1132                 if (opp->oprom_size == 0) {
1133                         *property_value = '\0';
1134                 } else {
1135                         estrcpy(property_value, opp->oprom_array, len);
1136                 }
1137                 break;
1138         case options:
1139                 estrcpy(opp->oprom_array, property_name, PBUFSIZE);
1140                 opp->oprom_size = PBUFSIZE;
1141                 if (ioctl(prom_fd, OPROMGETOPT, opp) < 0) {
1142                         return (0);
1143                 }
1144                 if (opp->oprom_size == 0) {
1145                         return (0);
1146                 }
1147                 if (property_value != NULL) {
1148                         estrcpy(property_value, opp->oprom_array, len);
1149                 }
1150                 break;
1151         default:
1152                 logerror("Only root node and options node are supported.\n");
1153                 return (0);
1154         }
1155 
1156         return (1);
1157 }
1158 
1159 #define isspace(ch)     ((ch) == ' ' || (ch) == '\t')
1160 #define iseol(ch)       ((ch) == '\n' || (ch) == '\r' || (ch) == '\f')
1161 
1162 /*ARGSUSED*/
1163 static void
1164 power_button_monitor(void *arg)
1165 {
1166         struct pollfd pfd;
1167         int events, ret;
1168 
1169         if (ioctl(pb_fd, PB_BEGIN_MONITOR, NULL) == -1) {
1170                 logerror("Failed to monitor the power button.");
1171                 thr_exit((void *) 0);
1172         }
1173 
1174         pfd.fd = pb_fd;
1175         pfd.events = POLLIN;
1176 
1177         /*CONSTCOND*/
1178         while (1) {
1179                 if (poll(&pfd, 1, INFTIM) == -1) {
1180                         logerror("Failed to poll for power button events.");
1181                         thr_exit((void *) 0);
1182                 }
1183 
1184                 if (!(pfd.revents & POLLIN))
1185                         continue;
1186 
1187                 /*
1188                  * Monitor the power button, but only take action if
1189                  * gnome-power-manager is not running.
1190                  *
1191                  * ret greater than 0 means could not find process.
1192                  */
1193                 ret = system("/usr/bin/pgrep -fx gnome-power-manager");
1194 
1195                 if (ioctl(pfd.fd, PB_GET_EVENTS, &events) == -1) {
1196                         logerror("Failed to get power button events.");
1197                         thr_exit((void *) 0);
1198                 }
1199 
1200                 if ((ret > 0) && (events & PB_BUTTON_PRESS) &&
1201                     (poweroff(NULL, power_button_cmd) != 0)) {
1202                         logerror("Power button is pressed, powering "
1203                             "down the system!");
1204 
1205                         /*
1206                          * Send SIGPWR signal to the init process to
1207                          * shut down the system.
1208                          */
1209                         if (kill(1, SIGPWR) == -1)
1210                                 (void) uadmin(A_SHUTDOWN, AD_POWEROFF, 0);
1211                 }
1212 
1213                 /*
1214                  * Clear any power button event that has happened
1215                  * meanwhile we were busy processing the last one.
1216                  */
1217                 if (ioctl(pfd.fd, PB_GET_EVENTS, &events) == -1) {
1218                         logerror("Failed to get power button events.");
1219                         thr_exit((void *) 0);
1220                 }
1221         }
1222 }
1223 
1224 static void
1225 do_attach(void)
1226 {
1227         if (read_cpr_config() < 0)
1228                 return;
1229 
1230         /*
1231          * If autopm behavior is explicitly enabled for energystar-v2, or
1232          * set to default for energystar-v3, create a new thread to attach
1233          * all devices.
1234          */
1235         estar_v3_prop = asinfo.is_autopm_default;
1236         if ((strcmp(asinfo.apm_behavior, "enable") == 0) ||
1237             (estar_v3_prop && strcmp(asinfo.apm_behavior, "default") == 0)) {
1238                 if (powerd_debug)
1239                         logerror("powerd starting device attach thread.");
1240                 if (thr_create(NULL, NULL, attach_devices, NULL,
1241                     THR_DAEMON, NULL) != 0) {
1242                         logerror("Unable to create thread to attach devices.");
1243                 }
1244         }
1245 }
1246 
1247 /*ARGSUSED*/
1248 static void *
1249 attach_devices(void *arg)
1250 {
1251         di_node_t root_node;
1252 
1253         (void) sleep(60);       /* let booting finish first */
1254 
1255         if ((root_node = di_init("/", DINFOFORCE)) == DI_NODE_NIL) {
1256                 logerror("Failed to attach devices.");
1257                 return (NULL);
1258         }
1259         di_fini(root_node);
1260 
1261         /*
1262          * Unload all the modules.
1263          */
1264         (void) modctl(MODUNLOAD, 0);
1265 
1266         return (NULL);
1267 }
1268 
1269 
1270 /*
1271  * Create a file which will contain our pid.  Pmconfig will check this file
1272  * to see if we are running and can use the pid to signal us.  Returns the
1273  * file descriptor if successful, -1 otherwise.
1274  *
1275  * Note: Deal with attempt to launch multiple instances and also with existence
1276  * of an obsolete pid file caused by an earlier abort.
1277  */
1278 static int
1279 open_pidfile(char *me)
1280 {
1281         int fd;
1282         const char *e1 = "%s: Cannot open pid file for read: ";
1283         const char *e2 = "%s: Cannot unlink obsolete pid file: ";
1284         const char *e3 = "%s: Either another daemon is running or the"
1285             " process is defunct (pid %d). \n";
1286         const char *e4 = "%s: Cannot create pid file: ";
1287 
1288 again:
1289         if ((fd = open(pidpath, O_CREAT | O_EXCL | O_WRONLY, 0444)) == -1) {
1290                 if (errno  == EEXIST) {
1291                         FILE *fp;
1292                         pid_t pid;
1293 
1294                         if ((fp = fopen(pidpath, "r")) == NULL) {
1295                                 (void) fprintf(stderr, e1, me);
1296                                 perror(NULL);
1297                                 return (-1);
1298                         }
1299 
1300                         /* Read the pid */
1301                         pid = (pid_t)-1;
1302                         (void) fscanf(fp, "%ld", &pid);
1303                         (void) fclose(fp);
1304                         if (pid == -1) {
1305                                 if (unlink(pidpath) == -1) {
1306                                         (void) fprintf(stderr, e2, me);
1307                                         perror(NULL);
1308                                         return (-1);
1309                                 } else /* try without corrupted file */
1310                                         goto again;
1311                         }
1312 
1313                         /* Is pid for a running process */
1314                         if (kill(pid, 0) == -1) {
1315                                 if (errno == ESRCH) {
1316                                         if (unlink(pidpath) == -1) {
1317                                                 (void) fprintf(stderr, e2, me);
1318                                                 perror(NULL);
1319                                                 return (-1);
1320                                         } else  /* try without obsolete file */
1321                                                 goto again;
1322                                 }
1323                         } else {    /* powerd deamon still running or defunct */
1324                                 (void) fprintf(stderr, e3, me, pid);
1325                                 return (-1);
1326                         }
1327 
1328                 } else {        /* create failure not due to existing file */
1329                         (void) fprintf(stderr, e4, me);
1330                         perror(NULL);
1331                         return (-1);
1332                 }
1333         }
1334 
1335         (void) fchown(fd, (uid_t)-1, (gid_t)0);
1336         return (fd);
1337 }
1338 
1339 /*
1340  * Write a pid to the pid file.  Report errors to syslog.
1341  *
1342  */
1343 static int
1344 write_pidfile(int fd, pid_t pid)
1345 {
1346         int     len;
1347         int     rc = 0;                 /* assume success */
1348 
1349         len = sprintf(scratch, "%ld\n", pid);
1350         if (write(fd, scratch, len) != len) {
1351                 logerror("Cannot write pid file: %s", strerror(errno));
1352                 rc = -1;
1353         }
1354 
1355         return (rc);
1356 }