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