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