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