1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> /* Standard */ 27 #include <stdlib.h> 28 #include <fcntl.h> 29 #include <sys/types.h> 30 #include <time.h> 31 #include <string.h> 32 #include <errno.h> 33 #include <pwd.h> 34 #include <dirent.h> 35 #include <thread.h> 36 #include <limits.h> 37 #include <sys/todio.h> /* Time-Of-Day chip */ 38 #include <sys/stat.h> 39 #include <sys/wait.h> 40 #include <sys/ipc.h> /* IPC functions */ 41 #include <signal.h> /* signal handling */ 42 #include <syslog.h> 43 #include <unistd.h> 44 #include <libdevinfo.h> 45 #include <poll.h> 46 #include <sys/pm.h> /* power management driver */ 47 #include <sys/uadmin.h> 48 #include <sys/openpromio.h> /* for prom access */ 49 #include <sys/sysmacros.h> /* for MIN & MAX macros */ 50 #include <sys/modctl.h> 51 #include <sys/stropts.h> /* for INFTIM */ 52 #include <sys/pbio.h> 53 #include <sys/cpr.h> 54 #include <sys/srn.h> 55 #include <stdarg.h> 56 57 #include "powerd.h" 58 59 /* External Functions */ 60 extern struct tm *localtime_r(const time_t *, struct tm *); 61 extern void sysstat_init(void); 62 extern int check_tty(hrtime_t *, int); 63 extern int check_disks(hrtime_t *, int); 64 extern int check_load_ave(hrtime_t *, float); 65 extern int check_nfs(hrtime_t *, int); 66 extern int last_disk_activity(hrtime_t *, int); 67 extern int last_tty_activity(hrtime_t *, int); 68 extern int last_load_ave_activity(hrtime_t *); 69 extern int last_nfs_activity(hrtime_t *, int); 70 71 #define PM "/dev/pm" 72 #define TOD "/dev/tod" 73 #define PROM "/dev/openprom" 74 #define PB "/dev/power_button" 75 #define SRN "/dev/srn" 76 #define LOGFILE "./powerd.log" 77 78 #define PBM_THREAD 0 79 #define ATTACH_THREAD 1 80 #define NUM_THREADS 2 81 82 #define CHECK_INTERVAL 5 83 #define IDLECHK_INTERVAL 15 84 #define MINS_TO_SECS 60 85 #define HOURS_TO_SECS (60 * 60) 86 #define DAYS_TO_SECS (24 * 60 * 60) 87 #define HOURS_TO_MINS 60 88 #define DAYS_TO_MINS (24 * 60) 89 90 #define LIFETIME_SECS (7 * 365 * DAYS_TO_SECS) 91 #define DEFAULT_POWER_CYCLE_LIMIT 10000 92 #define DEFAULT_SYSTEM_BOARD_DATE 804582000 /* July 1, 1995 */ 93 94 #define LLEN 80 95 96 typedef enum {root, options} prom_node_t; 97 98 /* State Variables */ 99 static struct cprconfig asinfo; 100 static time_t shutdown_time; /* Time for next shutdown check */ 101 static time_t checkidle_time; /* Time for next idleness check */ 102 static time_t last_resume; 103 pwr_info_t *info; /* private as config data buffer */ 104 static int pb_fd; /* power button driver */ 105 static int broadcast; /* Enables syslog messages */ 106 static int start_calc; 107 static int autoshutdown_en; 108 static int do_idlecheck; 109 static int got_sighup; 110 static int estar_v2_prop; 111 static int estar_v3_prop; 112 static int log_power_cycles_error = 0; 113 static int log_system_board_date_error = 0; 114 static int log_no_autoshutdown_warning = 0; 115 static mutex_t poweroff_mutex; 116 117 static char *autoshutdown_cmd[] = { 118 "/usr/bin/sys-suspend", 119 "-n", "-d", ":0", NULL 120 }; 121 122 static char *power_button_cmd[] = { 123 "/usr/bin/sys-suspend", 124 "-h", "-d", ":0", NULL 125 }; 126 127 static char *autoS3_cmd[] = { 128 "/usr/bin/sys-suspend", 129 "-n", "-d", ":0", NULL 130 }; 131 132 static char pidpath[] = PIDPATH; 133 static char scratch[PATH_MAX]; 134 static char *prog; 135 136 /* Local Functions */ 137 static void alarm_handler(int); 138 static void thaw_handler(int); 139 static void kill_handler(int); 140 static void work_handler(int); 141 static void check_shutdown(time_t *, hrtime_t *); 142 static void check_idleness(time_t *, hrtime_t *); 143 static int last_system_activity(hrtime_t *); 144 static int run_idlecheck(void); 145 static void set_alarm(time_t); 146 static int poweroff(const char *, char **); 147 static int is_ok2shutdown(time_t *); 148 static int get_prom(int, prom_node_t, char *, char *, size_t); 149 static void power_button_monitor(void *); 150 static int open_pidfile(char *); 151 static int write_pidfile(int, pid_t); 152 static int read_cpr_config(void); 153 static void system_activity_monitor(void); 154 static void autos3_monitor(void); 155 static void do_attach(void); 156 static void *attach_devices(void *); 157 static int powerd_debug; 158 159 /* PRINTFLIKE1 */ 160 static void 161 logerror(const char *fmt, ...) 162 { 163 va_list args; 164 165 va_start(args, fmt); 166 if (broadcast) 167 vsyslog(LOG_ERR, fmt, args); 168 va_end(args); 169 } 170 171 172 static void 173 estrcpy(char *dst, char *src, size_t dlen) 174 { 175 size_t slen; 176 177 slen = strlcpy(dst, src, dlen); 178 if (slen >= dlen) { 179 logerror("%s: string too long \"%s ...\"\n" 180 "(len %d, max %d)\n", prog, dst, slen, dlen - 1); 181 exit(EXIT_FAILURE); 182 } 183 } 184 185 186 int 187 main(int argc, char *argv[]) 188 { 189 pid_t pid; 190 int pm_fd; 191 struct sigaction act; 192 sigset_t sigmask; 193 int c; 194 char errmsg[PATH_MAX + 64]; 195 int pid_fd; 196 197 prog = argv[0]; 198 if (geteuid() != 0) { 199 (void) fprintf(stderr, "%s: Must be root\n", prog); 200 exit(EXIT_FAILURE); 201 } 202 203 if ((pid_fd = open_pidfile(prog)) == -1) 204 exit(EXIT_FAILURE); 205 206 /* 207 * Process options 208 */ 209 broadcast = 1; 210 while ((c = getopt(argc, argv, "nd")) != EOF) { 211 switch (c) { 212 case 'd': 213 powerd_debug = 1; 214 break; 215 case 'n': 216 broadcast = 0; 217 break; 218 case '?': 219 (void) fprintf(stderr, "Usage: %s [-n]\n", prog); 220 exit(EXIT_FAILURE); 221 } 222 } 223 224 pm_fd = open(PM, O_RDWR); 225 if (pm_fd == -1) { 226 (void) snprintf(errmsg, sizeof (errmsg), "%s: %s", prog, PM); 227 perror(errmsg); 228 exit(EXIT_FAILURE); 229 } 230 (void) close(pm_fd); 231 232 /* 233 * Initialize mutex lock used to insure only one command to 234 * run at a time. 235 */ 236 if (mutex_init(&poweroff_mutex, USYNC_THREAD, NULL) != 0) { 237 (void) fprintf(stderr, 238 "%s: Unable to initialize mutex lock\n", prog); 239 exit(EXIT_FAILURE); 240 } 241 242 if ((info = (pwr_info_t *)malloc(sizeof (pwr_info_t))) == NULL) { 243 (void) snprintf(errmsg, sizeof (errmsg), "%s: malloc", prog); 244 perror(errmsg); 245 exit(EXIT_FAILURE); 246 } 247 248 /* 249 * Daemon is set to go... 250 */ 251 if ((pid = fork()) < 0) 252 exit(EXIT_FAILURE); 253 else if (pid != 0) 254 exit(EXIT_SUCCESS); 255 256 pid = getpid(); 257 openlog(prog, 0, LOG_DAEMON); 258 if (write_pidfile(pid_fd, pid) == -1) /* logs errors on failure */ 259 exit(EXIT_FAILURE); 260 (void) close(pid_fd); 261 262 /* 263 * Close all the parent's file descriptors (Bug 1225843). 264 */ 265 closefrom(0); 266 (void) setsid(); 267 (void) chdir("/"); 268 (void) umask(0); 269 #ifdef DEBUG 270 /* 271 * Connect stdout to the console. 272 */ 273 if (dup2(open("/dev/console", O_WRONLY|O_NOCTTY), 1) == -1) { 274 logerror("Unable to connect to the console."); 275 } 276 #endif 277 info->pd_flags = PD_AC; 278 info->pd_idle_time = -1; 279 info->pd_start_time = 0; 280 info->pd_finish_time = 0; 281 282 /* 283 * Allow SIGQUIT, SIGINT and SIGTERM signals to terminate us 284 * any time 285 */ 286 act.sa_handler = kill_handler; 287 (void) sigemptyset(&act.sa_mask); 288 act.sa_flags = 0; 289 (void) sigaction(SIGQUIT, &act, NULL); 290 (void) sigaction(SIGINT, &act, NULL); 291 (void) sigaction(SIGTERM, &act, NULL); 292 293 (void) sigfillset(&sigmask); 294 (void) sigdelset(&sigmask, SIGQUIT); 295 (void) sigdelset(&sigmask, SIGINT); 296 (void) sigdelset(&sigmask, SIGTERM); 297 (void) thr_sigsetmask(SIG_SETMASK, &sigmask, NULL); 298 299 /* 300 * If "power_button" device node can be opened, create a new 301 * thread to monitor the power button. 302 */ 303 if ((pb_fd = open(PB, O_RDONLY)) != -1) { 304 if (powerd_debug) 305 logerror("powerd starting power button monitor."); 306 if (thr_create(NULL, NULL, 307 (void *(*)(void *))power_button_monitor, NULL, 308 THR_DAEMON, NULL) != 0) { 309 logerror("Unable to monitor system's power button."); 310 } 311 } 312 313 do_attach(); 314 315 /* 316 * Create a new thread to monitor system activity and suspend 317 * system if idle. 318 */ 319 if (powerd_debug) 320 logerror("powerd starting system activity monitor."); 321 if (thr_create(NULL, NULL, 322 (void *(*)(void *))system_activity_monitor, NULL, 323 THR_DAEMON, NULL) != 0) { 324 logerror("Unable to create thread to monitor system activity."); 325 } 326 327 /* 328 * Create a new thread to handle autos3 trigger 329 */ 330 if (powerd_debug) 331 logerror("powerd starting autos3 monitor."); 332 if (thr_create(NULL, NULL, 333 (void *(*)(void *))autos3_monitor, NULL, THR_DAEMON, NULL) != 0) { 334 logerror("Unable to create thread to monitor autos3 activity."); 335 } 336 337 /* 338 * Block until we receive an explicit terminate signal 339 */ 340 (void) sigsuspend(&sigmask); 341 342 return (1); 343 } 344 345 static void 346 system_activity_monitor(void) 347 { 348 struct sigaction act; 349 sigset_t sigmask; 350 351 /* 352 * Setup for gathering system's statistic. 353 */ 354 sysstat_init(); 355 356 /* 357 * In addition to the SIGQUIT, SIGINT and SIGTERM signals already 358 * being handled, this thread also needs to handle SIGHUP, SIGALRM 359 * and SIGTHAW signals. 360 */ 361 (void) sigemptyset(&act.sa_mask); 362 act.sa_flags = 0; 363 act.sa_handler = alarm_handler; 364 (void) sigaction(SIGALRM, &act, NULL); 365 act.sa_handler = work_handler; 366 (void) sigaction(SIGHUP, &act, NULL); 367 act.sa_handler = thaw_handler; 368 (void) sigaction(SIGTHAW, &act, NULL); 369 370 /* 371 * Invoke work_handler with a dummy SIGHUP signal to read 372 * cpr config file, get autoshutdown properties and schedule 373 * an alarm if needed. 374 */ 375 work_handler(SIGHUP); 376 377 /* 378 * Wait for signal to read file 379 */ 380 (void) thr_sigsetmask(0, 0, &sigmask); 381 (void) sigdelset(&sigmask, SIGHUP); 382 (void) sigdelset(&sigmask, SIGALRM); 383 (void) sigdelset(&sigmask, SIGTHAW); 384 (void) thr_sigsetmask(SIG_SETMASK, &sigmask, NULL); 385 do { 386 (void) sigsuspend(&sigmask); 387 } while (errno == EINTR); 388 } 389 390 static void 391 autos3_monitor(void) 392 { 393 struct pollfd poll_fd; 394 srn_event_info_t srn_event; /* contains suspend type */ 395 int fd, ret; 396 397 fd = open(SRN, O_RDWR|O_EXCL|O_NDELAY); 398 if (fd == -1) { 399 logerror("Unable to open %s: %s", SRN, strerror(errno)); 400 thr_exit((void *) errno); 401 } 402 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 *) 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 *) 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 *) 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 } 1357