diff options
Diffstat (limited to 'util-linux/acpid.c')
-rw-r--r-- | util-linux/acpid.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/util-linux/acpid.c b/util-linux/acpid.c index 6e7321b02..1b22f3a01 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c | |||
@@ -8,13 +8,13 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | //usage:#define acpid_trivial_usage | 10 | //usage:#define acpid_trivial_usage |
11 | //usage: "[-d] [-c CONFDIR] [-l LOGFILE] [-a ACTIONFILE] [-M MAPFILE] [-e PROC_EVENT_FILE] [-p PIDFILE]" | 11 | //usage: "[-df] [-c CONFDIR] [-l LOGFILE] [-a ACTIONFILE] [-M MAPFILE] [-e PROC_EVENT_FILE] [-p PIDFILE]" |
12 | //usage:#define acpid_full_usage "\n\n" | 12 | //usage:#define acpid_full_usage "\n\n" |
13 | //usage: "Listen to ACPI events and spawn specific helpers on event arrival\n" | 13 | //usage: "Listen to ACPI events and spawn specific helpers on event arrival\n" |
14 | //usage: "\n -d Log to stderr, not log file (implies -f)" | ||
15 | //usage: "\n -f Run in foreground" | ||
14 | //usage: "\n -c DIR Config directory [/etc/acpi]" | 16 | //usage: "\n -c DIR Config directory [/etc/acpi]" |
15 | //usage: "\n -d Don't daemonize, (implies -f)" | ||
16 | //usage: "\n -e FILE /proc event file [/proc/acpi/event]" | 17 | //usage: "\n -e FILE /proc event file [/proc/acpi/event]" |
17 | //usage: "\n -f Run in foreground" | ||
18 | //usage: "\n -l FILE Log file [/var/log/acpid.log]" | 18 | //usage: "\n -l FILE Log file [/var/log/acpid.log]" |
19 | //usage: "\n -p FILE Pid file [/var/run/acpid.pid]" | 19 | //usage: "\n -p FILE Pid file [/var/run/acpid.pid]" |
20 | //usage: "\n -a FILE Action file [/etc/acpid.conf]" | 20 | //usage: "\n -a FILE Action file [/etc/acpid.conf]" |
@@ -225,7 +225,6 @@ static void parse_map_file(const char *filename) | |||
225 | int acpid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 225 | int acpid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
226 | int acpid_main(int argc UNUSED_PARAM, char **argv) | 226 | int acpid_main(int argc UNUSED_PARAM, char **argv) |
227 | { | 227 | { |
228 | struct input_event ev; | ||
229 | int nfd; | 228 | int nfd; |
230 | int opts; | 229 | int opts; |
231 | struct pollfd *pfd; | 230 | struct pollfd *pfd; |
@@ -248,23 +247,33 @@ int acpid_main(int argc UNUSED_PARAM, char **argv) | |||
248 | ); | 247 | ); |
249 | 248 | ||
250 | if (!(opts & OPT_f)) { | 249 | if (!(opts & OPT_f)) { |
250 | /* No -f "Foreground", we go to background */ | ||
251 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); | 251 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); |
252 | } | 252 | } |
253 | 253 | ||
254 | if (!(opts & OPT_d)) { | 254 | if (!(opts & OPT_d)) { |
255 | /* No -d "Debug", we log to log file. | ||
256 | * This includes any output from children. | ||
257 | */ | ||
258 | xmove_fd(xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); | ||
259 | xdup2(STDOUT_FILENO, STDERR_FILENO); | ||
260 | /* Also, acpid's messages (but not children) will go to syslog too */ | ||
255 | openlog(applet_name, LOG_PID, LOG_DAEMON); | 261 | openlog(applet_name, LOG_PID, LOG_DAEMON); |
256 | logmode = LOGMODE_SYSLOG | LOGMODE_STDIO; | 262 | logmode = LOGMODE_SYSLOG | LOGMODE_STDIO; |
257 | } else { | ||
258 | xmove_fd(xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); | ||
259 | } | 263 | } |
264 | /* else: -d "Debug", log is not redirected */ | ||
260 | 265 | ||
261 | parse_conf_file(opt_action); | 266 | parse_conf_file(opt_action); |
262 | parse_map_file(opt_map); | 267 | parse_map_file(opt_map); |
263 | 268 | ||
264 | xchdir(opt_dir); | 269 | xchdir(opt_dir); |
265 | 270 | ||
271 | /* We spawn children but don't wait for them. Prevent zombies: */ | ||
266 | bb_signals((1 << SIGCHLD), SIG_IGN); | 272 | bb_signals((1 << SIGCHLD), SIG_IGN); |
267 | bb_signals(BB_FATAL_SIGS, record_signo); | 273 | // If you enable this, (1) explain why, (2) |
274 | // make sure while(poll) loop below is still interruptible | ||
275 | // by SIGTERM et al: | ||
276 | //bb_signals(BB_FATAL_SIGS, record_signo); | ||
268 | 277 | ||
269 | pfd = NULL; | 278 | pfd = NULL; |
270 | nfd = 0; | 279 | nfd = 0; |
@@ -272,13 +281,14 @@ int acpid_main(int argc UNUSED_PARAM, char **argv) | |||
272 | int fd; | 281 | int fd; |
273 | char *dev_event; | 282 | char *dev_event; |
274 | 283 | ||
275 | dev_event = xasprintf((option_mask32 & OPT_e) ? "%s" : "%s%u", opt_input, nfd); | 284 | dev_event = xasprintf((opts & OPT_e) ? "%s" : "%s%u", opt_input, nfd); |
276 | fd = open(dev_event, O_RDONLY | O_NONBLOCK); | 285 | fd = open(dev_event, O_RDONLY | O_NONBLOCK); |
277 | if (fd < 0) { | 286 | if (fd < 0) { |
278 | if (nfd == 0) | 287 | if (nfd == 0) |
279 | bb_simple_perror_msg_and_die(dev_event); | 288 | bb_simple_perror_msg_and_die(dev_event); |
280 | break; | 289 | break; |
281 | } | 290 | } |
291 | free(dev_event); | ||
282 | pfd = xrealloc_vector(pfd, 1, nfd); | 292 | pfd = xrealloc_vector(pfd, 1, nfd); |
283 | pfd[nfd].fd = fd; | 293 | pfd[nfd].fd = fd; |
284 | pfd[nfd].events = POLLIN; | 294 | pfd[nfd].events = POLLIN; |
@@ -287,16 +297,26 @@ int acpid_main(int argc UNUSED_PARAM, char **argv) | |||
287 | 297 | ||
288 | write_pidfile(opt_pidfile); | 298 | write_pidfile(opt_pidfile); |
289 | 299 | ||
290 | while (poll(pfd, nfd, -1) > 0) { | 300 | while (safe_poll(pfd, nfd, -1) > 0) { |
291 | int i; | 301 | int i; |
292 | for (i = 0; i < nfd; i++) { | 302 | for (i = 0; i < nfd; i++) { |
293 | const char *event = NULL; | 303 | const char *event; |
294 | 304 | ||
295 | memset(&ev, 0, sizeof(ev)); | 305 | if (!(pfd[i].revents & POLLIN)) { |
296 | 306 | if (pfd[i].revents == 0) | |
297 | if (!(pfd[i].revents & POLLIN)) | 307 | continue; /* this fd has nothing */ |
298 | continue; | 308 | |
309 | /* Likely POLLERR, POLLHUP, POLLNVAL. | ||
310 | * Do not listen on this fd anymore. | ||
311 | */ | ||
312 | close(pfd[i].fd); | ||
313 | nfd--; | ||
314 | for (; i < nfd; i++) | ||
315 | pfd[i].fd = pfd[i + 1].fd; | ||
316 | break; /* do poll() again */ | ||
317 | } | ||
299 | 318 | ||
319 | event = NULL; | ||
300 | if (option_mask32 & OPT_e) { | 320 | if (option_mask32 & OPT_e) { |
301 | char *buf; | 321 | char *buf; |
302 | int len; | 322 | int len; |
@@ -307,7 +327,10 @@ int acpid_main(int argc UNUSED_PARAM, char **argv) | |||
307 | if (len >= 0) | 327 | if (len >= 0) |
308 | buf[len] = '\0'; | 328 | buf[len] = '\0'; |
309 | event = find_action(NULL, buf); | 329 | event = find_action(NULL, buf); |
330 | free(buf); | ||
310 | } else { | 331 | } else { |
332 | struct input_event ev; | ||
333 | |||
311 | if (sizeof(ev) != full_read(pfd[i].fd, &ev, sizeof(ev))) | 334 | if (sizeof(ev) != full_read(pfd[i].fd, &ev, sizeof(ev))) |
312 | continue; | 335 | continue; |
313 | 336 | ||
@@ -318,17 +341,14 @@ int acpid_main(int argc UNUSED_PARAM, char **argv) | |||
318 | } | 341 | } |
319 | if (!event) | 342 | if (!event) |
320 | continue; | 343 | continue; |
321 | // spawn event handler | 344 | /* spawn event handler */ |
322 | process_event(event); | 345 | process_event(event); |
323 | } | 346 | } |
324 | } | 347 | } |
325 | 348 | ||
326 | if (ENABLE_FEATURE_CLEAN_UP) { | 349 | if (ENABLE_FEATURE_CLEAN_UP) { |
327 | while (nfd--) { | 350 | while (nfd--) |
328 | if (pfd[nfd].fd) { | 351 | close(pfd[nfd].fd); |
329 | close(pfd[nfd].fd); | ||
330 | } | ||
331 | } | ||
332 | free(pfd); | 352 | free(pfd); |
333 | } | 353 | } |
334 | remove_pidfile(opt_pidfile); | 354 | remove_pidfile(opt_pidfile); |