cf634372d74d12316b619a612abf74c7c7a46002
[sliver-openvswitch.git] / utilities / ovs-kill.c
1 /*
2  * Copyright (c) 2008, 2009, 2010 Nicira Networks.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <getopt.h>
21 #include <signal.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "command-line.h"
26 #include "daemon.h"
27 #include "timeval.h"
28 #include "util.h"
29 #include "vlog.h"
30
31 /* -s, --signal: signal to send. */
32 static int sig_nr = SIGTERM;
33
34 /* -f, --force: ignore errors. */
35 static bool force;
36
37 static void cond_error(int err_no, const char *, ...) PRINTF_FORMAT(2, 3);
38
39 static void parse_options(int argc, char *argv[]);
40 static void usage(void);
41
42 int
43 main(int argc, char *argv[])
44 {
45     bool ok = true;
46     int i;
47
48     set_program_name(argv[0]);
49     vlog_init();
50     parse_options(argc, argv);
51
52     argc -= optind;
53     argv += optind;
54     if (argc < 1) {
55         if (!force) {
56             ovs_fatal(0, "need at least one non-option argument; "
57                       "use --help for usage");
58         }
59     }
60
61     for (i = 0; i < argc; i++) {
62         char *pidfile;
63         pid_t pid;
64
65         pidfile = make_pidfile_name(argv[i]);
66         pid = read_pidfile(pidfile);
67         if (pid >= 0) {
68             if (kill(pid, sig_nr) < 0) {
69                 cond_error(errno, "%s: kill(%ld)", pidfile, (long int) pid);
70             }
71         } else {
72             cond_error(-pid, "could not read %s", pidfile);
73         }
74         free(pidfile);
75     }
76
77     return ok || force ? EXIT_SUCCESS : EXIT_FAILURE;
78 }
79
80 static void
81 parse_options(int argc, char *argv[])
82 {
83     static struct option long_options[] = {
84         {"signal",      required_argument, 0, 's'},
85         {"force",       no_argument, 0, 'f'},
86         {"help",        no_argument, 0, 'h'},
87         {"version",     no_argument, 0, 'V'},
88         {0, 0, 0, 0},
89     };
90     char *short_options = long_options_to_short_options(long_options);
91
92     for (;;) {
93         int c;
94
95         c = getopt_long(argc, argv, short_options, long_options, NULL);
96         if (c == -1) {
97             break;
98         }
99
100         switch (c) {
101         case 's':
102             if (atoi(optarg) || !strcmp(optarg, "0")) {
103                 sig_nr = atoi(optarg);
104             } else {
105                 struct signal_name {
106                     const char *name;
107                     int number;
108                 };
109
110                 static const struct signal_name signals[] = {
111 #define SIGNAL(NAME) { #NAME, NAME }
112                     SIGNAL(SIGABRT),
113                     SIGNAL(SIGALRM),
114                     SIGNAL(SIGBUS),
115                     SIGNAL(SIGCHLD),
116                     SIGNAL(SIGCONT),
117                     SIGNAL(SIGFPE),
118                     SIGNAL(SIGHUP),
119                     SIGNAL(SIGILL),
120                     SIGNAL(SIGINT),
121                     SIGNAL(SIGKILL),
122                     SIGNAL(SIGPIPE),
123                     SIGNAL(SIGQUIT),
124                     SIGNAL(SIGSEGV),
125                     SIGNAL(SIGSTOP),
126                     SIGNAL(SIGTERM),
127                     SIGNAL(SIGTSTP),
128                     SIGNAL(SIGTTIN),
129                     SIGNAL(SIGTTOU),
130                     SIGNAL(SIGUSR1),
131                     SIGNAL(SIGUSR2),
132 #ifdef SIGPOLL
133                     SIGNAL(SIGPOLL),
134 #endif
135                     SIGNAL(SIGPROF),
136                     SIGNAL(SIGSYS),
137                     SIGNAL(SIGTRAP),
138                     SIGNAL(SIGURG),
139                     SIGNAL(SIGVTALRM),
140                     SIGNAL(SIGXCPU),
141                     SIGNAL(SIGXFSZ),
142 #undef SIGNAL
143                 };
144                 int i;
145
146                 for (i = 0; i < ARRAY_SIZE(signals); i++) {
147                     const struct signal_name *s = &signals[i];
148                     if (!strcmp(optarg, s->name)
149                         || !strcmp(optarg, s->name + 3)) {
150                         sig_nr = s->number;
151                         goto got_name;
152                     }
153                 }
154                 ovs_fatal(0, "unknown signal \"%s\"", optarg);
155             got_name: ;
156             }
157             break;
158
159         case 'f':
160             force = true;
161             break;
162
163         case 'h':
164             usage();
165
166         case 'V':
167             OVS_PRINT_VERSION(0, 0);
168             exit(EXIT_SUCCESS);
169
170         case '?':
171             exit(EXIT_FAILURE);
172
173         default:
174             abort();
175         }
176     }
177     free(short_options);
178 }
179
180 static void
181 usage(void)
182 {
183     printf("%s: kills a program using a pidfile\n"
184            "usage: %s [OPTIONS] PIDFILE [PIDFILE...]\n"
185            "where PIDFILE is a pidfile created by an Open vSwitch daemon.\n"
186            "\nOptions:\n"
187            "  -s, --signal=NUMBER|NAME  signal to send (default: TERM)\n"
188            "  -f, --force             ignore errors\n"
189            "  -h, --help              display this help message\n"
190            "  -V, --version           display version information\n",
191            program_name, program_name);
192     exit(EXIT_SUCCESS);
193 }
194
195 static void
196 cond_error(int err_no, const char *format, ...)
197 {
198     if (!force) {
199         va_list args;
200
201         fprintf(stderr, "%s: ", program_name);
202         va_start(args, format);
203         vfprintf(stderr, format, args);
204         va_end(args);
205         if (err_no != 0)
206             fprintf(stderr, " (%s)", strerror(err_no));
207         putc('\n', stderr);
208     }
209 }