summaryrefslogtreecommitdiff
path: root/utilities/ovs-kill.c
diff options
context:
space:
mode:
Diffstat (limited to 'utilities/ovs-kill.c')
-rw-r--r--utilities/ovs-kill.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/utilities/ovs-kill.c b/utilities/ovs-kill.c
new file mode 100644
index 000000000..f30bf0b94
--- /dev/null
+++ b/utilities/ovs-kill.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2008, 2009 Nicira Networks.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "command-line.h"
+#include "daemon.h"
+#include "timeval.h"
+#include "util.h"
+#include "vlog.h"
+
+/* -s, --signal: signal to send. */
+static int sig_nr = SIGTERM;
+
+/* -f, --force: ignore errors. */
+static bool force;
+
+static void cond_error(int err_no, const char *, ...) PRINTF_FORMAT(2, 3);
+
+static void parse_options(int argc, char *argv[]);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ bool ok = true;
+ int i;
+
+ set_program_name(argv[0]);
+ time_init();
+ vlog_init();
+ parse_options(argc, argv);
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 1) {
+ if (!force) {
+ ovs_fatal(0, "need at least one non-option argument; "
+ "use --help for usage");
+ }
+ }
+
+ for (i = 0; i < argc; i++) {
+ char *pidfile;
+ pid_t pid;
+
+ pidfile = make_pidfile_name(argv[i]);
+ pid = read_pidfile(pidfile);
+ if (pid >= 0) {
+ if (kill(pid, sig_nr) < 0) {
+ cond_error(errno, "%s: kill(%ld)", pidfile, (long int) pid);
+ }
+ } else {
+ cond_error(-pid, "could not read %s", pidfile);
+ }
+ free(pidfile);
+ }
+
+ return ok || force ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+static void
+parse_options(int argc, char *argv[])
+{
+ static struct option long_options[] = {
+ {"signal", required_argument, 0, 's'},
+ {"force", no_argument, 0, 'f'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {0, 0, 0, 0},
+ };
+ char *short_options = long_options_to_short_options(long_options);
+
+ for (;;) {
+ int c;
+
+ c = getopt_long(argc, argv, short_options, long_options, NULL);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 's':
+ if (atoi(optarg) || !strcmp(optarg, "0")) {
+ sig_nr = atoi(optarg);
+ } else {
+ struct signal_name {
+ const char *name;
+ int number;
+ };
+
+ static const struct signal_name signals[] = {
+#define SIGNAL(NAME) { #NAME, NAME }
+ SIGNAL(SIGABRT),
+ SIGNAL(SIGALRM),
+ SIGNAL(SIGBUS),
+ SIGNAL(SIGCHLD),
+ SIGNAL(SIGCONT),
+ SIGNAL(SIGFPE),
+ SIGNAL(SIGHUP),
+ SIGNAL(SIGILL),
+ SIGNAL(SIGINT),
+ SIGNAL(SIGKILL),
+ SIGNAL(SIGPIPE),
+ SIGNAL(SIGQUIT),
+ SIGNAL(SIGSEGV),
+ SIGNAL(SIGSTOP),
+ SIGNAL(SIGTERM),
+ SIGNAL(SIGTSTP),
+ SIGNAL(SIGTTIN),
+ SIGNAL(SIGTTOU),
+ SIGNAL(SIGUSR1),
+ SIGNAL(SIGUSR2),
+#ifdef SIGPOLL
+ SIGNAL(SIGPOLL),
+#endif
+ SIGNAL(SIGPROF),
+ SIGNAL(SIGSYS),
+ SIGNAL(SIGTRAP),
+ SIGNAL(SIGURG),
+ SIGNAL(SIGVTALRM),
+ SIGNAL(SIGXCPU),
+ SIGNAL(SIGXFSZ),
+#undef SIGNAL
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(signals); i++) {
+ const struct signal_name *s = &signals[i];
+ if (!strcmp(optarg, s->name)
+ || !strcmp(optarg, s->name + 3)) {
+ sig_nr = s->number;
+ goto got_name;
+ }
+ }
+ ovs_fatal(0, "unknown signal \"%s\"", optarg);
+ got_name: ;
+ }
+ break;
+
+ case 'f':
+ force = true;
+ break;
+
+ case 'h':
+ usage();
+
+ case 'V':
+ OVS_PRINT_VERSION(0, 0);
+ exit(EXIT_SUCCESS);
+
+ case '?':
+ exit(EXIT_FAILURE);
+
+ default:
+ abort();
+ }
+ }
+ free(short_options);
+}
+
+static void
+usage(void)
+{
+ printf("%s: kills a program using a pidfile\n"
+ "usage: %s [OPTIONS] PIDFILE [PIDFILE...]\n"
+ "where PIDFILE is a pidfile created by an Open vSwitch daemon.\n"
+ "\nOptions:\n"
+ " -s, --signal=NUMBER|NAME signal to send (default: TERM)\n"
+ " -f, --force ignore errors\n"
+ " -h, --help display this help message\n"
+ " -V, --version display version information\n",
+ program_name, program_name);
+ exit(EXIT_SUCCESS);
+}
+
+static void
+cond_error(int err_no, const char *format, ...)
+{
+ if (!force) {
+ va_list args;
+
+ fprintf(stderr, "%s: ", program_name);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ if (err_no != 0)
+ fprintf(stderr, " (%s)", strerror(err_no));
+ putc('\n', stderr);
+ }
+}