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