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