From 468db9e951d59f64a479233df5c8c8ccae477d3a Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Wed, 18 Jul 2012 12:15:58 +0200 Subject: [PATCH] Daemon: Added a new daemon-control utility --- ucw/daemon.h | 1 + ucw/utils/Makefile | 3 +- ucw/utils/daemon-control.c | 122 +++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 ucw/utils/daemon-control.c diff --git a/ucw/daemon.h b/ucw/daemon.h index 288a05c2..c99f8e08 100644 --- a/ucw/daemon.h +++ b/ucw/daemon.h @@ -89,6 +89,7 @@ enum daemon_control_action { **/ enum daemon_control_status daemon_control(struct daemon_control_params *dc); +// XXX: Also used as exit codes of the daemon-control utility. enum daemon_control_status { DAEMON_STATUS_OK = 0, DAEMON_STATUS_ALREADY_DONE = 100, diff --git a/ucw/utils/Makefile b/ucw/utils/Makefile index 3227bb0a..20de4727 100644 --- a/ucw/utils/Makefile +++ b/ucw/utils/Makefile @@ -1,11 +1,12 @@ # Makefile for the UCW utilities (c) 2008 Michal Vaner -UCW_UTILS=$(addprefix $(o)/ucw/utils/,basecode daemon-helper rotate-log urltool) +UCW_UTILS=$(addprefix $(o)/ucw/utils/,basecode daemon-helper daemon-control rotate-log urltool) PROGS+=$(UCW_UTILS) DIRS+=ucw/utils $(o)/ucw/utils/basecode: $(o)/ucw/utils/basecode.o $(LIBUCW) $(o)/ucw/utils/daemon-helper: $(o)/ucw/utils/daemon-helper.o $(LIBUCW) +$(o)/ucw/utils/daemon-control: $(o)/ucw/utils/daemon-control.o $(LIBUCW) $(o)/ucw/utils/urltool: $(o)/ucw/utils/urltool.o $(LIBUCW) TESTS+=$(o)/ucw/utils/basecode.test diff --git a/ucw/utils/daemon-control.c b/ucw/utils/daemon-control.c new file mode 100644 index 00000000..85fb4501 --- /dev/null +++ b/ucw/utils/daemon-control.c @@ -0,0 +1,122 @@ +/* + * A Simple Utility for Controlling Daemons + * + * (c) 2012 Martin Mares + * + * For more information, see ucw/doc/daemon.txt. + * + * Return codes: + * 100 already done + * 101 not running + * 102 error + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static int action; + +static struct option options[] = { + { "pid-file", required_argument, NULL, 'p' }, + { "guard-file", required_argument, NULL, 'g' }, + { "signal", required_argument, NULL, 's' }, + { "start", no_argument, &action, DAEMON_CONTROL_START }, + { "stop", no_argument, &action, DAEMON_CONTROL_STOP }, + { "check", no_argument, &action, DAEMON_CONTROL_CHECK }, + { "reload", no_argument, &action, DAEMON_CONTROL_SIGNAL }, + { NULL, no_argument, NULL, 0 } +}; + +static void NONRET +usage(void) +{ + fputs("\n\ +Usage: daemon-control --start -- \n\ + or: daemon-control --stop \n\ + or: daemon-control --reload \n\ + or: daemon-control --check \n\ +\n\ +Options:\n\ +--pid-file Name of PID file for this daemon (mandatory)\n\ +--guard-file Name of guard file (default: derived from --pid-file)\n\ +--signal Send a signal of a given name or number\n\ + Default: SIGTERM for --stop, SIGHUP for --reload\n\ +\n\ +Exit codes:\n\ +0 Successfully completed\n\ +1 Invalid arguments\n\ +100 The action was null (e.g., --stop on a stopped daemon)\n\ +101 The daemon was not running (on --reload or --check)\n\ +102 The action has failed (error message was printed to stderr)\n\ +", stderr); + exit(1); +} + +int +main(int argc, char **argv) +{ + int c, sig; + struct daemon_control_params dc = { }; + + while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) + switch (c) + { + case 0: + break; + case 'p': + dc.pid_file = optarg; + break; + case 'g': + dc.guard_file = optarg; + break; + case 's': + sig = sig_name_to_number(optarg); + if (sig < 0) + { + fprintf(stderr, "%s: Unknown signal %s\n", argv[0], optarg); + return 1; + } + dc.signal = sig; + break; + default: + usage(); + } + if (!dc.pid_file || !action) + usage(); + dc.action = action; + + if (action == DAEMON_CONTROL_START) + { + if (optind >= argc) + usage(); + dc.argv = argv + optind; + } + else if (optind < argc) + usage(); + + if (!dc.guard_file) + { + if (!str_has_suffix(dc.pid_file, ".pid")) + { + fprintf(stderr, "%s: For automatic choice of --guard-file, the --pid-file must end with `.pid'\n", argv[0]); + return 1; + } + int len = strlen(dc.pid_file); + char *buf = xmalloc(len + 2); + sprintf(buf, "%.*s.lock", len-4, dc.pid_file); + dc.guard_file = buf; + } + + int err = daemon_control(&dc); + if (err == DAEMON_STATUS_ERROR) + fprintf(stderr, "%s: %s\n", argv[0], dc.error_msg); + return err; +} -- 2.39.2