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