mirror of
https://github.com/openvswitch/ovs
synced 2025-10-23 14:57:06 +00:00
211 lines
5.6 KiB
C
211 lines
5.6 KiB
C
/*
|
|
* Copyright (c) 2008, 2009 Nicira Networks.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#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);
|
|
}
|
|
}
|