summaryrefslogtreecommitdiffstats
path: root/cgrulesengd.c
diff options
context:
space:
mode:
authorJan Safranek <jsafrane@redhat.com>2009-03-13 15:16:19 +0100
committerJan Safranek <jsafrane@redhat.com>2009-03-26 09:34:18 +0100
commitf8e05fc8c129a13fed256b03a23537ef94c77152 (patch)
treec64ea7d9f7daeefd307feec1bcb90ea5e3e6d600 /cgrulesengd.c
parent04bb98f8bd9751dd8a514b0e3a6c4862ceabeae9 (diff)
downloadlibcg-f8e05fc8c129a13fed256b03a23537ef94c77152.tar.gz
libcg-f8e05fc8c129a13fed256b03a23537ef94c77152.tar.xz
libcg-f8e05fc8c129a13fed256b03a23537ef94c77152.zip
Distribute files to various subdirectories
Signed-off-by: Jan Safranek <jsafrane@redhat.com>
Diffstat (limited to 'cgrulesengd.c')
-rw-r--r--cgrulesengd.c793
1 files changed, 0 insertions, 793 deletions
diff --git a/cgrulesengd.c b/cgrulesengd.c
deleted file mode 100644
index 8efdce1..0000000
--- a/cgrulesengd.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * Copyright Red Hat Inc. 2008
- *
- * Author: Steve Olivieri <sjo@redhat.com>
- * Author: Vivek Goyal <vgoyal@redhat.com>
- *
- * Some part of the programs have been derived from Dhaval Giani's posting
- * for daemon to place the task in right container. Original copyright notice
- * follows.
- *
- * Copyright IBM Corporation, 2007
- * Author: Dhaval Giani <dhaval <at> linux.vnet.ibm.com>
- * Derived from test_cn_proc.c by Matt Helsley
- * Original copyright notice follows
- *
- * Copyright (C) Matt Helsley, IBM Corp. 2005
- * Derived from fcctl.c by Guillaume Thouvenin
- * Original copyright notice follows:
- *
- * Copyright (C) 2005 BULL SA.
- * Written by Guillaume Thouvenin <guillaume.thouvenin <at> bull.net>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * TODO Stop using netlink for communication (or at least rewrite that part).
- */
-
-#include "libcgroup.h"
-#include "cgrulesengd.h"
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/syslog.h>
-#include <string.h>
-#include <linux/netlink.h>
-#include <signal.h>
-#include <time.h>
-#include <syslog.h>
-#include <getopt.h>
-
-#include <sys/stat.h>
-#include <unistd.h>
-#include <linux/connector.h>
-#include <linux/cn_proc.h>
-
-/* Log file, NULL if logging to file is disabled */
-FILE* logfile;
-
-/* Log facility, 0 if logging to syslog is disabled */
-int logfacility;
-
-/* Current log level */
-int loglevel;
-
-/**
- * Prints the usage information for this program and, optionally, an error
- * message. This function uses vfprintf.
- * @param fd The file stream to print to
- * @param msg The error message to print (printf style)
- * @param ... Any args to msg (printf style)
- */
-void usage(FILE* fd, const char* msg, ...)
-{
- /* List of args to msg */
- va_list ap;
-
- /* Put all args after msg into the list. */
- va_start(ap, msg);
-
- if (msg)
- vfprintf(fd, msg, ap);
- fprintf(fd, "\n");
- fprintf(fd, "cgrulesengd -- a daemon for the cgroups rules engine\n\n");
- fprintf(fd, "Usage : cgrulesengd [options]\n\n");
- fprintf(fd, " options :\n");
- fprintf(fd, " -q | --quiet quiet mode\n"
- " -v | --verbose verbose mode\n"
- " -f <path> | --logfile=<path> write log to file\n"
- " -s[facility] | --syslog=[facility] write log to syslog\n"
- " -n | --nodaemom don't fork daemon\n"
- " -d | --debug same as -v -v -n -f -\n"
- " -Q | --nolog disable logging\n"
- " -h | --help show this help\n\n"
- );
- va_end(ap);
-}
-
-/**
- * Prints a formatted message (like printf()) to all log destinations.
- * Flushes the file stream's buffer so that the message is immediately
- * readable.
- * @param level The log level (LOG_EMERG ... LOG_DEBUG)
- * @param format The format for the message (printf style)
- * @param ... Any args to format (printf style)
- */
-void flog(int level, const char *format, ...)
-{
- /* List of args to format */
- va_list ap;
-
- /* Check the log level */
- if (level > loglevel)
- return;
-
- if (logfile) {
- /* Print the message to the given stream. */
- va_start(ap, format);
- vfprintf(logfile, format, ap);
- va_end(ap);
- fprintf(logfile, "\n");
-
- /*
- * Flush the stream's buffer, so the data is readable
- * immediately.
- */
- fflush(logfile);
- }
-
- if (logfacility) {
- va_start(ap, format);
- vsyslog(LOG_MAKEPRI(logfacility, level), format, ap);
- va_end(ap);
- }
-}
-
-/**
- * Process an event from the kernel, and determine the correct UID/GID/PID to
- * pass to libcgroup. Then, libcgroup will decide the cgroup to move the PID
- * to, if any.
- * @param ev The event to process
- * @param type The type of event to process (part of ev)
- * @return 0 on success, > 0 on failure
- */
-int cgre_process_event(const struct proc_event *ev, const int type)
-{
- /* Handle for the /proc/PID/status file */
- FILE *f;
-
- /* Path for /proc/PID/status file */
- char path[FILENAME_MAX];
-
- /* Temporary buffer */
- char *buf = NULL;
-
- /* UID data */
- uid_t ruid, euid, suid, fsuid, log_uid = 0;
-
- /* GID data */
- gid_t rgid, egid, sgid, fsgid, log_gid = 0;
-
- /* PID, just for logging */
- pid_t log_pid = 0;
-
- /* Return codes */
- int ret = 0;
-
- /*
- * First, we need to open the /proc/PID/status file so that we can
- * get the effective UID and GID for the process that we're working
- * on. This process is probably not us, so we can't just call
- * geteuid() or getegid().
- */
- sprintf(path, "/proc/%d/status", ev->event_data.id.process_pid);
- f = fopen(path, "r");
- if (!f) {
- flog(LOG_WARNING, "Failed to open %s", path);
- goto finished;
- }
-
- /* Now, we need to find either the eUID or the eGID of the process. */
- buf = calloc(4096, sizeof(char));
- if (!buf) {
- flog(LOG_WARNING, "Failed to process event, out of"
- "memory? Error: %s",
- strerror(errno));
- ret = errno;
- fclose(f);
- goto finished;
- }
- switch (type) {
- case PROC_EVENT_UID:
- /* Have the eUID, need to find the eGID. */
- while (fgets(buf, 4096, f)) {
- if (!strncmp(buf, "Gid:", 4)) {
- sscanf((buf + 5), "%d%d%d%d", &rgid, &egid,
- &sgid, &fsgid);
- break;
- }
- memset(buf, '\0', 4096);
- }
- break;
- case PROC_EVENT_GID:
- /* Have the eGID, need to find the eUID. */
- while (fgets(buf, 4096, f)) {
- if (!strncmp(buf, "Uid:", 4)) {
- sscanf((buf + 5), "%d%d%d%d", &ruid, &euid,
- &suid, &fsuid);
- break;
- }
- memset(buf, '\0', 4096);
- }
- break;
- default:
- flog(LOG_WARNING, "For some reason, we're processing a"
- " non-UID/GID event. Something is wrong!");
- break;
- }
- free(buf);
- fclose(f);
-
- /*
- * Now that we have the UID, the GID, and the PID, we can make a call
- * to libcgroup to change the cgroup for this PID.
- */
- switch (type) {
- case PROC_EVENT_UID:
- log_uid = ev->event_data.id.e.euid;
- log_gid = egid;
- log_pid = ev->event_data.id.process_pid;
- ret = cgroup_change_cgroup_uid_gid_flags(
- ev->event_data.id.e.euid,
- egid, ev->event_data.id.process_pid,
- CGFLAG_USECACHE);
- break;
- case PROC_EVENT_GID:
- log_uid = euid;
- log_gid = ev->event_data.id.e.egid;
- log_pid = ev->event_data.id.process_pid;
- ret = cgroup_change_cgroup_uid_gid_flags(euid,
- ev->event_data.id.e.egid,
- ev->event_data.id.process_pid,
- CGFLAG_USECACHE);
- break;
- default:
- break;
- }
-
- if (ret) {
- /*
- * TODO: add some supression, do not spam log when every group
- * change fails
- */
- flog(LOG_WARNING, "Cgroup change for PID: %d, UID: %d, GID: %d"
- " FAILED! (Error Code: %d)", log_pid, log_uid, log_gid,
- ret);
- } else {
- flog(LOG_INFO, "Cgroup change for PID: %d, UID: %d, GID: %d OK",
- log_pid, log_uid, log_gid);
- }
-
-finished:
- return ret;
-}
-
-/**
- * Handle a netlink message. In the event of PROC_EVENT_UID or PROC_EVENT_GID,
- * we pass the event along to cgre_process_event for further processing. All
- * other events are ignored.
- * @param cn_hdr The netlink message
- * @return 0 on success, > 0 on error
- */
-int cgre_handle_msg(struct cn_msg *cn_hdr)
-{
- /* The event to consider */
- struct proc_event *ev;
-
- /* Return codes */
- int ret = 0;
-
- /* Get the event data. We only care about two event types. */
- ev = (struct proc_event*)cn_hdr->data;
- switch (ev->what) {
- case PROC_EVENT_UID:
- flog(LOG_DEBUG, "UID Event: PID = %d, tGID = %d, rUID = %d,"
- " eUID = %d", ev->event_data.id.process_pid,
- ev->event_data.id.process_tgid,
- ev->event_data.id.r.ruid,
- ev->event_data.id.e.euid);
- ret = cgre_process_event(ev, PROC_EVENT_UID);
- break;
- case PROC_EVENT_GID:
- flog(LOG_DEBUG, "GID Event: PID = %d, tGID = %d, rGID = %d,"
- " eGID = %d", ev->event_data.id.process_pid,
- ev->event_data.id.process_tgid,
- ev->event_data.id.r.rgid,
- ev->event_data.id.e.egid);
- ret = cgre_process_event(ev, PROC_EVENT_GID);
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-int cgre_create_netlink_socket_process_msg()
-{
- int sk_nl;
- int err;
- struct sockaddr_nl my_nla, kern_nla, from_nla;
- socklen_t from_nla_len;
- char buff[BUFF_SIZE];
- int rc = -1;
- struct nlmsghdr *nl_hdr;
- struct cn_msg *cn_hdr;
- enum proc_cn_mcast_op *mcop_msg;
- size_t recv_len = 0;
-
- /*
- * Create an endpoint for communication. Use the kernel user
- * interface device (PF_NETLINK) which is a datagram oriented
- * service (SOCK_DGRAM). The protocol used is the connector
- * protocol (NETLINK_CONNECTOR)
- */
- sk_nl = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
- if (sk_nl == -1) {
- cgroup_dbg("socket sk_nl error");
- return rc;
- }
-
- my_nla.nl_family = AF_NETLINK;
- my_nla.nl_groups = CN_IDX_PROC;
- my_nla.nl_pid = getpid();
- my_nla.nl_pad = 0;
-
- kern_nla.nl_family = AF_NETLINK;
- kern_nla.nl_groups = CN_IDX_PROC;
- kern_nla.nl_pid = 1;
- kern_nla.nl_pad = 0;
-
- err = bind(sk_nl, (struct sockaddr *)&my_nla, sizeof(my_nla));
- if (err == -1) {
- cgroup_dbg("binding sk_nl error");
- goto close_and_exit;
- }
-
- nl_hdr = (struct nlmsghdr *)buff;
- cn_hdr = (struct cn_msg *)NLMSG_DATA(nl_hdr);
- mcop_msg = (enum proc_cn_mcast_op*)&cn_hdr->data[0];
- cgroup_dbg("sending proc connector: PROC_CN_MCAST_LISTEN... ");
- memset(buff, 0, sizeof(buff));
- *mcop_msg = PROC_CN_MCAST_LISTEN;
-
- /* fill the netlink header */
- nl_hdr->nlmsg_len = SEND_MESSAGE_LEN;
- nl_hdr->nlmsg_type = NLMSG_DONE;
- nl_hdr->nlmsg_flags = 0;
- nl_hdr->nlmsg_seq = 0;
- nl_hdr->nlmsg_pid = getpid();
-
- /* fill the connector header */
- cn_hdr->id.idx = CN_IDX_PROC;
- cn_hdr->id.val = CN_VAL_PROC;
- cn_hdr->seq = 0;
- cn_hdr->ack = 0;
- cn_hdr->len = sizeof(enum proc_cn_mcast_op);
- cgroup_dbg("sending netlink message len=%d, cn_msg len=%d\n",
- nl_hdr->nlmsg_len, (int) sizeof(struct cn_msg));
- if (send(sk_nl, nl_hdr, nl_hdr->nlmsg_len, 0) != nl_hdr->nlmsg_len) {
- cgroup_dbg("failed to send proc connector mcast ctl op!\n");
- goto close_and_exit;
- }
- cgroup_dbg("sent\n");
-
- for(memset(buff, 0, sizeof(buff)), from_nla_len = sizeof(from_nla);
- ; memset(buff, 0, sizeof(buff)), from_nla_len = sizeof(from_nla)) {
- struct nlmsghdr *nlh = (struct nlmsghdr*)buff;
- memcpy(&from_nla, &kern_nla, sizeof(from_nla));
- recv_len = recvfrom(sk_nl, buff, BUFF_SIZE, 0,
- (struct sockaddr*)&from_nla, &from_nla_len);
- if (recv_len == ENOBUFS) {
- flog(LOG_ERR, "ERROR: NETLINK BUFFER FULL, MESSAGE "
- "DROPPED!");
- continue;
- }
- if (recv_len < 1)
- continue;
- while (NLMSG_OK(nlh, recv_len)) {
- cn_hdr = NLMSG_DATA(nlh);
- if (nlh->nlmsg_type == NLMSG_NOOP)
- continue;
- if ((nlh->nlmsg_type == NLMSG_ERROR) ||
- (nlh->nlmsg_type == NLMSG_OVERRUN))
- break;
- if(cgre_handle_msg(cn_hdr) < 0) {
- goto close_and_exit;
- }
- if (nlh->nlmsg_type == NLMSG_DONE)
- break;
- nlh = NLMSG_NEXT(nlh, recv_len);
- }
- }
-
-close_and_exit:
- close(sk_nl);
- return rc;
-}
-
-/**
- * Start logging. Opens syslog and/or log file and sets log level.
- * @param logp Path of the log file, NULL if no log file was specified
- * @param logf Syslog facility, NULL if no facility was specified
- * @param logv Log verbosity, 2 is the default, 0 = no logging, 4 = everything
- */
-static void cgre_start_log(const char *logp, int logf, int logv)
-{
- /* Current system time */
- time_t tm;
-
- /* Log levels */
- int loglevels[] = {
- LOG_EMERG, /* -qq */
- LOG_ERR, /* -q */
- LOG_NOTICE, /* default */
- LOG_INFO, /* -v */
- LOG_DEBUG /* -vv */
- };
-
- /* Set default logging destination if nothing was specified */
- if (!logp && !logf)
- logf = LOG_DAEMON;
-
- /* Open log file */
- if (logp) {
- if (strcmp("-", logp) == 0) {
- logfile = stdout;
- } else {
- logfile = fopen(logp, "a");
- if (!logfile) {
- fprintf(stderr, "Failed to open log file %s,"
- " error: %s. Continuing anyway.\n",
- logp, strerror(errno));
- logfile = stdout;
- }
- }
- } else
- logfile = NULL;
-
- /* Open syslog */
- if (logf) {
- openlog("CGRE", LOG_CONS | LOG_PID, logf);
- logfacility = logf;
- } else
- logfacility = 0;
-
- /* Set the log level */
- if (logv < 0)
- logv = 0;
- if (logv >= sizeof(loglevels)/sizeof(int))
- logv = sizeof(loglevels)/sizeof(int)-1;
-
- loglevel = loglevels[logv];
-
- flog(LOG_DEBUG, "CGroup Rules Engine Daemon log started");
- tm = time(0);
- flog(LOG_DEBUG, "Current time: %s", ctime(&tm));
- flog(LOG_DEBUG, "Opened log file: %s, log facility: %d, log level: %d",
- logp, logfacility, loglevel);
-}
-
-
-/**
- * Turns this program into a daemon. In doing so, we fork() and kill the
- * parent process. Note too that stdout, stdin, and stderr are closed in
- * daemon mode, and a file descriptor for a log file is opened.
- * @param logp Path of the log file, NULL if no log file was specified
- * @param logf Syslog facility, 0 if no facility was specified
- * @param daemon False to turn off daemon mode (no fork, leave FDs open)
- * @param logv Log verbosity, 2 is the default, 0 = no logging, 5 = everything
- * @return 0 on success, > 0 on error
- */
-int cgre_start_daemon(const char *logp, const int logf,
- const unsigned char daemon, const int logv)
-{
- /* PID returned from the fork() */
- pid_t pid;
-
- /* Fork and die. */
- if (daemon) {
- pid = fork();
- if (pid < 0) {
- openlog("CGRE", LOG_CONS, LOG_DAEMON|LOG_WARNING);
- syslog(LOG_DAEMON|LOG_WARNING, "Failed to fork,"
- " error: %s", strerror(errno));
- closelog();
- fprintf(stderr, "Failed to fork(), %s\n",
- strerror(errno));
- return 1;
- } else if (pid > 0) {
- exit(EXIT_SUCCESS);
- }
-
- /* Change the file mode mask. */
- umask(0);
- } else {
- cgroup_dbg("Not using daemon mode.\n");
- pid = getpid();
- }
-
- cgre_start_log(logp, logf, logv);
-
- if (!daemon) {
- /* We can skip the rest, since we're not becoming a daemon. */
- flog(LOG_INFO, "Proceeding with PID %d", getpid());
- return 0;
- } else {
- /* Get a new SID for the child. */
- if (setsid() < 0) {
- flog(LOG_ERR, "Failed to get a new SID, error: %s",
- strerror(errno));
- return 2;
- }
-
- /* Change to the root directory. */
- if (chdir("/") < 0) {
- flog(LOG_ERR, "Failed to chdir to /, error: %s",
- strerror(errno));
- return 3;
- }
-
- /* Close standard file descriptors. */
- close(STDIN_FILENO);
- if (logfile != stdout)
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
- }
-
- /* If we make it this far, we're a real daemon! Or we chose not to. */
- flog(LOG_INFO, "Proceeding with PID %d", getpid());
- return 0;
-}
-
-/**
- * Catch the SIGUSR2 signal and reload the rules configuration. This function
- * makes use of the logfile and flog() to print the new rules.
- * @param signum The signal that we caught (always SIGUSR2)
- */
-void cgre_flash_rules(int signum)
-{
- /* Current time */
- time_t tm = time(0);
-
- flog(LOG_NOTICE, "Reloading rules configuration.");
- flog(LOG_DEBUG, "Current time: %s", ctime(&tm));
-
- /* Ask libcgroup to reload the rules table. */
- cgroup_reload_cached_rules();
-
- /* Print the results of the new table to our log file. */
- if (logfile && loglevel >= LOG_INFO) {
- cgroup_print_rules_config(logfile);
- fprintf(logfile, "\n");
- }
-}
-
-/**
- * Catch the SIGTERM and SIGINT signals so that we can exit gracefully. Before
- * exiting, this function makes use of the logfile and flog().
- * @param signum The signal that we caught (SIGTERM, SIGINT)
- */
-void cgre_catch_term(int signum)
-{
- /* Current time */
- time_t tm = time(0);
-
- flog(LOG_NOTICE, "Stopped CGroup Rules Engine Daemon at %s",
- ctime(&tm));
-
- /* Close the log file, if we opened one */
- if (logfile && logfile != stdout)
- fclose(logfile);
-
- /* Close syslog */
- if (logfacility)
- closelog();
-
- exit(EXIT_SUCCESS);
-}
-
-/**
- * Parse the syslog facility as received on command line.
- * @param arg Command line argument with the syslog facility
- * @return the syslog facility (e.g. LOG_DAEMON) or 0 on error
- */
-static int cgre_parse_syslog_facility(const char *arg)
-{
- if (arg == NULL)
- return 0;
-
- if (strlen(arg) > 1)
- return 0;
-
- switch (arg[0]) {
- case '0':
- return LOG_LOCAL0;
- case '1':
- return LOG_LOCAL1;
- case '2':
- return LOG_LOCAL2;
- case '3':
- return LOG_LOCAL3;
- case '4':
- return LOG_LOCAL4;
- case '5':
- return LOG_LOCAL5;
- case '6':
- return LOG_LOCAL6;
- case '7':
- return LOG_LOCAL7;
- case 'D':
- return LOG_DAEMON;
- default:
- return 0;
- }
-}
-
-int main(int argc, char *argv[])
-{
- /* Patch to the log file */
- const char *logp = NULL;
-
- /* Syslog facility */
- int facility = 0;
-
- /* Verbose level */
- int verbosity = 2;
-
- /* For catching signals */
- struct sigaction sa;
-
- /* Should we daemonize? */
- unsigned char daemon = 1;
-
- /* Return codes */
- int ret = 0;
-
- /* Command line arguments */
- const char *short_options = "hvqf:s::ndQ";
- struct option long_options[] = {
- {"help", no_argument, NULL, 'h'},
- {"verbose", no_argument, NULL, 'v'},
- {"quiet", no_argument, NULL, 'q'},
- {"logfile", required_argument, NULL, 'f'},
- {"syslog", optional_argument, NULL, 's'},
- {"nodaemon", no_argument, NULL, 'n'},
- {"debug", no_argument, NULL, 'd'},
- {"nolog", no_argument, NULL, 'Q'},
- {NULL, 0, NULL, 0}
- };
-
- /* Make sure the user is root. */
- if (getuid() != 0) {
- fprintf(stderr, "Error: Only root can start/stop the control"
- " group rules engine daemon\n");
- ret = 1;
- goto finished;
- }
-
- while (1) {
- int c;
-
- c = getopt_long(argc, argv, short_options, long_options, NULL);
- if (c == -1)
- break;
-
- switch (c) {
- case 'h': /* --help */
- usage(stdout, "Help:\n");
- ret = 0;
- goto finished;
-
- case 'v': /* --verbose */
- verbosity++;
- break;
-
- case 'q': /* --quiet */
- verbosity--;
- break;
-
- case 'Q': /* --nolog */
- verbosity = 0;
- break;
-
- case 'f': /* --logfile=<filename> */
- logp = optarg;
- break;
-
- case 's': /* --syslog=[facility] */
- if (optarg) {
- facility = cgre_parse_syslog_facility(optarg);
- if (facility == 0) {
- fprintf(stderr,
- "Unknown syslog facility: %s\n",
- optarg);
- ret = 2;
- goto finished;
- }
- } else {
- facility = LOG_DAEMON;
- }
- break;
-
- case 'n': /* --no-fork */
- daemon = 0;
- break;
-
- case 'd': /* --debug */
- /* same as -vvn */
- daemon = 0;
- verbosity = 4;
- logp = "-";
- break;
-
- default:
- usage(stderr, "");
- ret = 2;
- goto finished;
- }
- }
-
- /* Initialize libcgroup. */
- if ((ret = cgroup_init()) != 0) {
- fprintf(stderr, "Error: libcgroup initialization failed, %d\n",
- ret);
- goto finished;
- }
-
- /* Ask libcgroup to load the configuration rules. */
- if ((ret = cgroup_init_rules_cache()) != 0) {
- fprintf(stderr, "Error: libcgroup failed to initialize rules"
- "cache, %d\n", ret);
- goto finished;
- }
-
- /* Now, start the daemon. */
- ret = cgre_start_daemon(logp, facility, daemon, verbosity);
- if (ret < 0) {
- fprintf(stderr, "Error: Failed to launch the daemon, %d\n",
- ret);
- goto finished;
- }
-
- /*
- * Set up the signal handler to reload the cached rules upon reception
- * of a SIGUSR2 signal.
- */
- sa.sa_handler = &cgre_flash_rules;
- sa.sa_flags = 0;
- sa.sa_restorer = NULL;
- sigemptyset(&sa.sa_mask);
- if ((ret = sigaction(SIGUSR2, &sa, NULL))) {
- flog(LOG_ERR, "Failed to set up signal handler for SIGUSR2."
- " Error: %s", strerror(errno));
- goto finished;
- }
-
- /*
- * Set up the signal handler to catch SIGINT and SIGTERM so that we
- * can exit gracefully.
- */
- sa.sa_handler = &cgre_catch_term;
- ret = sigaction(SIGINT, &sa, NULL);
- ret |= sigaction(SIGTERM, &sa, NULL);
- if (ret) {
- flog(LOG_ERR, "Failed to set up the signal handler. Error:"
- " %s", strerror(errno));
- goto finished;
- }
-
- /* Print the configuration to the log file, or stdout. */
- if (logfile && loglevel >= LOG_INFO)
- cgroup_print_rules_config(logfile);
-
- flog(LOG_NOTICE, "Started the CGroup Rules Engine Daemon.");
-
- /* We loop endlesly in this function, unless we encounter an error. */
- ret = cgre_create_netlink_socket_process_msg();
-
-finished:
- if (logfile && logfile != stdout)
- fclose(logfile);
-
- return ret;
-}