diff options
author | Souf Oued <souf_oued@yahoo.fr> | 2010-09-26 12:40:05 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-09-26 12:40:05 +0200 |
commit | ccb7a4390004e3c32fbf93e93474fc124bcd17be (patch) | |
tree | f33697c6ecb8ddf2e265f123391e81b2bb6c5547 /util-linux | |
parent | 7d3a48a003cd645edfae2b404493688022b13193 (diff) | |
download | busybox-w32-ccb7a4390004e3c32fbf93e93474fc124bcd17be.tar.gz busybox-w32-ccb7a4390004e3c32fbf93e93474fc124bcd17be.tar.bz2 busybox-w32-ccb7a4390004e3c32fbf93e93474fc124bcd17be.zip |
acpid: add config file and map file
function old new delta
acpid_main 434 1137 +703
find_action - 204 +204
f_evt_tab - 48 +48
packed_usage 27724 27755 +31
f_act_tab - 16 +16
process_event 126 - -126
------------------------------------------------------------------------------
(add/remove: 3/1 grow/shrink: 2/0 up/down: 1002/-126) Total: 876 bytes
Signed-off-by: Souf Oued <souf_oued@yahoo.fr>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'util-linux')
-rw-r--r-- | util-linux/acpid.c | 306 |
1 files changed, 208 insertions, 98 deletions
diff --git a/util-linux/acpid.c b/util-linux/acpid.c index c3b3c8b0b..5a3bd5a6a 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c | |||
@@ -7,27 +7,58 @@ | |||
7 | * Licensed under GPLv2, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | #include <syslog.h> | |
11 | #include <linux/input.h> | 11 | #include <linux/input.h> |
12 | #ifndef EV_SW | ||
13 | # define EV_SW 0x05 | ||
14 | #endif | ||
15 | #ifndef EV_KEY | ||
16 | # define EV_KEY 0x01 | ||
17 | #endif | ||
18 | #ifndef SW_LID | ||
19 | # define SW_LID 0x00 | ||
20 | #endif | ||
21 | #ifndef SW_RFKILL_ALL | ||
22 | # define SW_RFKILL_ALL 0x03 | ||
23 | #endif | ||
24 | #ifndef KEY_POWER | ||
25 | # define KEY_POWER 116 /* SC System Power Down */ | ||
26 | #endif | ||
27 | #ifndef KEY_SLEEP | ||
28 | # define KEY_SLEEP 142 /* SC System Sleep */ | ||
29 | #endif | ||
30 | 12 | ||
13 | enum { | ||
14 | OPT_c = (1 << 0), | ||
15 | OPT_d = (1 << 1), | ||
16 | OPT_e = (1 << 2), | ||
17 | OPT_f = (1 << 3), | ||
18 | OPT_l = (1 << 4), | ||
19 | OPT_p = (1 << 5) * ENABLE_FEATURE_PIDFILE, | ||
20 | OPT_a = (1 << 6), | ||
21 | OPT_M = (1 << 7), | ||
22 | }; | ||
23 | |||
24 | struct acpi_event { | ||
25 | const char *s_type; | ||
26 | uint16_t n_type; | ||
27 | const char *s_code; | ||
28 | uint16_t n_code; | ||
29 | uint32_t value; | ||
30 | const char *desc; | ||
31 | }; | ||
32 | |||
33 | static const struct acpi_event f_evt_tab[] = { | ||
34 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRF 00000080" }, | ||
35 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRB 00000080" }, | ||
36 | }; | ||
37 | |||
38 | struct acpi_action { | ||
39 | const char *key; | ||
40 | const char *action; | ||
41 | }; | ||
42 | |||
43 | static const struct acpi_action f_act_tab[] = { | ||
44 | { "PWRF", "PWRF/00000080" }, | ||
45 | { "LID0", "LID/00000080" }, | ||
46 | }; | ||
47 | |||
48 | struct globals { | ||
49 | struct acpi_action *act_tab; | ||
50 | int n_act; | ||
51 | struct acpi_event *evt_tab; | ||
52 | int n_evt; | ||
53 | } FIX_ALIASING; | ||
54 | #define G (*ptr_to_globals) | ||
55 | #define act_tab (G.act_tab) | ||
56 | #define n_act (G.n_act ) | ||
57 | #define evt_tab (G.evt_tab) | ||
58 | #define n_evt (G.n_evt ) | ||
59 | #define INIT_G() do { \ | ||
60 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | ||
61 | } while (0) | ||
31 | 62 | ||
32 | /* | 63 | /* |
33 | * acpid listens to ACPI events coming either in textual form | 64 | * acpid listens to ACPI events coming either in textual form |
@@ -48,7 +79,7 @@ static void process_event(const char *event) | |||
48 | const char *args[] = { "run-parts", handler, NULL }; | 79 | const char *args[] = { "run-parts", handler, NULL }; |
49 | 80 | ||
50 | // debug info | 81 | // debug info |
51 | if (option_mask32 & 8) { // -d | 82 | if (option_mask32 & OPT_d) { |
52 | bb_error_msg("%s", event); | 83 | bb_error_msg("%s", event); |
53 | } | 84 | } |
54 | 85 | ||
@@ -60,125 +91,204 @@ static void process_event(const char *event) | |||
60 | spawn((char **)args + (0==(st.st_mode & S_IFDIR))); | 91 | spawn((char **)args + (0==(st.st_mode & S_IFDIR))); |
61 | else | 92 | else |
62 | bb_simple_perror_msg(event); | 93 | bb_simple_perror_msg(event); |
94 | |||
63 | free(handler); | 95 | free(handler); |
64 | } | 96 | } |
65 | 97 | ||
98 | static const char *find_action(struct input_event *ev, const char *buf) | ||
99 | { | ||
100 | const char *action = NULL; | ||
101 | int i; | ||
102 | |||
103 | // map event | ||
104 | for (i = 0; i < n_evt; i++) { | ||
105 | if (ev) { | ||
106 | if (ev->type == evt_tab[i].n_type && ev->code == evt_tab[i].n_code && ev->value == evt_tab[i].value) { | ||
107 | action = evt_tab[i].desc; | ||
108 | break; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (buf) { | ||
113 | if (strncmp(buf, evt_tab[i].desc, strlen(buf)) == 0) { | ||
114 | action = evt_tab[i].desc; | ||
115 | break; | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | |||
120 | // get action | ||
121 | if (action) { | ||
122 | for (i = 0; i < n_act; i++) { | ||
123 | if (strstr(action, act_tab[i].key)) { | ||
124 | action = act_tab[i].action; | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | |||
130 | return action; | ||
131 | } | ||
132 | |||
133 | static void parse_conf_file(const char *filename) | ||
134 | { | ||
135 | parser_t *parser; | ||
136 | char *tokens[2]; | ||
137 | |||
138 | parser = config_open2(filename, fopen_for_read); | ||
139 | |||
140 | if (parser) { | ||
141 | while (config_read(parser, tokens, 2, 2, "# \t", PARSE_NORMAL)) { | ||
142 | act_tab = xrealloc_vector(act_tab, 1, n_act); | ||
143 | act_tab[n_act].key = xstrdup(tokens[0]); | ||
144 | act_tab[n_act].action = xstrdup(tokens[1]); | ||
145 | n_act++; | ||
146 | } | ||
147 | config_close(parser); | ||
148 | } else { | ||
149 | act_tab = (void*)f_act_tab; | ||
150 | n_act = ARRAY_SIZE(f_act_tab); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | static void parse_map_file(const char *filename) | ||
155 | { | ||
156 | parser_t *parser; | ||
157 | char *tokens[6]; | ||
158 | |||
159 | parser = config_open2(filename, fopen_for_read); | ||
160 | |||
161 | if (parser) { | ||
162 | while (config_read(parser, tokens, 6, 6, "# \t", PARSE_NORMAL)) { | ||
163 | evt_tab = xrealloc_vector(evt_tab, 1, n_evt); | ||
164 | evt_tab[n_evt].s_type = xstrdup(tokens[0]); | ||
165 | evt_tab[n_evt].n_type = xstrtou(tokens[1], 16); | ||
166 | evt_tab[n_evt].s_code = xstrdup(tokens[2]); | ||
167 | evt_tab[n_evt].n_code = xatou16(tokens[3]); | ||
168 | evt_tab[n_evt].value = xatoi_positive(tokens[4]); | ||
169 | evt_tab[n_evt].desc = xstrdup(tokens[5]); | ||
170 | n_evt++; | ||
171 | } | ||
172 | config_close(parser); | ||
173 | } else { | ||
174 | evt_tab = (void*)f_evt_tab; | ||
175 | n_evt = ARRAY_SIZE(f_evt_tab); | ||
176 | } | ||
177 | } | ||
178 | |||
66 | /* | 179 | /* |
67 | * acpid [-c conf_dir] [-l log_file] [-e proc_event_file] [evdev_event_file...] | 180 | * acpid [-c conf_dir] [-r conf_file ] [-a map_file ] [-l log_file] [-e proc_event_file] |
68 | */ | 181 | */ |
69 | 182 | ||
70 | int acpid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 183 | int acpid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
71 | int acpid_main(int argc, char **argv) | 184 | int acpid_main(int argc UNUSED_PARAM, char **argv) |
72 | { | 185 | { |
186 | struct input_event ev; | ||
187 | int nfd; | ||
188 | int opts; | ||
73 | struct pollfd *pfd; | 189 | struct pollfd *pfd; |
74 | int i, nfd; | 190 | const char *opt_dir = "/etc/acpi"; |
75 | const char *opt_conf = "/etc/acpi"; | 191 | const char *opt_input = "/dev/input/event"; |
76 | const char *opt_input = "/proc/acpi/event"; | ||
77 | const char *opt_logfile = "/var/log/acpid.log"; | 192 | const char *opt_logfile = "/var/log/acpid.log"; |
193 | const char *opt_action = "/etc/acpid.conf"; | ||
194 | const char *opt_map = "/etc/acpi.map"; | ||
195 | #if ENABLE_FEATURE_PIDFILE | ||
196 | const char *opt_pidfile = "/var/run/acpid.pid"; | ||
197 | #endif | ||
198 | |||
199 | INIT_G(); | ||
78 | 200 | ||
79 | getopt32(argv, "c:e:l:d" | 201 | opt_complementary = "df:e--e"; |
80 | IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), | 202 | opts = getopt32(argv, "c:de:fl:p:a:M:" IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), |
81 | &opt_conf, &opt_input, &opt_logfile | 203 | &opt_dir, &opt_input, &opt_logfile, &opt_pidfile, &opt_action, &opt_map |
82 | IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL, NULL) | 204 | IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL) |
83 | ); | 205 | ); |
84 | 206 | ||
85 | // daemonize unless -d given | 207 | if (!(opts & OPT_f)) { |
86 | if (!(option_mask32 & 8)) { // ! -d | 208 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); |
87 | bb_daemonize_or_rexec(0, argv); | ||
88 | close(2); | ||
89 | xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC); | ||
90 | } | 209 | } |
91 | 210 | ||
92 | argv += optind; | 211 | if (!(opts & OPT_d)) { |
93 | argc -= optind; | 212 | openlog(applet_name, LOG_PID, LOG_DAEMON); |
213 | logmode = LOGMODE_SYSLOG | LOGMODE_STDIO; | ||
214 | } else { | ||
215 | xmove_fd(xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); | ||
216 | } | ||
94 | 217 | ||
95 | // goto configuration directory | 218 | parse_conf_file(opt_action); |
96 | xchdir(opt_conf); | 219 | parse_map_file(opt_map); |
97 | 220 | ||
98 | // prevent zombies | 221 | xchdir(opt_dir); |
99 | signal(SIGCHLD, SIG_IGN); | ||
100 | 222 | ||
101 | // no explicit evdev files given? -> use proc event interface | 223 | bb_signals((1 << SIGCHLD), SIG_IGN); |
102 | if (!*argv) { | 224 | bb_signals(BB_FATAL_SIGS, record_signo); |
103 | // proc_event file is just a "config" :) | ||
104 | char *token[4]; | ||
105 | parser_t *parser = config_open(opt_input); | ||
106 | 225 | ||
107 | // dispatch events | 226 | pfd = NULL; |
108 | while (config_read(parser, token, 4, 4, "\0 ", PARSE_NORMAL)) { | 227 | nfd = 0; |
109 | char *event = xasprintf("%s/%s", token[1], token[2]); | 228 | while (1) { |
110 | process_event(event); | 229 | int fd; |
111 | free(event); | 230 | char *dev_event; |
112 | } | ||
113 | 231 | ||
114 | if (ENABLE_FEATURE_CLEAN_UP) | 232 | dev_event = xasprintf((option_mask32 & OPT_e) ? "%s" : "%s%u", opt_input, nfd); |
115 | config_close(parser); | 233 | fd = open(dev_event, O_RDONLY | O_NONBLOCK); |
116 | return EXIT_SUCCESS; | 234 | if (fd < 0) { |
235 | if (nfd == 0) | ||
236 | bb_simple_perror_msg_and_die(dev_event); | ||
237 | break; | ||
238 | } | ||
239 | pfd = xrealloc_vector(pfd, 1, nfd); | ||
240 | pfd[nfd].fd = fd; | ||
241 | pfd[nfd].events = POLLIN; | ||
242 | nfd++; | ||
117 | } | 243 | } |
118 | 244 | ||
119 | // evdev files given, use evdev interface | 245 | write_pidfile(opt_pidfile); |
120 | |||
121 | // open event devices | ||
122 | pfd = xzalloc(sizeof(*pfd) * argc); | ||
123 | nfd = 0; | ||
124 | while (*argv) { | ||
125 | pfd[nfd].fd = open_or_warn(*argv++, O_RDONLY | O_NONBLOCK); | ||
126 | if (pfd[nfd].fd >= 0) | ||
127 | pfd[nfd++].events = POLLIN; | ||
128 | } | ||
129 | 246 | ||
130 | // dispatch events | 247 | while (poll(pfd, nfd, -1) > 0) { |
131 | while (/* !bb_got_signal && */ poll(pfd, nfd, -1) > 0) { | 248 | int i; |
132 | for (i = 0; i < nfd; i++) { | 249 | for (i = 0; i < nfd; i++) { |
133 | const char *event; | 250 | const char *event = NULL; |
134 | struct input_event ev; | ||
135 | 251 | ||
136 | if (!(pfd[i].revents & POLLIN)) | 252 | memset(&ev, 0, sizeof(ev)); |
137 | continue; | ||
138 | 253 | ||
139 | if (sizeof(ev) != full_read(pfd[i].fd, &ev, sizeof(ev))) | 254 | if (!(pfd[i].revents & POLLIN)) |
140 | continue; | ||
141 | //bb_info_msg("%d: %d %d %4d", i, ev.type, ev.code, ev.value); | ||
142 | |||
143 | // filter out unneeded events | ||
144 | if (ev.value != 1) | ||
145 | continue; | 255 | continue; |
146 | 256 | ||
147 | event = NULL; | 257 | if (option_mask32 & OPT_e) { |
258 | char *buf; | ||
259 | int len; | ||
148 | 260 | ||
149 | // N.B. we will conform to /proc/acpi/event | 261 | buf = xmalloc_reads(pfd[i].fd, NULL, NULL); |
150 | // naming convention when assigning event names | 262 | /* buf = "button/power PWRB 00000080 00000000" */ |
263 | len = strlen(buf) - 9; | ||
264 | if (len >= 0) | ||
265 | buf[len] = '\0'; | ||
266 | event = find_action(NULL, buf); | ||
267 | } else { | ||
268 | if (sizeof(ev) != full_read(pfd[i].fd, &ev, sizeof(ev))) | ||
269 | continue; | ||
151 | 270 | ||
152 | // TODO: do we want other events? | 271 | if (ev.value != 1 && ev.value != 0) |
272 | continue; | ||
153 | 273 | ||
154 | // power and sleep buttons delivered as keys pressed | 274 | event = find_action(&ev, NULL); |
155 | if (EV_KEY == ev.type) { | ||
156 | if (KEY_POWER == ev.code) | ||
157 | event = "PWRF/00000080"; | ||
158 | else if (KEY_SLEEP == ev.code) | ||
159 | event = "SLPB/00000080"; | ||
160 | } | ||
161 | // switches | ||
162 | else if (EV_SW == ev.type) { | ||
163 | if (SW_LID == ev.code) | ||
164 | event = "LID/00000080"; | ||
165 | else if (SW_RFKILL_ALL == ev.code) | ||
166 | event = "RFKILL"; | ||
167 | } | 275 | } |
168 | // filter out unneeded events | ||
169 | if (!event) | 276 | if (!event) |
170 | continue; | 277 | continue; |
171 | |||
172 | // spawn event handler | 278 | // spawn event handler |
173 | process_event(event); | 279 | process_event(event); |
174 | } | 280 | } |
175 | } | 281 | } |
176 | 282 | ||
177 | if (ENABLE_FEATURE_CLEAN_UP) { | 283 | if (ENABLE_FEATURE_CLEAN_UP) { |
178 | for (i = 0; i < nfd; i++) | 284 | while (nfd--) { |
179 | close(pfd[i].fd); | 285 | if (pfd[nfd].fd) { |
286 | close(pfd[nfd].fd); | ||
287 | } | ||
288 | } | ||
180 | free(pfd); | 289 | free(pfd); |
181 | } | 290 | } |
291 | remove_pidfile(opt_pidfile); | ||
182 | 292 | ||
183 | return EXIT_SUCCESS; | 293 | return EXIT_SUCCESS; |
184 | } | 294 | } |