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