aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-11-29 09:05:50 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-11-29 09:05:50 +0000
commitd16950ded91446a23a6ceef35fb3e100400301d9 (patch)
tree038faff9ea801e5d7f022b75256fc52e66186b75
parentf7d87f9b183aa28777ce09d40222fbe221d15c91 (diff)
downloadbusybox-w32-d16950ded91446a23a6ceef35fb3e100400301d9.tar.gz
busybox-w32-d16950ded91446a23a6ceef35fb3e100400301d9.tar.bz2
busybox-w32-d16950ded91446a23a6ceef35fb3e100400301d9.zip
acpid: new applet by Vladimir. +737 bytes
-rw-r--r--docs/busybox.net/news.html4
-rw-r--r--include/applets.h1
-rw-r--r--include/usage.h17
-rw-r--r--util-linux/Config.in22
-rw-r--r--util-linux/Kbuild1
-rw-r--r--util-linux/acpid.c167
6 files changed, 210 insertions, 2 deletions
diff --git a/docs/busybox.net/news.html b/docs/busybox.net/news.html
index 3fccaae12..5c005fb0e 100644
--- a/docs/busybox.net/news.html
+++ b/docs/busybox.net/news.html
@@ -32,8 +32,8 @@
32 <a href="http://busybox.net/downloads/fixes-1.12.3/">patches</a>, 32 <a href="http://busybox.net/downloads/fixes-1.12.3/">patches</a>,
33 <a href="http://busybox.net/fix.html">how to add a patch</a>)</p> 33 <a href="http://busybox.net/fix.html">how to add a patch</a>)</p>
34 34
35 <p>Bug-fix releases. 1.13.1 has fixes for ash, option parsing, id, init, 35 <p>Bug fix releases. 1.13.1 has fixes for ash, option parsing, id, init,
36 inotify, klogd, line editing and modprobe. 1.12.3 has fixes 36 inotifyd, klogd, line editing and modprobe. 1.12.3 has fixes
37 for option parsing and line editing. 37 for option parsing and line editing.
38 </p> 38 </p>
39 </li> 39 </li>
diff --git a/include/applets.h b/include/applets.h
index fb904bb9f..ad3925577 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -69,6 +69,7 @@ s - suid type:
69 69
70USE_TEST(APPLET_NOFORK([, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER, test)) 70USE_TEST(APPLET_NOFORK([, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER, test))
71USE_TEST(APPLET_NOFORK([[, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER, test)) 71USE_TEST(APPLET_NOFORK([[, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER, test))
72USE_ACPID(APPLET(acpid, _BB_DIR_SBIN, _BB_SUID_NEVER))
72USE_ADDGROUP(APPLET(addgroup, _BB_DIR_BIN, _BB_SUID_NEVER)) 73USE_ADDGROUP(APPLET(addgroup, _BB_DIR_BIN, _BB_SUID_NEVER))
73USE_ADDUSER(APPLET(adduser, _BB_DIR_BIN, _BB_SUID_NEVER)) 74USE_ADDUSER(APPLET(adduser, _BB_DIR_BIN, _BB_SUID_NEVER))
74USE_ADJTIMEX(APPLET(adjtimex, _BB_DIR_SBIN, _BB_SUID_NEVER)) 75USE_ADJTIMEX(APPLET(adjtimex, _BB_DIR_SBIN, _BB_SUID_NEVER))
diff --git a/include/usage.h b/include/usage.h
index d35f8ae71..502fea7a0 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -16,6 +16,23 @@
16 16
17#define NOUSAGE_STR "\b" 17#define NOUSAGE_STR "\b"
18 18
19#define acpid_trivial_usage \
20 "[-d] [-c CONFDIR] [-l LOGFILE] [-e PROC_EVENT_FILE] [EVDEV_EVENT_FILE...]"
21
22#define acpid_full_usage "\n\n" \
23 "Listen to ACPI events and spawn specific helpers on event arrival\n" \
24 "\nOptions:" \
25 "\n -d Do not daemonize and log to stderr" \
26 "\n -c DIR Config directory [/etc/acpi]" \
27 "\n -e FILE /proc event file [/proc/acpi/event]" \
28 "\n -l FILE Log file [/var/log/acpid]" \
29 USE_FEATURE_ACPID_COMPAT( \
30 "\n\nAccept and ignore compatibility options -g -m -s -S -v" \
31 )
32
33#define acpid_example_usage \
34 "# acpid -l /var/log/my-acpi-log\n" \
35 "# acpid -d /dev/input/event*\n"
19 36
20#define addgroup_trivial_usage \ 37#define addgroup_trivial_usage \
21 "[-g GID] " USE_FEATURE_ADDUSER_TO_GROUP("[user_name] ") "group_name" 38 "[-g GID] " USE_FEATURE_ADDUSER_TO_GROUP("[user_name] ") "group_name"
diff --git a/util-linux/Config.in b/util-linux/Config.in
index 976507b68..3bba2e26d 100644
--- a/util-linux/Config.in
+++ b/util-linux/Config.in
@@ -5,6 +5,28 @@
5 5
6menu "Linux System Utilities" 6menu "Linux System Utilities"
7 7
8config ACPID
9 bool "acpid"
10 default n
11 help
12 acpid listens to ACPI events coming either in textual form from
13 /proc/acpi/event (though it is marked deprecated it is still widely
14 used and _is_ a standard) or in binary form from specified evdevs
15 (just use /dev/input/event*).
16
17 It parses the event to retrieve ACTION and a possible PARAMETER.
18 It then spawns /etc/acpi/<ACTION>[/<PARAMETER>] either via run-parts
19 (if the resulting path is a directory) or directly as an executable.
20
21 N.B. acpid relies on run-parts so have the latter installed.
22
23config FEATURE_ACPID_COMPAT
24 bool "Accept and ignore redundant options"
25 default n
26 depends on ACPID
27 help
28 Accept and ignore compatibility options -g -m -s -S -v.
29
8config BLKID 30config BLKID
9 bool "blkid" 31 bool "blkid"
10 default n 32 default n
diff --git a/util-linux/Kbuild b/util-linux/Kbuild
index 2d0fc4928..842afb756 100644
--- a/util-linux/Kbuild
+++ b/util-linux/Kbuild
@@ -5,6 +5,7 @@
5# Licensed under the GPL v2, see the file LICENSE in this tarball. 5# Licensed under the GPL v2, see the file LICENSE in this tarball.
6 6
7lib-y:= 7lib-y:=
8lib-$(CONFIG_ACPID) += acpid.o
8lib-$(CONFIG_BLKID) += blkid.o 9lib-$(CONFIG_BLKID) += blkid.o
9lib-$(CONFIG_DMESG) += dmesg.o 10lib-$(CONFIG_DMESG) += dmesg.o
10lib-$(CONFIG_FBSET) += fbset.o 11lib-$(CONFIG_FBSET) += fbset.o
diff --git a/util-linux/acpid.c b/util-linux/acpid.c
new file mode 100644
index 000000000..ef4e54d5d
--- /dev/null
+++ b/util-linux/acpid.c
@@ -0,0 +1,167 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * simple ACPI events listener
4 *
5 * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
6 *
7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 */
9#include "libbb.h"
10
11#include <linux/input.h>
12#ifndef SW_RFKILL_ALL
13# define SW_RFKILL_ALL 3
14#endif
15
16/*
17 * acpid listens to ACPI events coming either in textual form
18 * from /proc/acpi/event (though it is marked deprecated,
19 * it is still widely used and _is_ a standard) or in binary form
20 * from specified evdevs (just use /dev/input/event*).
21 * It parses the event to retrieve ACTION and a possible PARAMETER.
22 * It then spawns /etc/acpi/<ACTION>[/<PARAMETER>] either via run-parts
23 * (if the resulting path is a directory) or directly.
24 * If the resulting path does not exist it logs it via perror
25 * and continues listening.
26 */
27
28static void process_event(const char *event)
29{
30 struct stat st;
31 char *handler = xasprintf("./%s", event);
32 const char *args[] = { "run-parts", handler, NULL };
33
34 // debug info
35 if (option_mask32 & 8) { // -d
36 bb_error_msg("%s", event);
37 }
38
39 // spawn handler
40 // N.B. run-parts would require scripts to have #!/bin/sh
41 // handler is directory? -> use run-parts
42 // handler is file? -> run it directly
43 if (0 == stat(event, &st))
44 spawn((char **)args + (0==(st.st_mode & S_IFDIR)));
45 else
46 bb_simple_perror_msg(event);
47 free(handler);
48}
49
50/*
51 * acpid [-c conf_dir] [-l log_file] [-e proc_event_file] [evdev_event_file...]
52*/
53
54int acpid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
55int acpid_main(int argc, char **argv)
56{
57 struct pollfd *pfd;
58 int i, nfd;
59 const char *opt_conf = "/etc/acpi";
60 const char *opt_input = "/proc/acpi/event";
61 const char *opt_logfile = "/var/log/acpid.log";
62
63 getopt32(argv, "c:e:l:d"
64 USE_FEATURE_ACPID_COMPAT("g:m:s:S:v"),
65 &opt_conf, &opt_input, &opt_logfile
66 USE_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL, NULL)
67 );
68
69 // daemonize unless -d given
70 if (!(option_mask32 & 8)) { // ! -d
71 bb_daemonize_or_rexec(0, argv);
72 close(2);
73 xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC);
74 }
75
76 argv += optind;
77
78 // goto configuration directory
79 xchdir(opt_conf);
80
81// // setup signals
82// bb_signals(BB_FATAL_SIGS, record_signo);
83
84 // no explicit evdev files given? -> use proc event interface
85 if (!*argv) {
86 // proc_event file is just a "config" :)
87 char *token[4];
88 parser_t *parser = config_open(opt_input);
89
90 // dispatch events
91 while (config_read(parser, token, 4, 4, "\0 ", PARSE_NORMAL)) {
92 char *event = xasprintf("%s/%s", token[1], token[2]);
93 process_event(event);
94 free(event);
95 }
96
97 if (ENABLE_FEATURE_CLEAN_UP)
98 config_close(parser);
99 return EXIT_SUCCESS;
100 }
101
102 // evdev files given, use evdev interface
103
104 // open event devices
105 pfd = xzalloc(sizeof(*pfd) * (argc - optind));
106 nfd = 0;
107 while (*argv) {
108 pfd[nfd].fd = open_or_warn(*argv++, O_RDONLY | O_NONBLOCK);
109 if (pfd[nfd].fd >= 0)
110 pfd[nfd++].events = POLLIN;
111 }
112
113 // dispatch events
114 while (/* !bb_got_signal && */ poll(pfd, nfd, -1) > 0) {
115 for (i = 0; i < nfd; i++) {
116 const char *event;
117 struct input_event ev;
118
119 if (!(pfd[i].revents & POLLIN))
120 continue;
121
122 if (sizeof(ev) != full_read(pfd[i].fd, &ev, sizeof(ev)))
123 continue;
124//bb_info_msg("%d: %d %d %4d", i, ev.type, ev.code, ev.value);
125
126 // filter out unneeded events
127 if (ev.value != 1)
128 continue;
129
130 event = NULL;
131
132 // N.B. we will conform to /proc/acpi/event
133 // naming convention when assigning event names
134
135 // TODO: do we want other events?
136
137 // power and sleep buttons delivered as keys pressed
138 if (EV_KEY == ev.type) {
139 if (KEY_POWER == ev.code)
140 event = "PWRF/00000080";
141 else if (KEY_SLEEP == ev.code)
142 event = "SLPB/00000080";
143 }
144 // switches
145 else if (EV_SW == ev.type) {
146 if (SW_LID == ev.code)
147 event = "LID/00000080";
148 else if (SW_RFKILL_ALL == ev.code)
149 event = "RFKILL";
150 }
151 // filter out unneeded events
152 if (!event)
153 continue;
154
155 // spawn event handler
156 process_event(event);
157 }
158 }
159
160 if (ENABLE_FEATURE_CLEAN_UP) {
161 for (i = 0; i < nfd; i++)
162 close(pfd[i].fd);
163 free(pfd);
164 }
165
166 return EXIT_SUCCESS;
167}