1d50a71bdSMitsuru IWASAKI /*- 2d50a71bdSMitsuru IWASAKI * APM (Advanced Power Management) Event Dispatcher 3d50a71bdSMitsuru IWASAKI * 4d50a71bdSMitsuru IWASAKI * Copyright (c) 1999 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 5d50a71bdSMitsuru IWASAKI * Copyright (c) 1999 KOIE Hidetaka <koie@suri.co.jp> 6d50a71bdSMitsuru IWASAKI * All rights reserved. 7d50a71bdSMitsuru IWASAKI * 8d50a71bdSMitsuru IWASAKI * Redistribution and use in source and binary forms, with or without 9d50a71bdSMitsuru IWASAKI * modification, are permitted provided that the following conditions 10d50a71bdSMitsuru IWASAKI * are met: 11d50a71bdSMitsuru IWASAKI * 1. Redistributions of source code must retain the above copyright 12d50a71bdSMitsuru IWASAKI * notice, this list of conditions and the following disclaimer. 13d50a71bdSMitsuru IWASAKI * 2. Redistributions in binary form must reproduce the above copyright 14d50a71bdSMitsuru IWASAKI * notice, this list of conditions and the following disclaimer in the 15d50a71bdSMitsuru IWASAKI * documentation and/or other materials provided with the distribution. 16d50a71bdSMitsuru IWASAKI * 17d50a71bdSMitsuru IWASAKI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18d50a71bdSMitsuru IWASAKI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19d50a71bdSMitsuru IWASAKI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20d50a71bdSMitsuru IWASAKI * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21d50a71bdSMitsuru IWASAKI * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22d50a71bdSMitsuru IWASAKI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23d50a71bdSMitsuru IWASAKI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24d50a71bdSMitsuru IWASAKI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25d50a71bdSMitsuru IWASAKI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26d50a71bdSMitsuru IWASAKI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27d50a71bdSMitsuru IWASAKI * SUCH DAMAGE. 28d50a71bdSMitsuru IWASAKI */ 29d50a71bdSMitsuru IWASAKI 30d50a71bdSMitsuru IWASAKI #ifndef lint 31d50a71bdSMitsuru IWASAKI static const char rcsid[] = 32d50a71bdSMitsuru IWASAKI "$Id: apmd.c,v 1.1.3.13 1999/06/18 04:07:05 koie Exp $"; 33d50a71bdSMitsuru IWASAKI #endif /* not lint */ 34d50a71bdSMitsuru IWASAKI 35d50a71bdSMitsuru IWASAKI #include <assert.h> 36d50a71bdSMitsuru IWASAKI #include <bitstring.h> 37d50a71bdSMitsuru IWASAKI #include <err.h> 38d50a71bdSMitsuru IWASAKI #include <errno.h> 39d50a71bdSMitsuru IWASAKI #include <fcntl.h> 40d50a71bdSMitsuru IWASAKI #include <paths.h> 41d50a71bdSMitsuru IWASAKI #include <signal.h> 42d50a71bdSMitsuru IWASAKI #include <stdio.h> 43d50a71bdSMitsuru IWASAKI #include <stdlib.h> 44d50a71bdSMitsuru IWASAKI #include <string.h> 45d50a71bdSMitsuru IWASAKI #include <syslog.h> 46d50a71bdSMitsuru IWASAKI #include <unistd.h> 47d50a71bdSMitsuru IWASAKI #include <sys/ioctl.h> 48d50a71bdSMitsuru IWASAKI #include <sys/types.h> 49d50a71bdSMitsuru IWASAKI #include <sys/time.h> 50d50a71bdSMitsuru IWASAKI #include <sys/wait.h> 51d50a71bdSMitsuru IWASAKI #include <machine/apm_bios.h> 52d50a71bdSMitsuru IWASAKI 53d50a71bdSMitsuru IWASAKI #include "apmd.h" 54d50a71bdSMitsuru IWASAKI 55d50a71bdSMitsuru IWASAKI extern int yyparse(void); 56d50a71bdSMitsuru IWASAKI 57d50a71bdSMitsuru IWASAKI int debug_level = 0; 58d50a71bdSMitsuru IWASAKI int verbose = 0; 59d50a71bdSMitsuru IWASAKI const char *apmd_configfile = APMD_CONFIGFILE; 60d50a71bdSMitsuru IWASAKI const char *apmd_pidfile = APMD_PIDFILE; 61d50a71bdSMitsuru IWASAKI int apmctl_fd = -1; 62d50a71bdSMitsuru IWASAKI 63d50a71bdSMitsuru IWASAKI /* 64d50a71bdSMitsuru IWASAKI * table of event handlers 65d50a71bdSMitsuru IWASAKI */ 66d50a71bdSMitsuru IWASAKI #define EVENT_CONFIG_INITIALIZER(EV,R) { #EV, NULL, R }, 67d50a71bdSMitsuru IWASAKI struct event_config events[EVENT_MAX] = { 68d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(NOEVENT, 0) 69d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(STANDBYREQ, 1) 70d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(SUSPENDREQ, 1) 71d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(NORMRESUME, 0) 72d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(CRITRESUME, 0) 73d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(BATTERYLOW, 0) 74d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(POWERSTATECHANGE, 0) 75d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(UPDATETIME, 0) 76d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(CRITSUSPEND, 1) 77d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(USERSTANDBYREQ, 1) 78d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(USERSUSPENDREQ, 1) 79d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(STANDBYRESUME, 0) 80d50a71bdSMitsuru IWASAKI EVENT_CONFIG_INITIALIZER(CAPABILITIESCHANGE, 0) 81d50a71bdSMitsuru IWASAKI }; 82d50a71bdSMitsuru IWASAKI 83d50a71bdSMitsuru IWASAKI /* 84d50a71bdSMitsuru IWASAKI * default procedure 85d50a71bdSMitsuru IWASAKI */ 86d50a71bdSMitsuru IWASAKI struct event_cmd * 87d50a71bdSMitsuru IWASAKI event_cmd_default_clone(void *this) 88d50a71bdSMitsuru IWASAKI { 89d50a71bdSMitsuru IWASAKI struct event_cmd * oldone = this; 90d50a71bdSMitsuru IWASAKI struct event_cmd * newone = malloc(oldone->len); 91d50a71bdSMitsuru IWASAKI 92d50a71bdSMitsuru IWASAKI newone->next = NULL; 93d50a71bdSMitsuru IWASAKI newone->len = oldone->len; 94d50a71bdSMitsuru IWASAKI newone->name = oldone->name; 95d50a71bdSMitsuru IWASAKI newone->op = oldone->op; 96d50a71bdSMitsuru IWASAKI return newone; 97d50a71bdSMitsuru IWASAKI } 98d50a71bdSMitsuru IWASAKI 99d50a71bdSMitsuru IWASAKI /* 100d50a71bdSMitsuru IWASAKI * exec command 101d50a71bdSMitsuru IWASAKI */ 102d50a71bdSMitsuru IWASAKI int 103d50a71bdSMitsuru IWASAKI event_cmd_exec_act(void *this) 104d50a71bdSMitsuru IWASAKI { 105d50a71bdSMitsuru IWASAKI struct event_cmd_exec * p = this; 106d50a71bdSMitsuru IWASAKI int status = -1; 107d50a71bdSMitsuru IWASAKI pid_t pid; 108d50a71bdSMitsuru IWASAKI 109d50a71bdSMitsuru IWASAKI switch ((pid = fork())) { 110d50a71bdSMitsuru IWASAKI case -1: 111d50a71bdSMitsuru IWASAKI (void) warn("cannot fork"); 112d50a71bdSMitsuru IWASAKI goto out; 113d50a71bdSMitsuru IWASAKI case 0: 114d50a71bdSMitsuru IWASAKI /* child process */ 115d50a71bdSMitsuru IWASAKI execl(_PATH_BSHELL, "sh", "-c", p->line, (char *)NULL); 116d50a71bdSMitsuru IWASAKI _exit(127); 117d50a71bdSMitsuru IWASAKI default: 118d50a71bdSMitsuru IWASAKI /* parent process */ 119d50a71bdSMitsuru IWASAKI do { 120d50a71bdSMitsuru IWASAKI pid = waitpid(pid, &status, 0); 121d50a71bdSMitsuru IWASAKI } while (pid == -1 && errno == EINTR); 122d50a71bdSMitsuru IWASAKI break; 123d50a71bdSMitsuru IWASAKI } 124d50a71bdSMitsuru IWASAKI out: 125d50a71bdSMitsuru IWASAKI return status; 126d50a71bdSMitsuru IWASAKI } 127d50a71bdSMitsuru IWASAKI void 128d50a71bdSMitsuru IWASAKI event_cmd_exec_dump(void *this, FILE *fp) 129d50a71bdSMitsuru IWASAKI { 130d50a71bdSMitsuru IWASAKI fprintf(fp, " \"%s\"", ((struct event_cmd_exec *)this)->line); 131d50a71bdSMitsuru IWASAKI } 132d50a71bdSMitsuru IWASAKI struct event_cmd * 133d50a71bdSMitsuru IWASAKI event_cmd_exec_clone(void *this) 134d50a71bdSMitsuru IWASAKI { 135d50a71bdSMitsuru IWASAKI struct event_cmd_exec * newone = (struct event_cmd_exec *) event_cmd_default_clone(this); 136d50a71bdSMitsuru IWASAKI struct event_cmd_exec * oldone = this; 137d50a71bdSMitsuru IWASAKI 138d50a71bdSMitsuru IWASAKI newone->evcmd.next = NULL; 139d50a71bdSMitsuru IWASAKI newone->evcmd.len = oldone->evcmd.len; 140d50a71bdSMitsuru IWASAKI newone->evcmd.name = oldone->evcmd.name; 141d50a71bdSMitsuru IWASAKI newone->evcmd.op = oldone->evcmd.op; 142d50a71bdSMitsuru IWASAKI newone->line = strdup(oldone->line); 143d50a71bdSMitsuru IWASAKI return (struct event_cmd *) newone; 144d50a71bdSMitsuru IWASAKI } 145d50a71bdSMitsuru IWASAKI void 146d50a71bdSMitsuru IWASAKI event_cmd_exec_free(void *this) 147d50a71bdSMitsuru IWASAKI { 148d50a71bdSMitsuru IWASAKI free(((struct event_cmd_exec *)this)->line); 149d50a71bdSMitsuru IWASAKI } 150d50a71bdSMitsuru IWASAKI struct event_cmd_op event_cmd_exec_ops = { 151d50a71bdSMitsuru IWASAKI event_cmd_exec_act, 152d50a71bdSMitsuru IWASAKI event_cmd_exec_dump, 153d50a71bdSMitsuru IWASAKI event_cmd_exec_clone, 154d50a71bdSMitsuru IWASAKI event_cmd_exec_free 155d50a71bdSMitsuru IWASAKI }; 156d50a71bdSMitsuru IWASAKI 157d50a71bdSMitsuru IWASAKI /* 158d50a71bdSMitsuru IWASAKI * reject commad 159d50a71bdSMitsuru IWASAKI */ 160d50a71bdSMitsuru IWASAKI int 161d50a71bdSMitsuru IWASAKI event_cmd_reject_act(void *this) 162d50a71bdSMitsuru IWASAKI { 163d50a71bdSMitsuru IWASAKI int rc = -1; 164d50a71bdSMitsuru IWASAKI 165d50a71bdSMitsuru IWASAKI if (ioctl(apmctl_fd, APMIO_REJECTLASTREQ, NULL)) { 166d50a71bdSMitsuru IWASAKI syslog(LOG_NOTICE, "fail to reject\n"); 167d50a71bdSMitsuru IWASAKI goto out; 168d50a71bdSMitsuru IWASAKI } 169d50a71bdSMitsuru IWASAKI rc = 0; 170d50a71bdSMitsuru IWASAKI out: 171d50a71bdSMitsuru IWASAKI return rc; 172d50a71bdSMitsuru IWASAKI } 173d50a71bdSMitsuru IWASAKI struct event_cmd_op event_cmd_reject_ops = { 174d50a71bdSMitsuru IWASAKI event_cmd_reject_act, 175d50a71bdSMitsuru IWASAKI NULL, 176d50a71bdSMitsuru IWASAKI event_cmd_default_clone, 177d50a71bdSMitsuru IWASAKI NULL 178d50a71bdSMitsuru IWASAKI }; 179d50a71bdSMitsuru IWASAKI 180d50a71bdSMitsuru IWASAKI /* 181d50a71bdSMitsuru IWASAKI * manipulate event_config 182d50a71bdSMitsuru IWASAKI */ 183d50a71bdSMitsuru IWASAKI struct event_cmd * 184d50a71bdSMitsuru IWASAKI clone_event_cmd_list(struct event_cmd *p) 185d50a71bdSMitsuru IWASAKI { 186d50a71bdSMitsuru IWASAKI struct event_cmd dummy; 187d50a71bdSMitsuru IWASAKI struct event_cmd *q = &dummy; 188d50a71bdSMitsuru IWASAKI for ( ;p; p = p->next) { 189d50a71bdSMitsuru IWASAKI assert(p->op->clone); 190d50a71bdSMitsuru IWASAKI if ((q->next = p->op->clone(p)) == NULL) 191d50a71bdSMitsuru IWASAKI (void) err(1, "out of memory"); 192d50a71bdSMitsuru IWASAKI q = q->next; 193d50a71bdSMitsuru IWASAKI } 194d50a71bdSMitsuru IWASAKI q->next = NULL; 195d50a71bdSMitsuru IWASAKI return dummy.next; 196d50a71bdSMitsuru IWASAKI } 197d50a71bdSMitsuru IWASAKI void 198d50a71bdSMitsuru IWASAKI free_event_cmd_list(struct event_cmd *p) 199d50a71bdSMitsuru IWASAKI { 200d50a71bdSMitsuru IWASAKI struct event_cmd * q; 201d50a71bdSMitsuru IWASAKI for ( ; p ; p = q) { 202d50a71bdSMitsuru IWASAKI q = p->next; 203d50a71bdSMitsuru IWASAKI if (p->op->free) 204d50a71bdSMitsuru IWASAKI p->op->free(p); 205d50a71bdSMitsuru IWASAKI free(p); 206d50a71bdSMitsuru IWASAKI } 207d50a71bdSMitsuru IWASAKI } 208d50a71bdSMitsuru IWASAKI int 209d50a71bdSMitsuru IWASAKI register_apm_event_handlers( 210d50a71bdSMitsuru IWASAKI bitstr_t bit_decl(evlist, EVENT_MAX), 211d50a71bdSMitsuru IWASAKI struct event_cmd *cmdlist) 212d50a71bdSMitsuru IWASAKI { 213d50a71bdSMitsuru IWASAKI if (cmdlist) { 214d50a71bdSMitsuru IWASAKI bitstr_t bit_decl(tmp, EVENT_MAX); 215d50a71bdSMitsuru IWASAKI memcpy(&tmp, evlist, bitstr_size(EVENT_MAX)); 216d50a71bdSMitsuru IWASAKI 217d50a71bdSMitsuru IWASAKI for (;;) { 218d50a71bdSMitsuru IWASAKI int n; 219d50a71bdSMitsuru IWASAKI struct event_cmd *p; 220d50a71bdSMitsuru IWASAKI struct event_cmd *q; 221d50a71bdSMitsuru IWASAKI bit_ffs(tmp, EVENT_MAX, &n); 222d50a71bdSMitsuru IWASAKI if (n < 0) 223d50a71bdSMitsuru IWASAKI break; 224d50a71bdSMitsuru IWASAKI p = events[n].cmdlist; 225d50a71bdSMitsuru IWASAKI if ((q = clone_event_cmd_list(cmdlist)) == NULL) 226d50a71bdSMitsuru IWASAKI (void) err(1, "out of memory"); 227d50a71bdSMitsuru IWASAKI if (p) { 228d50a71bdSMitsuru IWASAKI while (p->next != NULL) 229d50a71bdSMitsuru IWASAKI p = p->next; 230d50a71bdSMitsuru IWASAKI p->next = q; 231d50a71bdSMitsuru IWASAKI } else { 232d50a71bdSMitsuru IWASAKI events[n].cmdlist = q; 233d50a71bdSMitsuru IWASAKI } 234d50a71bdSMitsuru IWASAKI bit_clear(tmp, n); 235d50a71bdSMitsuru IWASAKI } 236d50a71bdSMitsuru IWASAKI } 237d50a71bdSMitsuru IWASAKI return 0; 238d50a71bdSMitsuru IWASAKI } 239d50a71bdSMitsuru IWASAKI 240d50a71bdSMitsuru IWASAKI /* 241d50a71bdSMitsuru IWASAKI * execute command 242d50a71bdSMitsuru IWASAKI */ 243d50a71bdSMitsuru IWASAKI int 244d50a71bdSMitsuru IWASAKI exec_event_cmd(struct event_config *ev) 245d50a71bdSMitsuru IWASAKI { 246d50a71bdSMitsuru IWASAKI int status = 0; 247d50a71bdSMitsuru IWASAKI 248d50a71bdSMitsuru IWASAKI struct event_cmd *p = ev->cmdlist; 249d50a71bdSMitsuru IWASAKI for (; p; p = p->next) { 250d50a71bdSMitsuru IWASAKI assert(p->op->act); 251d50a71bdSMitsuru IWASAKI if (verbose) 252d50a71bdSMitsuru IWASAKI syslog(LOG_INFO, "action: %s", p->name); 253d50a71bdSMitsuru IWASAKI status = p->op->act(p); 254d50a71bdSMitsuru IWASAKI if (status) { 255d50a71bdSMitsuru IWASAKI syslog(LOG_NOTICE, "command finished with %d\n", status); 256d50a71bdSMitsuru IWASAKI if (ev->rejectable) { 257d50a71bdSMitsuru IWASAKI syslog(LOG_ERR, "canceled"); 258d50a71bdSMitsuru IWASAKI (void) event_cmd_reject_act(NULL); 259d50a71bdSMitsuru IWASAKI } 260d50a71bdSMitsuru IWASAKI break; 261d50a71bdSMitsuru IWASAKI } 262d50a71bdSMitsuru IWASAKI } 263d50a71bdSMitsuru IWASAKI return status; 264d50a71bdSMitsuru IWASAKI } 265d50a71bdSMitsuru IWASAKI 266d50a71bdSMitsuru IWASAKI /* 267d50a71bdSMitsuru IWASAKI * read config file 268d50a71bdSMitsuru IWASAKI */ 269d50a71bdSMitsuru IWASAKI extern FILE * yyin; 270d50a71bdSMitsuru IWASAKI extern int yydebug; 271d50a71bdSMitsuru IWASAKI 272d50a71bdSMitsuru IWASAKI void 273d50a71bdSMitsuru IWASAKI read_config(void) 274d50a71bdSMitsuru IWASAKI { 275d50a71bdSMitsuru IWASAKI int i; 276d50a71bdSMitsuru IWASAKI 277d50a71bdSMitsuru IWASAKI if ((yyin = fopen(apmd_configfile, "r")) == NULL) { 278d50a71bdSMitsuru IWASAKI (void) err(1, "cannot open config file"); 279d50a71bdSMitsuru IWASAKI } 280d50a71bdSMitsuru IWASAKI 281d50a71bdSMitsuru IWASAKI #ifdef DEBUG 282d50a71bdSMitsuru IWASAKI yydebug = debug_level; 283d50a71bdSMitsuru IWASAKI #endif 284d50a71bdSMitsuru IWASAKI 285d50a71bdSMitsuru IWASAKI if (yyparse() != 0) 286d50a71bdSMitsuru IWASAKI (void) err(1, "cannot parse config file"); 287d50a71bdSMitsuru IWASAKI 288d50a71bdSMitsuru IWASAKI fclose(yyin); 289d50a71bdSMitsuru IWASAKI 290d50a71bdSMitsuru IWASAKI /* enable events */ 291d50a71bdSMitsuru IWASAKI for (i = 0; i < EVENT_MAX; i++) { 292d50a71bdSMitsuru IWASAKI if (events[i].cmdlist) { 293d50a71bdSMitsuru IWASAKI u_int event_type = i; 294d50a71bdSMitsuru IWASAKI if (write(apmctl_fd, &event_type, sizeof(u_int)) == -1) { 295d50a71bdSMitsuru IWASAKI (void) err(1, "cannot enable event 0x%x", event_type); 296d50a71bdSMitsuru IWASAKI } 297d50a71bdSMitsuru IWASAKI } 298d50a71bdSMitsuru IWASAKI } 299d50a71bdSMitsuru IWASAKI } 300d50a71bdSMitsuru IWASAKI 301d50a71bdSMitsuru IWASAKI void 302d50a71bdSMitsuru IWASAKI dump_config() 303d50a71bdSMitsuru IWASAKI { 304d50a71bdSMitsuru IWASAKI int i; 305d50a71bdSMitsuru IWASAKI 306d50a71bdSMitsuru IWASAKI for (i = 0; i < EVENT_MAX; i++) { 307d50a71bdSMitsuru IWASAKI struct event_cmd * p; 308d50a71bdSMitsuru IWASAKI if ((p = events[i].cmdlist)) { 309d50a71bdSMitsuru IWASAKI fprintf(stderr, "apm_event %s {\n", events[i].name); 310d50a71bdSMitsuru IWASAKI for ( ; p ; p = p->next) { 311d50a71bdSMitsuru IWASAKI fprintf(stderr, "\t%s", p->name); 312d50a71bdSMitsuru IWASAKI if (p->op->dump) 313d50a71bdSMitsuru IWASAKI p->op->dump(p, stderr); 314d50a71bdSMitsuru IWASAKI fprintf(stderr, ";\n"); 315d50a71bdSMitsuru IWASAKI } 316d50a71bdSMitsuru IWASAKI fprintf(stderr, "}\n"); 317d50a71bdSMitsuru IWASAKI } 318d50a71bdSMitsuru IWASAKI } 319d50a71bdSMitsuru IWASAKI } 320d50a71bdSMitsuru IWASAKI 321d50a71bdSMitsuru IWASAKI void 322d50a71bdSMitsuru IWASAKI destroy_config() 323d50a71bdSMitsuru IWASAKI { 324d50a71bdSMitsuru IWASAKI int i; 325d50a71bdSMitsuru IWASAKI 326d50a71bdSMitsuru IWASAKI /* disable events */ 327d50a71bdSMitsuru IWASAKI for (i = 0; i < EVENT_MAX; i++) { 328d50a71bdSMitsuru IWASAKI if (events[i].cmdlist) { 329d50a71bdSMitsuru IWASAKI u_int event_type = i; 330d50a71bdSMitsuru IWASAKI if (write(apmctl_fd, &event_type, sizeof(u_int)) == -1) { 331d50a71bdSMitsuru IWASAKI (void) err(1, "cannot disable event 0x%x", event_type); 332d50a71bdSMitsuru IWASAKI } 333d50a71bdSMitsuru IWASAKI } 334d50a71bdSMitsuru IWASAKI } 335d50a71bdSMitsuru IWASAKI 336d50a71bdSMitsuru IWASAKI for (i = 0; i < EVENT_MAX; i++) { 337d50a71bdSMitsuru IWASAKI struct event_cmd * p; 338d50a71bdSMitsuru IWASAKI if ((p = events[i].cmdlist)) 339d50a71bdSMitsuru IWASAKI free_event_cmd_list(p); 340d50a71bdSMitsuru IWASAKI events[i].cmdlist = NULL; 341d50a71bdSMitsuru IWASAKI } 342d50a71bdSMitsuru IWASAKI } 343d50a71bdSMitsuru IWASAKI 344d50a71bdSMitsuru IWASAKI void 345d50a71bdSMitsuru IWASAKI restart() 346d50a71bdSMitsuru IWASAKI { 347d50a71bdSMitsuru IWASAKI destroy_config(); 348d50a71bdSMitsuru IWASAKI read_config(); 349d50a71bdSMitsuru IWASAKI if (verbose) 350d50a71bdSMitsuru IWASAKI dump_config(); 351d50a71bdSMitsuru IWASAKI } 352d50a71bdSMitsuru IWASAKI 353d50a71bdSMitsuru IWASAKI /* 354d50a71bdSMitsuru IWASAKI * write pid file 355d50a71bdSMitsuru IWASAKI */ 356d50a71bdSMitsuru IWASAKI static void 357d50a71bdSMitsuru IWASAKI write_pid() 358d50a71bdSMitsuru IWASAKI { 359d50a71bdSMitsuru IWASAKI FILE *fp = fopen(apmd_pidfile, "w"); 360d50a71bdSMitsuru IWASAKI 361d50a71bdSMitsuru IWASAKI if (fp) { 362d50a71bdSMitsuru IWASAKI fprintf(fp, "%d\n", getpid()); 363d50a71bdSMitsuru IWASAKI fclose(fp); 364d50a71bdSMitsuru IWASAKI } 365d50a71bdSMitsuru IWASAKI } 366d50a71bdSMitsuru IWASAKI 367d50a71bdSMitsuru IWASAKI /* 368d50a71bdSMitsuru IWASAKI * handle signals 369d50a71bdSMitsuru IWASAKI */ 370d50a71bdSMitsuru IWASAKI static int signal_fd[2]; 371d50a71bdSMitsuru IWASAKI 372d50a71bdSMitsuru IWASAKI void 373d50a71bdSMitsuru IWASAKI enque_signal(int sig) 374d50a71bdSMitsuru IWASAKI { 375d50a71bdSMitsuru IWASAKI if (write(signal_fd[1], &sig, sizeof sig) != sizeof sig) 376d50a71bdSMitsuru IWASAKI (void) err(1, "cannot process signal."); 377d50a71bdSMitsuru IWASAKI } 378d50a71bdSMitsuru IWASAKI 379d50a71bdSMitsuru IWASAKI void 380d50a71bdSMitsuru IWASAKI wait_child() 381d50a71bdSMitsuru IWASAKI { 382d50a71bdSMitsuru IWASAKI int status; 383d50a71bdSMitsuru IWASAKI while (waitpid(-1, &status, WNOHANG) > 0) 384d50a71bdSMitsuru IWASAKI ; 385d50a71bdSMitsuru IWASAKI } 386d50a71bdSMitsuru IWASAKI 387d50a71bdSMitsuru IWASAKI int 388d50a71bdSMitsuru IWASAKI proc_signal(int fd) 389d50a71bdSMitsuru IWASAKI { 390d50a71bdSMitsuru IWASAKI int rc = -1; 391d50a71bdSMitsuru IWASAKI int sig; 392d50a71bdSMitsuru IWASAKI 393d50a71bdSMitsuru IWASAKI while (read(fd, &sig, sizeof sig) == sizeof sig) { 394d50a71bdSMitsuru IWASAKI syslog(LOG_INFO, "caught signal: %d", sig); 395d50a71bdSMitsuru IWASAKI switch (sig) { 396d50a71bdSMitsuru IWASAKI case SIGHUP: 397d50a71bdSMitsuru IWASAKI syslog(LOG_NOTICE, "restart by SIG"); 398d50a71bdSMitsuru IWASAKI restart(); 399d50a71bdSMitsuru IWASAKI break; 400d50a71bdSMitsuru IWASAKI case SIGTERM: 401d50a71bdSMitsuru IWASAKI syslog(LOG_NOTICE, "going down on signal %d", sig); 402d50a71bdSMitsuru IWASAKI rc = 1; 403d50a71bdSMitsuru IWASAKI goto out; 404d50a71bdSMitsuru IWASAKI case SIGCHLD: 405d50a71bdSMitsuru IWASAKI wait_child(); 406d50a71bdSMitsuru IWASAKI break; 407d50a71bdSMitsuru IWASAKI default: 408d50a71bdSMitsuru IWASAKI (void) warn("unexpected signal(%d) received.", sig); 409d50a71bdSMitsuru IWASAKI break; 410d50a71bdSMitsuru IWASAKI } 411d50a71bdSMitsuru IWASAKI } 412d50a71bdSMitsuru IWASAKI rc = 0; 413d50a71bdSMitsuru IWASAKI out: 414d50a71bdSMitsuru IWASAKI return rc; 415d50a71bdSMitsuru IWASAKI } 416d50a71bdSMitsuru IWASAKI void 417d50a71bdSMitsuru IWASAKI proc_apmevent(int fd) 418d50a71bdSMitsuru IWASAKI { 419d50a71bdSMitsuru IWASAKI struct apm_event_info apmevent; 420d50a71bdSMitsuru IWASAKI 421d50a71bdSMitsuru IWASAKI while (ioctl(fd, APMIO_NEXTEVENT, &apmevent) == 0) { 422d50a71bdSMitsuru IWASAKI int status; 423d50a71bdSMitsuru IWASAKI syslog(LOG_NOTICE, "apmevent %04x index %d\n", 424d50a71bdSMitsuru IWASAKI apmevent.type, apmevent.index); 425d50a71bdSMitsuru IWASAKI syslog(LOG_INFO, "apm event: %s", events[apmevent.type].name); 426d50a71bdSMitsuru IWASAKI if (fork() == 0) { 427d50a71bdSMitsuru IWASAKI status = exec_event_cmd(&events[apmevent.type]); 428d50a71bdSMitsuru IWASAKI exit(status); 429d50a71bdSMitsuru IWASAKI } 430d50a71bdSMitsuru IWASAKI } 431d50a71bdSMitsuru IWASAKI } 432d50a71bdSMitsuru IWASAKI void 433d50a71bdSMitsuru IWASAKI event_loop(void) 434d50a71bdSMitsuru IWASAKI { 435d50a71bdSMitsuru IWASAKI int fdmax = 0; 436d50a71bdSMitsuru IWASAKI struct sigaction nsa; 437d50a71bdSMitsuru IWASAKI fd_set master_rfds; 438d50a71bdSMitsuru IWASAKI sigset_t sigmask, osigmask; 439d50a71bdSMitsuru IWASAKI 440d50a71bdSMitsuru IWASAKI FD_ZERO(&master_rfds); 441d50a71bdSMitsuru IWASAKI FD_SET(apmctl_fd, &master_rfds); 442d50a71bdSMitsuru IWASAKI fdmax = apmctl_fd > fdmax ? apmctl_fd : fdmax; 443d50a71bdSMitsuru IWASAKI 444d50a71bdSMitsuru IWASAKI FD_SET(signal_fd[0], &master_rfds); 445d50a71bdSMitsuru IWASAKI fdmax = signal_fd[0] > fdmax ? signal_fd[0] : fdmax; 446d50a71bdSMitsuru IWASAKI 447d50a71bdSMitsuru IWASAKI memset(&nsa, 0, sizeof nsa); 448d50a71bdSMitsuru IWASAKI nsa.sa_handler = enque_signal; 449d50a71bdSMitsuru IWASAKI sigfillset(&nsa.sa_mask); 450d50a71bdSMitsuru IWASAKI nsa.sa_flags = SA_RESTART; 451d50a71bdSMitsuru IWASAKI sigaction(SIGHUP, &nsa, NULL); 452d50a71bdSMitsuru IWASAKI sigaction(SIGCHLD, &nsa, NULL); 453d50a71bdSMitsuru IWASAKI sigaction(SIGTERM, &nsa, NULL); 454d50a71bdSMitsuru IWASAKI 455d50a71bdSMitsuru IWASAKI sigemptyset(&sigmask); 456d50a71bdSMitsuru IWASAKI sigaddset(&sigmask, SIGHUP); 457d50a71bdSMitsuru IWASAKI sigaddset(&sigmask, SIGCHLD); 458d50a71bdSMitsuru IWASAKI sigaddset(&sigmask, SIGTERM); 459d50a71bdSMitsuru IWASAKI sigprocmask(SIG_SETMASK, &sigmask, &osigmask); 460d50a71bdSMitsuru IWASAKI 461d50a71bdSMitsuru IWASAKI while (1) { 462d50a71bdSMitsuru IWASAKI fd_set rfds; 463d50a71bdSMitsuru IWASAKI 464d50a71bdSMitsuru IWASAKI memcpy(&rfds, &master_rfds, sizeof rfds); 465d50a71bdSMitsuru IWASAKI sigprocmask(SIG_SETMASK, &osigmask, NULL); 466d50a71bdSMitsuru IWASAKI if (select(fdmax + 1, &rfds, 0, 0, 0) < 0) { 467d50a71bdSMitsuru IWASAKI if (errno != EINTR) 468d50a71bdSMitsuru IWASAKI (void) err(1, "select"); 469d50a71bdSMitsuru IWASAKI } 470d50a71bdSMitsuru IWASAKI sigprocmask(SIG_SETMASK, &sigmask, NULL); 471d50a71bdSMitsuru IWASAKI 472d50a71bdSMitsuru IWASAKI if (FD_ISSET(signal_fd[0], &rfds)) { 473d50a71bdSMitsuru IWASAKI if (proc_signal(signal_fd[0]) < 0) 474d50a71bdSMitsuru IWASAKI goto out; 475d50a71bdSMitsuru IWASAKI } 476d50a71bdSMitsuru IWASAKI if (FD_ISSET(apmctl_fd, &rfds)) 477d50a71bdSMitsuru IWASAKI proc_apmevent(apmctl_fd); 478d50a71bdSMitsuru IWASAKI } 479d50a71bdSMitsuru IWASAKI out: 480d50a71bdSMitsuru IWASAKI return; 481d50a71bdSMitsuru IWASAKI } 482d50a71bdSMitsuru IWASAKI 483d50a71bdSMitsuru IWASAKI void 484d50a71bdSMitsuru IWASAKI main(int ac, char* av[]) 485d50a71bdSMitsuru IWASAKI { 486d50a71bdSMitsuru IWASAKI int ch; 487d50a71bdSMitsuru IWASAKI int daemonize = 1; 488d50a71bdSMitsuru IWASAKI char *prog; 489d50a71bdSMitsuru IWASAKI int logopt = LOG_NDELAY | LOG_PID; 490d50a71bdSMitsuru IWASAKI 491d50a71bdSMitsuru IWASAKI while ((ch = getopt(ac, av, "df:v")) != EOF) { 492d50a71bdSMitsuru IWASAKI switch (ch) { 493d50a71bdSMitsuru IWASAKI case 'd': 494d50a71bdSMitsuru IWASAKI daemonize = 0; 495d50a71bdSMitsuru IWASAKI debug_level++; 496d50a71bdSMitsuru IWASAKI break; 497d50a71bdSMitsuru IWASAKI case 'f': 498d50a71bdSMitsuru IWASAKI apmd_configfile = optarg; 499d50a71bdSMitsuru IWASAKI break; 500d50a71bdSMitsuru IWASAKI case 'v': 501d50a71bdSMitsuru IWASAKI verbose = 1; 502d50a71bdSMitsuru IWASAKI break; 503d50a71bdSMitsuru IWASAKI default: 504d50a71bdSMitsuru IWASAKI (void) err(1, "unknown option `%c'", ch); 505d50a71bdSMitsuru IWASAKI } 506d50a71bdSMitsuru IWASAKI } 507d50a71bdSMitsuru IWASAKI 508d50a71bdSMitsuru IWASAKI if (daemonize) 509d50a71bdSMitsuru IWASAKI daemon(0, 0); 510d50a71bdSMitsuru IWASAKI 511d50a71bdSMitsuru IWASAKI #ifdef NICE_INCR 512d50a71bdSMitsuru IWASAKI (void) nice(NICE_INCR); 513d50a71bdSMitsuru IWASAKI #endif 514d50a71bdSMitsuru IWASAKI 515d50a71bdSMitsuru IWASAKI if (!daemonize) 516d50a71bdSMitsuru IWASAKI logopt |= LOG_PERROR; 517d50a71bdSMitsuru IWASAKI 518d50a71bdSMitsuru IWASAKI prog = strrchr(av[0], '/'); 519d50a71bdSMitsuru IWASAKI openlog(prog ? prog+1 : av[0], logopt, LOG_DAEMON); 520d50a71bdSMitsuru IWASAKI 521d50a71bdSMitsuru IWASAKI syslog(LOG_NOTICE, "start"); 522d50a71bdSMitsuru IWASAKI 523d50a71bdSMitsuru IWASAKI if (pipe(signal_fd) < 0) 524d50a71bdSMitsuru IWASAKI (void) err(1, "pipe"); 525d50a71bdSMitsuru IWASAKI if (fcntl(signal_fd[0], F_SETFL, O_NONBLOCK) < 0) 526d50a71bdSMitsuru IWASAKI (void) err(1, "fcntl"); 527d50a71bdSMitsuru IWASAKI 528d50a71bdSMitsuru IWASAKI if ((apmctl_fd = open(APM_CTL_DEVICEFILE, O_RDWR)) == -1) { 529d50a71bdSMitsuru IWASAKI (void) err(1, "cannot open device file `%s'", APM_CTL_DEVICEFILE); 530d50a71bdSMitsuru IWASAKI } 531d50a71bdSMitsuru IWASAKI 532d50a71bdSMitsuru IWASAKI restart(); 533d50a71bdSMitsuru IWASAKI write_pid(); 534d50a71bdSMitsuru IWASAKI event_loop(); 535d50a71bdSMitsuru IWASAKI exit(EXIT_SUCCESS); 536d50a71bdSMitsuru IWASAKI } 537d50a71bdSMitsuru IWASAKI 538