Update primary code license to Apache 2.0.
[cascardo/ovs.git] / utilities / ovs-kill.c
1 /*
2  * Copyright (c) 2008, 2009 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     time_init();
50     vlog_init();
51     parse_options(argc, argv);
52
53     argc -= optind;
54     argv += optind;
55     if (argc < 1) {
56         if (!force) {
57             ovs_fatal(0, "need at least one non-option argument; "
58                       "use --help for usage");
59         }
60     }
61
62     for (i = 0; i < argc; i++) {
63         char *pidfile;
64         pid_t pid;
65
66         pidfile = make_pidfile_name(argv[i]);
67         pid = read_pidfile(pidfile);
68         if (pid >= 0) {
69             if (kill(pid, sig_nr) < 0) {
70                 cond_error(errno, "%s: kill(%ld)", pidfile, (long int) pid);
71             }
72         } else {
73             cond_error(-pid, "could not read %s", pidfile);
74         }
75         free(pidfile);
76     }
77
78     return ok || force ? EXIT_SUCCESS : EXIT_FAILURE;
79 }
80
81 static void
82 parse_options(int argc, char *argv[])
83 {
84     static struct option long_options[] = {
85         {"signal",      required_argument, 0, 's'},
86         {"force",       no_argument, 0, 'f'},
87         {"help",        no_argument, 0, 'h'},
88         {"version",     no_argument, 0, 'V'},
89         {0, 0, 0, 0},
90     };
91     char *short_options = long_options_to_short_options(long_options);
92
93     for (;;) {
94         int c;
95
96         c = getopt_long(argc, argv, short_options, long_options, NULL);
97         if (c == -1) {
98             break;
99         }
100
101         switch (c) {
102         case 's':
103             if (atoi(optarg) || !strcmp(optarg, "0")) {
104                 sig_nr = atoi(optarg);
105             } else {
106                 struct signal_name {
107                     const char *name;
108                     int number;
109                 };
110
111                 static const struct signal_name signals[] = {
112 #define SIGNAL(NAME) { #NAME, NAME }
113                     SIGNAL(SIGABRT),
114                     SIGNAL(SIGALRM),
115                     SIGNAL(SIGBUS),
116                     SIGNAL(SIGCHLD),
117                     SIGNAL(SIGCONT),
118                     SIGNAL(SIGFPE),
119                     SIGNAL(SIGHUP),
120                     SIGNAL(SIGILL),
121                     SIGNAL(SIGINT),
122                     SIGNAL(SIGKILL),
123                     SIGNAL(SIGPIPE),
124                     SIGNAL(SIGQUIT),
125                     SIGNAL(SIGSEGV),
126                     SIGNAL(SIGSTOP),
127                     SIGNAL(SIGTERM),
128                     SIGNAL(SIGTSTP),
129                     SIGNAL(SIGTTIN),
130                     SIGNAL(SIGTTOU),
131                     SIGNAL(SIGUSR1),
132                     SIGNAL(SIGUSR2),
133 #ifdef SIGPOLL
134                     SIGNAL(SIGPOLL),
135 #endif
136                     SIGNAL(SIGPROF),
137                     SIGNAL(SIGSYS),
138                     SIGNAL(SIGTRAP),
139                     SIGNAL(SIGURG),
140                     SIGNAL(SIGVTALRM),
141                     SIGNAL(SIGXCPU),
142                     SIGNAL(SIGXFSZ),
143 #undef SIGNAL
144                 };
145                 int i;
146
147                 for (i = 0; i < ARRAY_SIZE(signals); i++) {
148                     const struct signal_name *s = &signals[i];
149                     if (!strcmp(optarg, s->name)
150                         || !strcmp(optarg, s->name + 3)) {
151                         sig_nr = s->number;
152                         goto got_name;
153                     }
154                 }
155                 ovs_fatal(0, "unknown signal \"%s\"", optarg);
156             got_name: ;
157             }
158             break;
159
160         case 'f':
161             force = true;
162             break;
163
164         case 'h':
165             usage();
166
167         case 'V':
168             OVS_PRINT_VERSION(0, 0);
169             exit(EXIT_SUCCESS);
170
171         case '?':
172             exit(EXIT_FAILURE);
173
174         default:
175             abort();
176         }
177     }
178     free(short_options);
179 }
180
181 static void
182 usage(void)
183 {
184     printf("%s: kills a program using a pidfile\n"
185            "usage: %s [OPTIONS] PIDFILE [PIDFILE...]\n"
186            "where PIDFILE is a pidfile created by an Open vSwitch daemon.\n"
187            "\nOptions:\n"
188            "  -s, --signal=NUMBER|NAME  signal to send (default: TERM)\n"
189            "  -f, --force             ignore errors\n"
190            "  -h, --help              display this help message\n"
191            "  -V, --version           display version information\n",
192            program_name, program_name);
193     exit(EXIT_SUCCESS);
194 }
195
196 static void
197 cond_error(int err_no, const char *format, ...)
198 {
199     if (!force) {
200         va_list args;
201
202         fprintf(stderr, "%s: ", program_name);
203         va_start(args, format);
204         vfprintf(stderr, format, args);
205         va_end(args);
206         if (err_no != 0)
207             fprintf(stderr, " (%s)", strerror(err_no));
208         putc('\n', stderr);
209     }
210 }