|
Packit |
a94d48 |
/*
|
|
Packit |
a94d48 |
* acpid.c - ACPI daemon
|
|
Packit |
a94d48 |
*
|
|
Packit |
a94d48 |
* Portions Copyright (C) 2000 Andrew Henroid
|
|
Packit |
a94d48 |
* Portions Copyright (C) 2001 Sun Microsystems
|
|
Packit |
a94d48 |
* Portions Copyright (C) 2004 Tim Hockin (thockin@hockin.org)
|
|
Packit |
a94d48 |
*
|
|
Packit |
a94d48 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
a94d48 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
a94d48 |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
a94d48 |
* (at your option) any later version.
|
|
Packit |
a94d48 |
*
|
|
Packit |
a94d48 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
a94d48 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
a94d48 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
a94d48 |
* GNU General Public License for more details.
|
|
Packit |
a94d48 |
*
|
|
Packit |
a94d48 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
a94d48 |
* along with this program; if not, write to the Free Software
|
|
Packit |
a94d48 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
a94d48 |
*/
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
#include <unistd.h>
|
|
Packit |
a94d48 |
#include <sys/types.h>
|
|
Packit |
a94d48 |
#include <sys/stat.h>
|
|
Packit |
a94d48 |
#include <fcntl.h>
|
|
Packit |
a94d48 |
#include <signal.h>
|
|
Packit |
a94d48 |
#include <string.h>
|
|
Packit |
a94d48 |
#include <stdio.h>
|
|
Packit |
a94d48 |
#include <stdlib.h>
|
|
Packit |
a94d48 |
#include <errno.h>
|
|
Packit |
a94d48 |
#include <getopt.h>
|
|
Packit |
a94d48 |
#include <dirent.h>
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
#include "acpid.h"
|
|
Packit |
a94d48 |
#include "log.h"
|
|
Packit |
a94d48 |
#include "event.h"
|
|
Packit |
a94d48 |
#include "connection_list.h"
|
|
Packit |
a94d48 |
#include "proc.h"
|
|
Packit |
a94d48 |
#include "sock.h"
|
|
Packit |
a94d48 |
#include "input_layer.h"
|
|
Packit |
a94d48 |
#include "inotify_handler.h"
|
|
Packit |
a94d48 |
#include "netlink.h"
|
|
Packit |
a94d48 |
#include "libc_compat.h"
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
static int handle_cmdline(int *argc, char ***argv);
|
|
Packit |
a94d48 |
static void close_fds(void);
|
|
Packit |
a94d48 |
static int daemonize(void);
|
|
Packit |
a94d48 |
static void open_log(void);
|
|
Packit |
a94d48 |
static int std2null(void);
|
|
Packit |
a94d48 |
static int create_pidfile(void);
|
|
Packit |
a94d48 |
static void clean_exit(int sig);
|
|
Packit |
a94d48 |
static void reload_conf(int sig);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* do we log event info? */
|
|
Packit |
a94d48 |
int logevents;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
const char *progname;
|
|
Packit |
a94d48 |
static const char *confdir = ACPID_CONFDIR;
|
|
Packit |
a94d48 |
static const char *lockfile = ACPID_LOCKFILE;
|
|
Packit |
a94d48 |
static int nosocket;
|
|
Packit |
a94d48 |
static int foreground;
|
|
Packit |
a94d48 |
static const char *pidfile = ACPID_PIDFILE;
|
|
Packit |
a94d48 |
static int netlink;
|
|
Packit |
a94d48 |
const char *dropaction = DROP_ACTION;
|
|
Packit |
a94d48 |
int tpmutefix = 0;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
int
|
|
Packit |
a94d48 |
main(int argc, char **argv)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
/* learn who we really are */
|
|
Packit |
a94d48 |
progname = (const char *)strrchr(argv[0], '/');
|
|
Packit |
a94d48 |
progname = progname ? (progname + 1) : argv[0];
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* handle the commandline */
|
|
Packit |
a94d48 |
handle_cmdline(&argc, &argv);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* close any extra file descriptors */
|
|
Packit |
a94d48 |
close_fds();
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* open the log */
|
|
Packit |
a94d48 |
if (foreground)
|
|
Packit |
a94d48 |
log_to_stderr = 1;
|
|
Packit |
a94d48 |
else
|
|
Packit |
a94d48 |
open_log();
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* if we're running in the background, and we're not being started */
|
|
Packit |
a94d48 |
/* by systemd */
|
|
Packit |
a94d48 |
if (!foreground && !is_socket(STDIN_FILENO)) {
|
|
Packit |
a94d48 |
if (daemonize() < 0)
|
|
Packit |
a94d48 |
exit(EXIT_FAILURE);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
if (!netlink) {
|
|
Packit |
a94d48 |
/* open the acpi event file in the proc fs */
|
|
Packit |
a94d48 |
/* if the open fails, try netlink */
|
|
Packit |
a94d48 |
if (open_proc())
|
|
Packit |
a94d48 |
netlink = 1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
if (netlink) {
|
|
Packit |
a94d48 |
/* open the input layer */
|
|
Packit |
a94d48 |
open_input();
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* watch for new input layer devices */
|
|
Packit |
a94d48 |
open_inotify();
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* open netlink */
|
|
Packit |
a94d48 |
open_netlink();
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* open our socket */
|
|
Packit |
a94d48 |
if (!nosocket) {
|
|
Packit |
a94d48 |
open_sock();
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* redirect standard files to /dev/null */
|
|
Packit |
a94d48 |
if (std2null() < 0) {
|
|
Packit |
a94d48 |
exit(EXIT_FAILURE);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
acpid_log(LOG_INFO, "starting up with %s",
|
|
Packit |
a94d48 |
netlink ? "netlink and the input layer" : "proc fs");
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* trap key signals */
|
|
Packit |
a94d48 |
signal(SIGHUP, reload_conf);
|
|
Packit |
a94d48 |
signal(SIGINT, clean_exit);
|
|
Packit |
a94d48 |
signal(SIGQUIT, clean_exit);
|
|
Packit |
a94d48 |
signal(SIGTERM, clean_exit);
|
|
Packit |
a94d48 |
signal(SIGPIPE, SIG_IGN);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* read in our configuration */
|
|
Packit |
a94d48 |
if (acpid_read_conf(confdir)) {
|
|
Packit |
a94d48 |
exit(EXIT_FAILURE);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* create our pidfile */
|
|
Packit |
a94d48 |
if (!foreground && create_pidfile() < 0) {
|
|
Packit |
a94d48 |
exit(EXIT_FAILURE);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
acpid_log(LOG_INFO, "waiting for events: event logging is %s",
|
|
Packit |
a94d48 |
logevents ? "on" : "off");
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* main loop */
|
|
Packit |
a94d48 |
while (1) {
|
|
Packit |
a94d48 |
fd_set readfds;
|
|
Packit |
a94d48 |
int nready;
|
|
Packit |
a94d48 |
int i;
|
|
Packit |
a94d48 |
struct connection *p;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* it's going to get clobbered, so use a copy */
|
|
Packit |
a94d48 |
readfds = *get_fdset();
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* wait on data */
|
|
Packit |
a94d48 |
nready = TEMP_FAILURE_RETRY(select(get_highestfd() + 1, &readfds, NULL, NULL, NULL));
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
if (nready < 0) {
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "select(): %s", strerror(errno));
|
|
Packit |
a94d48 |
continue;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* house keeping */
|
|
Packit |
a94d48 |
acpid_close_dead_clients();
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* for each connection */
|
|
Packit |
a94d48 |
for (i = 0; i <= get_number_of_connections(); ++i) {
|
|
Packit |
a94d48 |
int fd;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
p = get_connection(i);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* if this connection is invalid, bail */
|
|
Packit |
a94d48 |
if (!p)
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* get the file descriptor */
|
|
Packit |
a94d48 |
fd = p->fd;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* if this file descriptor has data waiting */
|
|
Packit |
a94d48 |
if (FD_ISSET(fd, &readfds)) {
|
|
Packit |
a94d48 |
/* delegate to this connection's process function */
|
|
Packit |
a94d48 |
p->process(fd);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
clean_exit_with_status(EXIT_SUCCESS);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
return 0;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/*
|
|
Packit |
a94d48 |
* Parse command line arguments
|
|
Packit |
a94d48 |
*/
|
|
Packit |
a94d48 |
static int
|
|
Packit |
a94d48 |
handle_cmdline(int *argc, char ***argv)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
struct option opts[] = {
|
|
Packit |
a94d48 |
{"confdir", 1, 0, 'c'},
|
|
Packit |
a94d48 |
{"clientmax", 1, 0, 'C'},
|
|
Packit |
a94d48 |
{"debug", 0, 0, 'd'},
|
|
Packit |
a94d48 |
{"eventfile", 1, 0, 'e'},
|
|
Packit |
a94d48 |
{"foreground", 0, 0, 'f'},
|
|
Packit |
a94d48 |
{"logevents", 0, 0, 'l'},
|
|
Packit |
a94d48 |
{"socketgroup", 1, 0, 'g'},
|
|
Packit |
a94d48 |
{"socketmode", 1, 0, 'm'},
|
|
Packit |
a94d48 |
{"socketfile", 1, 0, 's'},
|
|
Packit |
a94d48 |
{"nosocket", 1, 0, 'S'},
|
|
Packit |
a94d48 |
{"pidfile", 1, 0, 'p'},
|
|
Packit |
a94d48 |
{"lockfile", 1, 0, 'L'},
|
|
Packit |
a94d48 |
{"netlink", 0, 0, 'n'},
|
|
Packit |
a94d48 |
{"dropaction", 1, 0, 'r'},
|
|
Packit |
a94d48 |
{"tpmutefix", 0, 0, 't'},
|
|
Packit |
a94d48 |
{"version", 0, 0, 'v'},
|
|
Packit |
a94d48 |
{"help", 0, 0, 'h'},
|
|
Packit |
a94d48 |
{NULL, 0, 0, 0},
|
|
Packit |
a94d48 |
};
|
|
Packit |
a94d48 |
const char *opts_help[] = {
|
|
Packit |
a94d48 |
"Set the configuration directory.", /* confdir */
|
|
Packit |
a94d48 |
"Set the limit on non-root socket connections.",/* clientmax */
|
|
Packit |
a94d48 |
"Increase debugging level.",/* debug */
|
|
Packit |
a94d48 |
"Use the specified file for events.", /* eventfile */
|
|
Packit |
a94d48 |
"Run in the foreground.", /* foreground */
|
|
Packit |
a94d48 |
"Log all event activity.", /* logevents */
|
|
Packit |
a94d48 |
"Set the group on the socket file.", /* socketgroup */
|
|
Packit |
a94d48 |
"Set the permissions on the socket file.",/* socketmode */
|
|
Packit |
a94d48 |
"Use the specified socket file.", /* socketfile */
|
|
Packit |
a94d48 |
"Do not listen on a UNIX socket (overrides -s).",/* nosocket */
|
|
Packit |
a94d48 |
"Use the specified PID file.", /* pidfile */
|
|
Packit |
a94d48 |
"Use the specified lockfile to stop processing.", /* lockfile */
|
|
Packit |
a94d48 |
"Force netlink/input layer mode. (overrides -e)", /* netlink */
|
|
Packit |
a94d48 |
"Define the pseudo-action to drop an event.", /* dropaction */
|
|
Packit |
a94d48 |
"Fixup for ThinkPad mute-repeat behaviour.", /* tpmutefix */
|
|
Packit |
a94d48 |
"Print version information.", /* version */
|
|
Packit |
a94d48 |
"Print this message.", /* help */
|
|
Packit |
a94d48 |
};
|
|
Packit |
a94d48 |
struct option *opt;
|
|
Packit |
a94d48 |
const char **hlp;
|
|
Packit |
a94d48 |
int max, size;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
for (;;) {
|
|
Packit |
a94d48 |
int i;
|
|
Packit |
a94d48 |
i = getopt_long(*argc, *argv,
|
|
Packit |
a94d48 |
"c:C:de:flg:m:s:Sp:L:nr:tvh", opts, NULL);
|
|
Packit |
a94d48 |
if (i == -1) {
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
switch (i) {
|
|
Packit |
a94d48 |
case 'c':
|
|
Packit |
a94d48 |
confdir = optarg;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'C':
|
|
Packit |
a94d48 |
clientmax = strtol(optarg, NULL, 0);
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'd':
|
|
Packit |
a94d48 |
debug_level++;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'e':
|
|
Packit |
a94d48 |
eventfile = optarg;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'f':
|
|
Packit |
a94d48 |
foreground = 1;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'l':
|
|
Packit |
a94d48 |
logevents = 1;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'g':
|
|
Packit |
a94d48 |
socketgroup = optarg;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'm':
|
|
Packit |
a94d48 |
socketmode = strtol(optarg, NULL, 8);
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 's':
|
|
Packit |
a94d48 |
socketfile = optarg;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'S':
|
|
Packit |
a94d48 |
nosocket = 1;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'p':
|
|
Packit |
a94d48 |
pidfile = optarg;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'L':
|
|
Packit |
a94d48 |
lockfile = optarg;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'n':
|
|
Packit |
a94d48 |
netlink = 1;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'r':
|
|
Packit |
a94d48 |
dropaction = optarg;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 't':
|
|
Packit |
a94d48 |
tpmutefix = 1;
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
case 'v':
|
|
Packit |
a94d48 |
printf(PACKAGE "-" VERSION "\n");
|
|
Packit |
a94d48 |
exit(EXIT_SUCCESS);
|
|
Packit |
a94d48 |
case 'h':
|
|
Packit |
a94d48 |
default:
|
|
Packit |
a94d48 |
fprintf(stderr, "Usage: %s [OPTIONS]\n", progname);
|
|
Packit |
a94d48 |
max = 0;
|
|
Packit |
a94d48 |
for (opt = opts; opt->name; opt++) {
|
|
Packit |
a94d48 |
size = strlen(opt->name);
|
|
Packit |
a94d48 |
if (size > max)
|
|
Packit |
a94d48 |
max = size;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
for (opt = opts, hlp = opts_help;
|
|
Packit |
a94d48 |
opt->name;
|
|
Packit |
a94d48 |
opt++, hlp++) {
|
|
Packit |
a94d48 |
fprintf(stderr, " -%c, --%s",
|
|
Packit |
a94d48 |
opt->val, opt->name);
|
|
Packit |
a94d48 |
size = strlen(opt->name);
|
|
Packit |
a94d48 |
for (; size < max; size++)
|
|
Packit |
a94d48 |
fprintf(stderr, " ");
|
|
Packit |
a94d48 |
fprintf(stderr, " %s\n", *hlp);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
exit(EXIT_FAILURE);
|
|
Packit |
a94d48 |
break;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
*argc -= optind;
|
|
Packit |
a94d48 |
*argv += optind;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
return 0;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
static void
|
|
Packit |
a94d48 |
close_fds(void)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
struct dirent *dent;
|
|
Packit |
a94d48 |
DIR *dirp;
|
|
Packit |
a94d48 |
char *endp;
|
|
Packit |
a94d48 |
long fd;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
if ((dirp = opendir("/proc/self/fd")) != NULL) {
|
|
Packit |
a94d48 |
while ((dent = readdir(dirp)) != NULL) {
|
|
Packit |
a94d48 |
fd = strtol(dent->d_name, &endp, 10);
|
|
Packit |
a94d48 |
if (dent->d_name != endp && *endp == '\0' &&
|
|
Packit |
a94d48 |
fd >= 3 && fd != dirfd(dirp)) {
|
|
Packit |
a94d48 |
close((int) fd);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
closedir(dirp);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
static int
|
|
Packit |
a94d48 |
daemonize(void)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
pid_t pid, sid;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* fork off the parent process */
|
|
Packit |
a94d48 |
pid = fork();
|
|
Packit |
a94d48 |
if (pid < 0) {
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "fork: %s", strerror(errno));
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
/* if we got a good PID, then we can exit the parent process */
|
|
Packit |
a94d48 |
if (pid > 0) {
|
|
Packit |
a94d48 |
exit(EXIT_SUCCESS);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* at this point we are executing as the child process */
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* change the umask to something predictable instead of inheriting */
|
|
Packit |
a94d48 |
/* whatever from the parent */
|
|
Packit |
a94d48 |
umask(0);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* create a new SID for the child process and */
|
|
Packit |
a94d48 |
/* detach the process from the parent (normally a shell) */
|
|
Packit |
a94d48 |
sid = setsid();
|
|
Packit |
a94d48 |
if (sid < 0) {
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "setsid: %s", strerror(errno));
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* Change the current working directory. This prevents the current
|
|
Packit |
a94d48 |
directory from being locked; hence not being able to remove it. */
|
|
Packit |
a94d48 |
if (chdir("/") < 0) {
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "chdir(\"/\"): %s", strerror(errno));
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
return 0;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
static void
|
|
Packit |
a94d48 |
open_log(void)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
int log_opts;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* open the syslog */
|
|
Packit |
a94d48 |
log_opts = LOG_CONS|LOG_NDELAY;
|
|
Packit |
a94d48 |
openlog(PACKAGE, log_opts, LOG_DAEMON);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
static int
|
|
Packit |
a94d48 |
std2null(void)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
int nullfd;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* open /dev/null */
|
|
Packit |
a94d48 |
nullfd = open("/dev/null", O_RDWR);
|
|
Packit |
a94d48 |
if (nullfd < 0) {
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "can't open /dev/null: %s", strerror(errno));
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* set up stdin, stdout, stderr to /dev/null */
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* don't redirect stdin if we're being sent a socket by systemd */
|
|
Packit |
a94d48 |
if (!is_socket(STDIN_FILENO) &&
|
|
Packit |
a94d48 |
dup2(nullfd, STDIN_FILENO) != STDIN_FILENO) {
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "dup2() stdin: %s", strerror(errno));
|
|
Packit |
a94d48 |
close(nullfd);
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
if (!log_to_stderr && dup2(nullfd, STDOUT_FILENO) != STDOUT_FILENO) {
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "dup2() stdout: %s", strerror(errno));
|
|
Packit |
a94d48 |
close(nullfd);
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
if (!log_to_stderr && dup2(nullfd, STDERR_FILENO) != STDERR_FILENO) {
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "dup2() stderr: %s", strerror(errno));
|
|
Packit |
a94d48 |
close(nullfd);
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
close(nullfd);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
return 0;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
static int
|
|
Packit |
a94d48 |
create_pidfile(void)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
int fd;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* JIC */
|
|
Packit |
a94d48 |
unlink(pidfile);
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* open the pidfile */
|
|
Packit |
a94d48 |
fd = open(pidfile, O_WRONLY|O_CREAT|O_EXCL, 0644);
|
|
Packit |
a94d48 |
if (fd >= 0) {
|
|
Packit |
a94d48 |
FILE *f;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* write our pid to it */
|
|
Packit |
a94d48 |
f = fdopen(fd, "w");
|
|
Packit |
a94d48 |
if (f != NULL) {
|
|
Packit |
a94d48 |
fprintf(f, "%d\n", getpid());
|
|
Packit |
a94d48 |
fclose(f);
|
|
Packit |
a94d48 |
/* leave the fd open */
|
|
Packit |
a94d48 |
return 0;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
close(fd);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* something went wrong */
|
|
Packit |
a94d48 |
acpid_log(LOG_ERR, "can't create pidfile %s: %s",
|
|
Packit |
a94d48 |
pidfile, strerror(errno));
|
|
Packit |
a94d48 |
return -1;
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
void
|
|
Packit |
a94d48 |
clean_exit_with_status(int status)
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
acpid_cleanup_rules(1);
|
|
Packit |
a94d48 |
delete_all_connections();
|
|
Packit |
a94d48 |
acpid_log(LOG_NOTICE, "exiting");
|
|
Packit |
a94d48 |
unlink(pidfile);
|
|
Packit |
a94d48 |
exit(status);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
static void
|
|
Packit |
a94d48 |
clean_exit(int sig __attribute__((unused)))
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
clean_exit_with_status(EXIT_SUCCESS);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
static void
|
|
Packit |
a94d48 |
reload_conf(int sig __attribute__((unused)))
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
acpid_log(LOG_NOTICE, "reloading configuration");
|
|
Packit |
a94d48 |
acpid_cleanup_rules(0);
|
|
Packit |
a94d48 |
acpid_read_conf(confdir);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
int
|
|
Packit |
a94d48 |
locked()
|
|
Packit |
a94d48 |
{
|
|
Packit |
a94d48 |
struct stat trash;
|
|
Packit |
a94d48 |
|
|
Packit |
a94d48 |
/* check for existence of a lockfile */
|
|
Packit |
a94d48 |
return (stat(lockfile, &trash) == 0);
|
|
Packit |
a94d48 |
}
|
|
Packit |
a94d48 |
|