Codebase list acpid / d80cf20
Merge commit 'upstream/2.0.9' Michael Meskes 13 years ago
12 changed file(s) with 189 addition(s) and 126 deletion(s). Raw diff Collapse all Expand all
0 * Tue Feb 15 2010 Ted Felix <http://www.tedfelix.com>
0 * Fri Apr 15 2011 Ted Felix <http://www.tedfelix.com>
1 - 2.0.9 release
2 - Removed newlines from acpid_log() calls and modified acpid_log() to
3 no longer need newlines. This change to acpid prevents blank lines in
4 the log for versions of syslogd that preserve newlines. (acpid.c
5 connection_list.c event.c inotify_handler.c input_layer.c netlink.c
6 proc.c sock.c) (Michael Meskes, Ted Felix)
7 - Added fcntl() for O_NONBLOCK on the client sockets. This prevents acpid
8 from hanging if a client behaves badly. (sock.c) (Vasiliy Kulikov)
9 From: http://www.openwall.com/lists/oss-security/2011/01/19/4
10 - Improvements to error handling. (sock.c) (Ted Felix)
11
12 * Tue Feb 15 2011 Ted Felix <http://www.tedfelix.com>
113 - 2.0.8 release
214 - Fixed "comparison between signed and unsigned integer expressions"
315 error with gcc 4.6. (libnetlink.c) (Eugeni Dodonov)
00 # Makefile for ACPI daemon
11
22 # update these numbers for new releases
3 VERSION = 2.0.8
3 VERSION = 2.0.9
44
55 OPT = -O2
66
44 - Run all these tests with valgrind to detect memory leaks.
55 - It's best to test without a window manager running (such as GNOME or KDE) as they tend to handle acpi events on their own and override acpid. To bring down X on a system that is configured with a graphical login, there's usually an "init" script you can run. As an example, with Debian/GNOME, log off of your X/GNOME session, switch to another tty (e.g. Alt-Ctrl-F1), login, and do this:
66 sudo /etc/init.d/gdm stop
7 [need instructions for upstart, maybe this: sudo initctl gdm stop]
78 Now X is out of the way and you can test from the console.
89 - You can kill acpid with "sudo killall acpid".
910 - To make testing more convenient, you can run acpid from a shell as "acpid -ld" to get maximum logging. Use Ctrl-C to stop acpid.
115115 exit(EXIT_FAILURE);
116116 }
117117
118 acpid_log(LOG_INFO, "starting up with %s\n",
118 acpid_log(LOG_INFO, "starting up with %s",
119119 netlink ? "netlink and the input layer" : "proc fs");
120120
121121 /* trap key signals */
135135 exit(EXIT_FAILURE);
136136 }
137137
138 acpid_log(LOG_INFO, "waiting for events: event logging is %s\n",
138 acpid_log(LOG_INFO, "waiting for events: event logging is %s",
139139 logevents ? "on" : "off");
140140
141141 /* main loop */
155155 if (nready < 0 && errno == EINTR) {
156156 continue;
157157 } else if (nready < 0) {
158 acpid_log(LOG_ERR, "select(): %s\n", strerror(errno));
158 acpid_log(LOG_ERR, "select(): %s", strerror(errno));
159159 continue;
160160 }
161161
334334 /* fork off the parent process */
335335 pid = fork();
336336 if (pid < 0) {
337 acpid_log(LOG_ERR, "fork: %s\n", strerror(errno));
337 acpid_log(LOG_ERR, "fork: %s", strerror(errno));
338338 return -1;
339339 }
340340 /* if we got a good PID, then we can exit the parent process */
352352 /* detach the process from the parent (normally a shell) */
353353 sid = setsid();
354354 if (sid < 0) {
355 acpid_log(LOG_ERR, "setsid: %s\n", strerror(errno));
355 acpid_log(LOG_ERR, "setsid: %s", strerror(errno));
356356 return -1;
357357 }
358358
359359 /* Change the current working directory. This prevents the current
360360 directory from being locked; hence not being able to remove it. */
361361 if (chdir("/") < 0) {
362 acpid_log(LOG_ERR, "chdir(\"/\"): %s\n", strerror(errno));
362 acpid_log(LOG_ERR, "chdir(\"/\"): %s", strerror(errno));
363363 return -1;
364364 }
365365
387387 /* open /dev/null */
388388 nullfd = open("/dev/null", O_RDWR);
389389 if (nullfd < 0) {
390 acpid_log(LOG_ERR, "can't open /dev/null: %s\n", strerror(errno));
390 acpid_log(LOG_ERR, "can't open /dev/null: %s", strerror(errno));
391391 return -1;
392392 }
393393
394394 /* set up stdin, stdout, stderr to /dev/null */
395395 if (dup2(nullfd, STDIN_FILENO) != STDIN_FILENO) {
396 acpid_log(LOG_ERR, "dup2() stdin: %s\n", strerror(errno));
396 acpid_log(LOG_ERR, "dup2() stdin: %s", strerror(errno));
397397 return -1;
398398 }
399399 if (!acpid_debug && dup2(nullfd, STDOUT_FILENO) != STDOUT_FILENO) {
400 acpid_log(LOG_ERR, "dup2() stdout: %s\n", strerror(errno));
400 acpid_log(LOG_ERR, "dup2() stdout: %s", strerror(errno));
401401 return -1;
402402 }
403403 if (!acpid_debug && dup2(nullfd, STDERR_FILENO) != STDERR_FILENO) {
404 acpid_log(LOG_ERR, "dup2() stderr: %s\n", strerror(errno));
404 acpid_log(LOG_ERR, "dup2() stderr: %s", strerror(errno));
405405 return -1;
406406 }
407407
435435 }
436436
437437 /* something went wrong */
438 acpid_log(LOG_ERR, "can't create pidfile %s: %s\n",
438 acpid_log(LOG_ERR, "can't create pidfile %s: %s",
439439 pidfile, strerror(errno));
440440 return -1;
441441 }
444444 clean_exit_with_status(int status)
445445 {
446446 acpid_cleanup_rules(1);
447 acpid_log(LOG_NOTICE, "exiting\n");
447 acpid_log(LOG_NOTICE, "exiting");
448448 unlink(pidfile);
449449 exit(status);
450450 }
458458 static void
459459 reload_conf(int sig __attribute__((unused)))
460460 {
461 acpid_log(LOG_NOTICE, "reloading configuration\n");
461 acpid_log(LOG_NOTICE, "reloading configuration");
462462 acpid_cleanup_rules(0);
463463 acpid_read_conf(confdir);
464464 }
478478 va_start(args, fmt);
479479 vfprintf(stderr, fmt, args);
480480 va_end(args);
481
482 fprintf(stderr, "\n");
481483 }
482484 } else {
483485 va_start(args, fmt);
5353 if (nconnections < 0)
5454 return;
5555 if (nconnections >= MAX_CONNECTIONS) {
56 acpid_log(LOG_ERR, "Too many connections.\n");
56 acpid_log(LOG_ERR, "Too many connections.");
5757 /* ??? This routine should return -1 in this situation so that */
5858 /* callers can clean up any open fds and whatnot. */
5959 return;
0 acpid (1:2.0.9-1) unstable; urgency=low
1
2 * Imported Upstream version 2.0.9
3
4 -- Michael Meskes <meskes@debian.org> Sun, 17 Apr 2011 16:33:17 +0200
5
06 acpid (1:2.0.8-4) unstable; urgency=low
17
28 * Updated homepage filed to point to new URL. (Closes: #618537)
9999
100100 dir = opendir(confdir);
101101 if (!dir) {
102 acpid_log(LOG_ERR, "opendir(%s): %s\n",
102 acpid_log(LOG_ERR, "opendir(%s): %s",
103103 confdir, strerror(errno));
104104 unlock_rules();
105105 return -1;
108108 /* Compile the regular expression. This is based on run-parts(8). */
109109 rc = regcomp(&preg, "^[a-zA-Z0-9_-]+$", RULE_REGEX_FLAGS);
110110 if (rc) {
111 acpid_log(LOG_ERR, "regcomp(): %d\n", rc);
111 acpid_log(LOG_ERR, "regcomp(): %d", rc);
112112 unlock_rules();
113113 return -1;
114114 }
129129
130130 /* skip any files that don't match the run-parts convention */
131131 if (regexec(&preg, dirent->d_name, 0, NULL, 0) != 0) {
132 acpid_log(LOG_INFO, "skipping conf file %s/%s\n",
132 acpid_log(LOG_INFO, "skipping conf file %s/%s",
133133 confdir, dirent->d_name);
134134 continue;
135135 }
140140
141141 file = malloc(len);
142142 if (!file) {
143 acpid_log(LOG_ERR, "malloc(): %s\n", strerror(errno));
143 acpid_log(LOG_ERR, "malloc(): %s", strerror(errno));
144144 unlock_rules();
145145 return -1;
146146 }
148148
149149 /* allow only regular files and symlinks to files */
150150 if (stat(file, &stat_buf) != 0) {
151 acpid_log(LOG_ERR, "stat(%s): %s\n", file,
151 acpid_log(LOG_ERR, "stat(%s): %s", file,
152152 strerror(errno));
153153 free(file);
154154 continue; /* keep trying the rest of the files */
155155 }
156156 if (!S_ISREG(stat_buf.st_mode)) {
157 acpid_log(LOG_INFO, "skipping non-file %s\n", file);
157 acpid_log(LOG_INFO, "skipping non-file %s", file);
158158 free(file);
159159 continue; /* skip non-regular files */
160160 }
169169 closedir(dir);
170170 unlock_rules();
171171
172 acpid_log(LOG_INFO, "%d rule%s loaded\n",
172 acpid_log(LOG_INFO, "%d rule%s loaded",
173173 nrules, (nrules == 1)?"":"s");
174174
175175 return 0;
187187 lock_rules();
188188
189189 if (acpid_debug >= 3) {
190 acpid_log(LOG_DEBUG, "cleaning up rules\n");
190 acpid_log(LOG_DEBUG, "cleaning up rules");
191191 }
192192
193193 if (do_detach) {
224224 int line = 0;
225225 struct rule *r;
226226
227 acpid_log(LOG_DEBUG, "parsing conf file %s\n", file);
227 acpid_log(LOG_DEBUG, "parsing conf file %s", file);
228228
229229 fp = fopen(file, "r");
230230 if (!fp) {
231 acpid_log(LOG_ERR, "fopen(%s): %s\n", file, strerror(errno));
231 acpid_log(LOG_ERR, "fopen(%s): %s", file, strerror(errno));
232232 return NULL;
233233 }
234234
241241 r->type = RULE_CMD;
242242 r->origin = strdup(file);
243243 if (!r->origin) {
244 acpid_log(LOG_ERR, "strdup(): %s\n", strerror(errno));
244 acpid_log(LOG_ERR, "strdup(): %s", strerror(errno));
245245 free_rule(r);
246246 fclose(fp);
247247 return NULL;
274274 /* quick parse */
275275 n = sscanf(p, "%63[^=\n]=%255[^\n]", key, val);
276276 if (n != 2) {
277 acpid_log(LOG_WARNING, "can't parse %s at line %d\n",
277 acpid_log(LOG_WARNING, "can't parse %s at line %d",
278278 file, line);
279279 continue;
280280 }
281281 if (acpid_debug >= 3) {
282 acpid_log(LOG_DEBUG, " key=\"%s\" val=\"%s\"\n",
282 acpid_log(LOG_DEBUG, " key=\"%s\" val=\"%s\"",
283283 key, val);
284284 }
285285 /* handle the parsed line */
287287 int rv;
288288 r->event = malloc(sizeof(regex_t));
289289 if (!r->event) {
290 acpid_log(LOG_ERR, "malloc(): %s\n",
290 acpid_log(LOG_ERR, "malloc(): %s",
291291 strerror(errno));
292292 free_rule(r);
293293 fclose(fp);
297297 if (rv) {
298298 char rbuf[128];
299299 regerror(rv, r->event, rbuf, sizeof(rbuf));
300 acpid_log(LOG_ERR, "regcomp(): %s\n", rbuf);
300 acpid_log(LOG_ERR, "regcomp(): %s", rbuf);
301301 free_rule(r);
302302 fclose(fp);
303303 return NULL;
304304 }
305305 } else if (!strcasecmp(key, "action")) {
306306 if (check_escapes(val) < 0) {
307 acpid_log(LOG_ERR, "can't load file %s\n",
307 acpid_log(LOG_ERR, "can't load file %s",
308308 file);
309309 free_rule(r);
310310 fclose(fp);
312312 }
313313 r->action.cmd = strdup(val);
314314 if (!r->action.cmd) {
315 acpid_log(LOG_ERR, "strdup(): %s\n",
315 acpid_log(LOG_ERR, "strdup(): %s",
316316 strerror(errno));
317317 free_rule(r);
318318 fclose(fp);
320320 }
321321 } else {
322322 acpid_log(LOG_WARNING,
323 "unknown option '%s' in %s at line %d\n",
323 "unknown option '%s' in %s at line %d",
324324 key, file, line);
325325 continue;
326326 }
327327 }
328328 if (!r->event || !r->action.cmd) {
329 acpid_log(LOG_INFO, "skipping incomplete file %s\n", file);
329 acpid_log(LOG_INFO, "skipping incomplete file %s", file);
330330 free_rule(r);
331331 fclose(fp);
332332 return NULL;
342342 struct rule *r;
343343 int nrules = 0;
344344
345 acpid_log(LOG_NOTICE, "client connected from %s\n", origin);
345 acpid_log(LOG_NOTICE, "client connected from %s", origin);
346346
347347 r = parse_client(clifd);
348348 if (r) {
351351 nrules++;
352352 }
353353
354 acpid_log(LOG_INFO, "%d client rule%s loaded\n",
354 acpid_log(LOG_INFO, "%d client rule%s loaded",
355355 nrules, (nrules == 1)?"":"s");
356356
357357 return 0;
372372 r->action.fd = client;
373373 r->event = malloc(sizeof(regex_t));
374374 if (!r->event) {
375 acpid_log(LOG_ERR, "malloc(): %s\n", strerror(errno));
375 acpid_log(LOG_ERR, "malloc(): %s", strerror(errno));
376376 free_rule(r);
377377 return NULL;
378378 }
380380 if (rv) {
381381 char buf[128];
382382 regerror(rv, r->event, buf, sizeof(buf));
383 acpid_log(LOG_ERR, "regcomp(): %s\n", buf);
383 acpid_log(LOG_ERR, "regcomp(): %s", buf);
384384 free_rule(r);
385385 return NULL;
386386 }
430430
431431 r = malloc(sizeof(*r));
432432 if (!r) {
433 acpid_log(LOG_ERR, "malloc(): %s\n", strerror(errno));
433 acpid_log(LOG_ERR, "malloc(): %s", strerror(errno));
434434 return NULL;
435435 }
436436
476476 r = poll(&pfd, 1, 0);
477477
478478 if (r < 0) {
479 acpid_log(LOG_ERR, "poll(): %s\n", strerror(errno));
479 acpid_log(LOG_ERR, "poll(): %s", strerror(errno));
480480 return 0;
481481 }
482482
498498 struct ucred cred;
499499 /* closed */
500500 acpid_log(LOG_NOTICE,
501 "client %s has disconnected\n", p->origin);
501 "client %s has disconnected", p->origin);
502502 delist_rule(&client_list, p);
503503 ud_get_peercred(p->action.fd, &cred);
504504 if (cred.uid != 0) {
538538 /* a match! */
539539 if (logevents) {
540540 acpid_log(LOG_INFO,
541 "rule from %s matched\n",
541 "rule from %s matched",
542542 p->origin);
543543 }
544544 nrules++;
548548 do_client_rule(p, event);
549549 } else {
550550 acpid_log(LOG_WARNING,
551 "unknown rule type: %d\n",
551 "unknown rule type: %d",
552552 p->type);
553553 }
554554 } else {
555555 if (acpid_debug >= 3 && logevents) {
556556 acpid_log(LOG_INFO,
557 "rule from %s did not match\n",
557 "rule from %s did not match",
558558 p->origin);
559559 }
560560 }
565565 unlock_rules();
566566
567567 if (logevents) {
568 acpid_log(LOG_INFO, "%d total rule%s matched\n",
568 acpid_log(LOG_INFO, "%d total rule%s matched",
569569 nrules, (nrules == 1)?"":"s");
570570 }
571571
591591 lock_rules(void)
592592 {
593593 if (acpid_debug >= 4) {
594 acpid_log(LOG_DEBUG, "blocking signals for rule lock\n");
594 acpid_log(LOG_DEBUG, "blocking signals for rule lock");
595595 }
596596 sigprocmask(SIG_BLOCK, signals_handled(), NULL);
597597 }
600600 unlock_rules(void)
601601 {
602602 if (acpid_debug >= 4) {
603 acpid_log(LOG_DEBUG, "unblocking signals for rule lock\n");
603 acpid_log(LOG_DEBUG, "unblocking signals for rule lock");
604604 }
605605 sigprocmask(SIG_UNBLOCK, signals_handled(), NULL);
606606 }
619619 pid = fork();
620620 switch (pid) {
621621 case -1:
622 acpid_log(LOG_ERR, "fork(): %s\n", strerror(errno));
622 acpid_log(LOG_ERR, "fork(): %s", strerror(errno));
623623 return -1;
624624 case 0: /* child */
625625 /* parse the commandline, doing any substitutions needed */
626626 action = parse_cmd(rule->action.cmd, event);
627627 if (logevents) {
628628 acpid_log(LOG_INFO,
629 "executing action \"%s\"\n", action);
629 "executing action \"%s\"", action);
630630 }
631631
632632 /* reset signals */
642642 }
643643 execl("/bin/sh", "/bin/sh", "-c", action, NULL);
644644 /* should not get here */
645 acpid_log(LOG_ERR, "execl(): %s\n", strerror(errno));
645 acpid_log(LOG_ERR, "execl(): %s", strerror(errno));
646646 exit(EXIT_FAILURE);
647647 }
648648
654654
655655 if (logevents) {
656656 if (WIFEXITED(status)) {
657 acpid_log(LOG_INFO, "action exited with status %d\n",
657 acpid_log(LOG_INFO, "action exited with status %d",
658658 WEXITSTATUS(status));
659659 } else if (WIFSIGNALED(status)) {
660 acpid_log(LOG_INFO, "action exited on signal %d\n",
660 acpid_log(LOG_INFO, "action exited on signal %d",
661661 WTERMSIG(status));
662662 } else {
663 acpid_log(LOG_INFO, "action exited with status %d\n",
663 acpid_log(LOG_INFO, "action exited with status %d",
664664 status);
665665 }
666666 }
675675 int client = rule->action.fd;
676676
677677 if (logevents) {
678 acpid_log(LOG_INFO, "notifying client %s\n", rule->origin);
678 acpid_log(LOG_INFO, "notifying client %s", rule->origin);
679679 }
680680
681681 r = safe_write(client, event, strlen(event));
683683 struct ucred cred;
684684 /* closed */
685685 acpid_log(LOG_NOTICE,
686 "client %s has disconnected\n", rule->origin);
686 "client %s has disconnected", rule->origin);
687687 delist_rule(&client_list, rule);
688688 ud_get_peercred(rule->action.fd, &cred);
689689 if (cred.uid != 0) {
722722 } while (ttl < len && ntries);
723723
724724 if (!ntries) {
725 /* crap */
726725 if (acpid_debug >= 2) {
727 acpid_log(LOG_ERR, "uh-oh! safe_write() timed out\n");
726 acpid_log(LOG_ERR, "safe_write() timed out");
728727 }
729728 return r;
730729 }
761760 buf[i++] = *p++;
762761 }
763762 if (acpid_debug >= 2) {
764 acpid_log(LOG_DEBUG, "expanded \"%s\" -> \"%s\"\n", cmd, buf);
763 acpid_log(LOG_DEBUG, "expanded \"%s\" -> \"%s\"", cmd, buf);
765764 }
766765
767766 return buf;
780779 p++;
781780 if (!*p) {
782781 acpid_log(LOG_WARNING,
783 "invalid escape at EOL\n");
782 "invalid escape at EOL");
784783 return -1;
785784 } else if (*p != '%' && *p != 'e') {
786785 acpid_log(LOG_WARNING,
787 "invalid escape \"%%%c\"\n", *p);
786 "invalid escape \"%%%c\"", *p);
788787 r = -1;
789788 }
790789 }
4848
4949 bytes = read(fd, &eventbuf.buffer, sizeof(eventbuf.buffer));
5050
51 acpid_log(LOG_DEBUG, "inotify read bytes: %d\n", bytes);
51 acpid_log(LOG_DEBUG, "inotify read bytes: %d", bytes);
5252
5353 /* eof is not expected */
5454 if (bytes == 0)
5555 {
56 acpid_log(LOG_WARNING, "inotify fd eof encountered\n");
56 acpid_log(LOG_WARNING, "inotify fd eof encountered");
5757 return;
5858 }
5959 else if (bytes < 0)
6060 {
6161 /* EINVAL means buffer wasn't big enough. See inotify(7). */
62 acpid_log(LOG_ERR, "inotify read error: %s (%d)\n",
62 acpid_log(LOG_ERR, "inotify read error: %s (%d)",
6363 strerror(errno), errno);
64 acpid_log(LOG_ERR, "disconnecting from inotify\n");
64 acpid_log(LOG_ERR, "disconnecting from inotify");
6565 delete_connection(fd);
6666 return;
6767 }
6868
69 acpid_log(LOG_DEBUG, "inotify name len: %d\n", eventbuf.event.len);
69 acpid_log(LOG_DEBUG, "inotify name len: %d", eventbuf.event.len);
7070
7171 /* if a name is included */
7272 if (eventbuf.event.len > 0)
7979 strcat(devname, "/");
8080 strncat(devname, eventbuf.event.name, dnsize - strlen(devname) - 1);
8181
82 acpid_log(LOG_DEBUG, "inotify about to open: %s\n", devname);
82 acpid_log(LOG_DEBUG, "inotify about to open: %s", devname);
8383
8484 open_inputfile(devname);
8585 }
9797 fd = inotify_init();
9898
9999 if (fd < 0) {
100 acpid_log(LOG_ERR, "inotify_init() failed: %s (%d)\n",
100 acpid_log(LOG_ERR, "inotify_init() failed: %s (%d)",
101101 strerror(errno), errno);
102102 return;
103103 }
104104
105 acpid_log(LOG_DEBUG, "inotify fd: %d\n", fd);
105 acpid_log(LOG_DEBUG, "inotify fd: %d", fd);
106106
107107 /* watch for new files being created in /dev/input */
108108 wd = inotify_add_watch(fd, ACPID_INPUTLAYERDIR, IN_CREATE);
109109
110110 if (wd < 0) {
111 acpid_log(LOG_ERR, "inotify_add_watch() failed: %s (%d)\n",
111 acpid_log(LOG_ERR, "inotify_add_watch() failed: %s (%d)",
112112 strerror(errno), errno);
113113 close(fd);
114114 return;
115115 }
116116
117 acpid_log(LOG_DEBUG, "inotify wd: %d\n", wd);
117 acpid_log(LOG_DEBUG, "inotify wd: %d", wd);
118118
119119 /* add a connection to the list */
120120 c.fd = fd;
190190 nbytes = read(fd, &event, sizeof(event));
191191
192192 if (nbytes == 0) {
193 acpid_log(LOG_WARNING, "input layer connection closed\n");
193 acpid_log(LOG_WARNING, "input layer connection closed");
194194 exit(EXIT_FAILURE);
195195 }
196196
199199 if (errno == EINTR)
200200 return;
201201 if (errno == ENODEV) {
202 acpid_log(LOG_WARNING, "input device has been disconnected\n");
202 acpid_log(LOG_WARNING, "input device has been disconnected");
203203 delete_connection(fd);
204204 return;
205205 }
206 acpid_log(LOG_ERR, "input layer read error: %s (%d)\n",
206 acpid_log(LOG_ERR, "input layer read error: %s (%d)",
207207 strerror(errno), errno);
208208 if (++nerrs >= ACPID_MAX_ERRS) {
209209 acpid_log(LOG_ERR,
210210 "too many errors reading "
211 "input layer - aborting\n");
211 "input layer - aborting");
212212 exit(EXIT_FAILURE);
213213 }
214214 return;
219219
220220 if (nbytes != sizeof(event)) {
221221 acpid_log(LOG_WARNING, "input layer unexpected length: "
222 "%d expected: %d\n", nbytes, sizeof(event));
222 "%d expected: %d", nbytes, sizeof(event));
223223 return;
224224 }
225225
234234 if (logevents) {
235235 acpid_log(LOG_INFO,
236236 "lockfile present, not processing "
237 "input layer event \"%s\"\n", str);
237 "input layer event \"%s\"", str);
238238 }
239239 return;
240240 }
241241
242242 if (logevents)
243243 acpid_log(LOG_INFO,
244 "received input layer event \"%s\"\n", str);
244 "received input layer event \"%s\"", str);
245245
246246 /* send the event off to the handler */
247247 acpid_handle_event(str);
248248
249249 if (logevents)
250250 acpid_log(LOG_INFO,
251 "completed input layer event \"%s\"\n", str);
251 "completed input layer event \"%s\"", str);
252252 }
253253
254254 #define BITS_PER_LONG (sizeof(long) * 8)
313313 }
314314
315315 acpid_log(LOG_DEBUG, "input layer %s "
316 "opened successfully\n", filename);
316 "opened successfully", filename);
317317
318318 /* add a connection to the list */
319319 c.fd = fd;
349349 }
350350
351351 if (!success)
352 acpid_log(LOG_ERR, "cannot open input layer\n");
352 acpid_log(LOG_ERR, "cannot open input layer");
353353
354354 globfree(&globbuf);
355355 }
5656 /* if this message doesn't have the proper family ID, drop it */
5757 if (msg->nlmsg_type != acpi_ids_getfamily()) {
5858 if (logevents) {
59 acpid_log(LOG_INFO, "wrong netlink family ID.\n");
59 acpid_log(LOG_INFO, "wrong netlink family ID.");
6060 }
6161 return;
6262 }
6565
6666 if (len < 0) {
6767 acpid_log(LOG_WARNING,
68 "wrong netlink controller message len: %d\n", len);
68 "wrong netlink controller message len: %d", len);
6969 return;
7070 }
7171
8989 if (logevents) {
9090 acpid_log(LOG_INFO,
9191 "lockfile present, not processing "
92 "netlink event \"%s\"\n", buf);
92 "netlink event \"%s\"", buf);
9393 }
9494 return;
9595 }
9696
9797 if (logevents)
9898 acpid_log(LOG_INFO,
99 "received netlink event \"%s\"\n", buf);
99 "received netlink event \"%s\"", buf);
100100
101101 /* send the event off to the handler */
102102 acpid_handle_event(buf);
103103
104104 if (logevents)
105105 acpid_log(LOG_INFO,
106 "completed netlink event \"%s\"\n", buf);
106 "completed netlink event \"%s\"", buf);
107107 }
108108 }
109109
147147 if (errno == EINTR)
148148 return;
149149
150 acpid_log(LOG_ERR, "netlink read error: %s (%d)\n",
150 acpid_log(LOG_ERR, "netlink read error: %s (%d)",
151151 strerror(errno), errno);
152152 if (++nerrs >= ACPID_MAX_ERRS) {
153153 acpid_log(LOG_ERR,
154154 "too many errors reading via "
155 "netlink - aborting\n");
155 "netlink - aborting");
156156 exit(EXIT_FAILURE);
157157 }
158158 return;
159159 }
160160 /* if an orderly shutdown has occurred, we're done */
161161 if (status == 0) {
162 acpid_log(LOG_WARNING, "netlink connection closed\n");
162 acpid_log(LOG_WARNING, "netlink connection closed");
163163 exit(EXIT_FAILURE);
164164 }
165165 /* check to see if the address length has changed */
166166 if (msg.msg_namelen != sizeof(nladdr)) {
167167 acpid_log(LOG_WARNING, "netlink unexpected length: "
168 "%d expected: %d\n", msg.msg_namelen, sizeof(nladdr));
168 "%d expected: %d", msg.msg_namelen, sizeof(nladdr));
169169 return;
170170 }
171171
176176
177177 if (l < 0 || len > status) {
178178 if (msg.msg_flags & MSG_TRUNC) {
179 acpid_log(LOG_WARNING, "netlink msg truncated (1)\n");
179 acpid_log(LOG_WARNING, "netlink msg truncated (1)");
180180 return;
181181 }
182182 acpid_log(LOG_WARNING,
183 "malformed netlink msg, length %d\n", len);
183 "malformed netlink msg, length %d", len);
184184 return;
185185 }
186186
191191 h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
192192 }
193193 if (msg.msg_flags & MSG_TRUNC) {
194 acpid_log(LOG_WARNING, "netlink msg truncated (2)\n");
194 acpid_log(LOG_WARNING, "netlink msg truncated (2)");
195195 return;
196196 }
197197 if (status) {
198 acpid_log(LOG_WARNING, "netlink remnant of size %d\n", status);
198 acpid_log(LOG_WARNING, "netlink remnant of size %d", status);
199199 return;
200200 }
201201
208208 nl_mgrp(__u32 group)
209209 {
210210 if (group > 31) {
211 acpid_log(LOG_ERR, "Unexpected group number %d\n", group);
211 acpid_log(LOG_ERR, "Unexpected group number %d", group);
212212 return 0;
213213 }
214214 return group ? (1 << (group - 1)) : 0;
222222 /* open the appropriate netlink socket for input */
223223 if (rtnl_open_byproto(
224224 &rth, nl_mgrp(acpi_ids_getgroup()), NETLINK_GENERIC) < 0) {
225 acpid_log(LOG_ERR, "cannot open generic netlink socket\n");
226 return;
227 }
228
229 acpid_log(LOG_DEBUG, "netlink opened successfully\n");
225 acpid_log(LOG_ERR, "cannot open generic netlink socket");
226 return;
227 }
228
229 acpid_log(LOG_DEBUG, "netlink opened successfully");
230230
231231 /* add a connection to the list */
232232 c.fd = rth.fd;
4747 if (logevents && event != NULL) {
4848 acpid_log(LOG_INFO,
4949 "lockfile present, not processing "
50 "event \"%s\"\n", event);
50 "event \"%s\"", event);
5151 }
5252 return;
5353 }
5656 if (event) {
5757 if (logevents) {
5858 acpid_log(LOG_INFO,
59 "procfs received event \"%s\"\n", event);
59 "procfs received event \"%s\"", event);
6060 }
6161 acpid_handle_event(event);
6262 if (logevents) {
6363 acpid_log(LOG_INFO,
64 "procfs completed event \"%s\"\n", event);
64 "procfs completed event \"%s\"", event);
6565 }
6666 } else if (errno == EPIPE) {
6767 acpid_log(LOG_WARNING,
68 "events file connection closed\n");
68 "events file connection closed");
6969 exit(EXIT_FAILURE);
7070 } else {
7171 static int nerrs;
7272 if (++nerrs >= ACPID_MAX_ERRS) {
7373 acpid_log(LOG_ERR,
7474 "too many errors reading "
75 "events file - aborting\n");
75 "events file - aborting");
7676 exit(EXIT_FAILURE);
7777 }
7878 }
8888 if (fd < 0) {
8989 if (errno == ENOENT) {
9090 acpid_log(LOG_DEBUG, "Deprecated %s was not found. "
91 "Trying netlink and the input layer...\n", eventfile);
91 "Trying netlink and the input layer...", eventfile);
9292 } else {
93 acpid_log(LOG_ERR, "can't open %s: %s (%d)\n", eventfile,
93 acpid_log(LOG_ERR, "can't open %s: %s (%d)", eventfile,
9494 strerror(errno), errno);
9595 }
9696 return -1;
101101 descriptors. */
102102 fcntl(fd, F_SETFD, FD_CLOEXEC);
103103
104 acpid_log(LOG_DEBUG, "proc fs opened successfully\n");
104 acpid_log(LOG_DEBUG, "proc fs opened successfully");
105105
106106 /* add a connection to the list */
107107 c.fd = fd;
131131 r = read(fd, buf+i, 1);
132132 if (r < 0 && errno != EINTR) {
133133 /* we should do something with the data */
134 acpid_log(LOG_ERR, "read(): %s\n",
134 acpid_log(LOG_ERR, "read(): %s",
135135 strerror(errno));
136136 return NULL;
137137 } else if (r == 0) {
175175 /* ??? This memory is leaked since it is never freed */
176176 buf = realloc(buf, buflen);
177177 if (!buf) {
178 acpid_log(LOG_ERR, "malloc(%d): %s\n",
178 acpid_log(LOG_ERR, "malloc(%d): %s",
179179 buflen, strerror(errno));
180180 return NULL;
181181 }
185185 r = read(fd, buf+i, 1);
186186 if (r < 0 && errno != EINTR) {
187187 /* we should do something with the data */
188 acpid_log(LOG_ERR, "read(): %s\n",
188 acpid_log(LOG_ERR, "read(): %s",
189189 strerror(errno));
190190 return NULL;
191191 } else if (r == 0) {
4141 /* the number of non-root clients that are connected */
4242 int non_root_clients;
4343
44 /* accept a new client connection */
4445 static void
4546 process_sock(int fd)
4647 {
5253 /* accept and add to our lists */
5354 cli_fd = ud_accept(fd, &creds);
5455 if (cli_fd < 0) {
55 acpid_log(LOG_ERR, "can't accept client: %s\n",
56 acpid_log(LOG_ERR, "can't accept client: %s",
5657 strerror(errno));
5758 accept_errors++;
5859 if (accept_errors >= 5) {
59 acpid_log(LOG_ERR, "giving up\n");
60 acpid_log(LOG_ERR, "giving up");
6061 clean_exit_with_status(EXIT_FAILURE);
6162 }
6263 return;
6364 }
6465 accept_errors = 0;
65 /* This check against clientmax is from the non-netlink 1.0.10. */
66
67 /* don't allow too many non-root clients */
6668 if (creds.uid != 0 && non_root_clients >= clientmax) {
6769 close(cli_fd);
68 acpid_log(LOG_ERR,
69 "too many non-root clients\n");
70 acpid_log(LOG_ERR, "too many non-root clients");
7071 return;
7172 }
7273 if (creds.uid != 0) {
7374 non_root_clients++;
7475 }
75 fcntl(cli_fd, F_SETFD, FD_CLOEXEC);
76 snprintf(buf, sizeof(buf)-1, "%d[%d:%d]",
76
77 /* don't leak fds when execing */
78 if (fcntl(cli_fd, F_SETFD, FD_CLOEXEC) < 0) {
79 close(cli_fd);
80 acpid_log(LOG_ERR, "fcntl() on client for FD_CLOEXEC: %s",
81 strerror(errno));
82 return;
83 }
84
85 /* don't allow clients to block this */
86 if (fcntl(cli_fd, F_SETFL, O_NONBLOCK) < 0) {
87 close(cli_fd);
88 acpid_log(LOG_ERR, "fcntl() on client for O_NONBLOCK: %s",
89 strerror(errno));
90 return;
91 }
92
93 snprintf(buf, sizeof(buf)-1, "%d[%d:%d]",
7794 creds.pid, creds.uid, creds.gid);
7895 acpid_add_client(cli_fd, buf);
7996 }
8097
98 /* set up the socket for client connections */
8199 void
82100 open_sock()
83101 {
86104
87105 fd = ud_create_socket(socketfile);
88106 if (fd < 0) {
89 acpid_log(LOG_ERR, "can't open socket %s: %s\n",
107 acpid_log(LOG_ERR, "can't open socket %s: %s",
90108 socketfile, strerror(errno));
91109 exit(EXIT_FAILURE);
92110 }
93 fcntl(fd, F_SETFD, FD_CLOEXEC);
94 chmod(socketfile, socketmode);
111
112 /* don't leak fds when execing */
113 if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
114 close(fd);
115 acpid_log(LOG_ERR, "fcntl() on socket %s for FD_CLOEXEC: %s",
116 socketfile, strerror(errno));
117 return;
118 }
119
120 /* avoid a potential hang */
121 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
122 close(fd);
123 acpid_log(LOG_ERR, "fcntl() on socket %s for O_NONBLOCK: %s",
124 socketfile, strerror(errno));
125 return;
126 }
127
128 if (chmod(socketfile, socketmode) < 0) {
129 close(fd);
130 acpid_log(LOG_ERR, "chmod() on socket %s: %s",
131 socketfile, strerror(errno));
132 return;
133 }
134
135 /* if we need to change the socket's group, do so */
95136 if (socketgroup) {
96137 struct group *gr;
97138 struct stat buf;
98 gr = getgrnam(socketgroup);
139
140 gr = getgrnam(socketgroup);
99141 if (!gr) {
100 acpid_log(LOG_ERR, "group %s does not exist\n", socketgroup);
142 acpid_log(LOG_ERR, "group %s does not exist", socketgroup);
101143 exit(EXIT_FAILURE);
102144 }
103145 if (stat(socketfile, &buf) < 0) {
104 acpid_log(LOG_ERR, "can't stat %s\n", socketfile);
146 acpid_log(LOG_ERR, "can't stat %s: %s",
147 socketfile, strerror(errno));
105148 exit(EXIT_FAILURE);
106149 }
107150 if (chown(socketfile, buf.st_uid, gr->gr_gid) < 0) {
108 acpid_log(LOG_ERR, "can't chown: %s\n", strerror(errno));
151 acpid_log(LOG_ERR, "can't chown %s: %s",
152 socketfile, strerror(errno));
109153 exit(EXIT_FAILURE);
110154 }
111155 }
115159 c.process = process_sock;
116160 add_connection(&c);
117161 }
118