aboutsummaryrefslogtreecommitdiff
path: root/util-linux/acpid.c
diff options
context:
space:
mode:
Diffstat (limited to 'util-linux/acpid.c')
-rw-r--r--util-linux/acpid.c62
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)
225int acpid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 225int acpid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
226int acpid_main(int argc UNUSED_PARAM, char **argv) 226int 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);