Enable secchan, ofp-discover to update /etc/resolv.conf.
[sliver-openvswitch.git] / utilities / ofp-kill.c
1 /* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
2  * Junior University
3  *
4  * We are making the OpenFlow specification and associated documentation
5  * (Software) available for public use and benefit with the expectation
6  * that others will use, modify and enhance the Software and contribute
7  * those enhancements back to the community. However, since we would
8  * like to make the Software available for broadest use, with as few
9  * restrictions as possible permission is hereby granted, free of
10  * charge, to any person obtaining a copy of this Software to deal in
11  * the Software under the copyrights without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  * SOFTWARE.
28  *
29  * The name and trademarks of copyright holder(s) may NOT be used in
30  * advertising or publicity pertaining to the Software or any
31  * derivatives without specific, written prior permission.
32  */
33
34 #include <config.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <getopt.h>
38 #include <signal.h>
39 #include <stdarg.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include "command-line.h"
43 #include "daemon.h"
44 #include "util.h"
45
46 /* -s, --signal: signal to send. */
47 static int sig_nr = SIGTERM;
48
49 /* -f, --force: ignore errors. */
50 static bool force;
51
52 static void cond_error(int err_no, const char *, ...) PRINTF_FORMAT(2, 3);
53 static bool kill_pidfile(const char *pidfile, FILE *);
54
55 static void parse_options(int argc, char *argv[]);
56 static void usage(void);
57
58 int
59 main(int argc, char *argv[])
60 {
61     bool ok = true;
62     int i;
63
64     set_program_name(argv[0]);
65     parse_options(argc, argv);
66
67     argc -= optind;
68     argv += optind;
69     if (argc < 1) {
70         if (!force) {
71             fatal(0, "need at least one non-option argument; "
72                   "use --help for usage");
73         }
74     }
75
76     for (i = 0; i < argc; i++) {
77         char *pidfile;
78         FILE *file;
79
80         pidfile = make_pidfile_name(argv[i]);
81         file = fopen(pidfile, "r");
82         if (!file) {
83             ok = false;
84             cond_error(errno, "%s: open", pidfile);
85         } else {
86             ok = kill_pidfile(argv[i], file) && ok;
87             fclose(file);
88         }
89         free(pidfile);
90     }
91
92     return ok || force ? EXIT_SUCCESS : EXIT_FAILURE;
93 }
94
95 static bool
96 kill_pidfile(const char *pidfile, FILE *file)
97 {
98     char line[128];
99     struct flock lck;
100
101     lck.l_type = F_WRLCK;
102     lck.l_whence = SEEK_SET;
103     lck.l_start = 0;
104     lck.l_len = 0;
105     if (fcntl(fileno(file), F_GETLK, &lck)) {
106         cond_error(errno, "%s: fcntl", pidfile); 
107         return false;
108     }
109
110     if (!fgets(line, sizeof line, file)) {
111         cond_error(errno, "%s: read", pidfile);
112         return false;
113     }
114
115     if (lck.l_pid != strtoul(line, NULL, 10)) {
116         cond_error(errno, "l_pid (%ld) != %s pid (%s)",
117                    (long int) lck.l_pid, pidfile, line);
118         return false;
119     }
120
121     if (kill(lck.l_pid, sig_nr) < 0) {
122         cond_error(errno, "%s: kill(%ld)", pidfile, (long int) lck.l_pid);
123         return false;
124     }
125
126     return true;
127 }
128
129 static void
130 parse_options(int argc, char *argv[])
131 {
132     static struct option long_options[] = {
133         {"signal",      required_argument, 0, 's'},
134         {"force",       no_argument, 0, 'f'},
135         {"help",        no_argument, 0, 'h'},
136         {"version",     no_argument, 0, 'V'},
137         {0, 0, 0, 0},
138     };
139     char *short_options = long_options_to_short_options(long_options);
140
141     for (;;) {
142         int c;
143
144         c = getopt_long(argc, argv, short_options, long_options, NULL);
145         if (c == -1) {
146             break;
147         }
148
149         switch (c) {
150         case 's':
151             if (atoi(optarg) || !strcmp(optarg, "0")) {
152                 sig_nr = atoi(optarg);
153             } else {
154                 struct signal_name {
155                     const char *name;
156                     int number;
157                 };
158
159                 static const struct signal_name signals[] = {
160 #define SIGNAL(NAME) { #NAME, NAME }
161                     SIGNAL(SIGABRT),
162                     SIGNAL(SIGALRM),
163                     SIGNAL(SIGBUS),
164                     SIGNAL(SIGCHLD),
165                     SIGNAL(SIGCONT),
166                     SIGNAL(SIGFPE),
167                     SIGNAL(SIGHUP),
168                     SIGNAL(SIGILL),
169                     SIGNAL(SIGINT),
170                     SIGNAL(SIGKILL),
171                     SIGNAL(SIGPIPE),
172                     SIGNAL(SIGQUIT),
173                     SIGNAL(SIGSEGV),
174                     SIGNAL(SIGSTOP),
175                     SIGNAL(SIGTERM),
176                     SIGNAL(SIGTSTP),
177                     SIGNAL(SIGTTIN),
178                     SIGNAL(SIGTTOU),
179                     SIGNAL(SIGUSR1),
180                     SIGNAL(SIGUSR2),
181 #ifdef SIGPOLL
182                     SIGNAL(SIGPOLL),
183 #endif
184                     SIGNAL(SIGPROF),
185                     SIGNAL(SIGSYS),
186                     SIGNAL(SIGTRAP),
187                     SIGNAL(SIGURG),
188                     SIGNAL(SIGVTALRM),
189                     SIGNAL(SIGXCPU),
190                     SIGNAL(SIGXFSZ),
191 #undef SIGNAL
192                 };
193                 int i;
194
195                 for (i = 0; i < ARRAY_SIZE(signals); i++) {
196                     const struct signal_name *s = &signals[i];
197                     if (!strcmp(optarg, s->name)
198                         || !strcmp(optarg, s->name + 3)) {
199                         sig_nr = s->number;
200                         goto got_name;
201                     }
202                 }
203                 fatal(0, "unknown signal \"%s\"", optarg);
204             got_name: ;
205             }
206             break;
207
208         case 'f':
209             force = true;
210             break;
211
212         case 'h':
213             usage();
214
215         case 'V':
216             printf("%s "VERSION" compiled "__DATE__" "__TIME__"\n", argv[0]);
217             exit(EXIT_SUCCESS);
218
219         case '?':
220             exit(EXIT_FAILURE);
221
222         default:
223             abort();
224         }
225     }
226     free(short_options);
227 }
228
229 static void
230 usage(void)
231 {
232     printf("%s: kills a program using a pidfile\n"
233            "usage: %s [OPTIONS] PIDFILE [PIDFILE...]\n"
234            "where each PIDFILE is a pidfile created by an OpenFlow daemon.\n"
235            "\nOptions:\n"
236            "  -s, --signal=NUMBER|NAME  signal to send (default: TERM)\n"
237            "  -f, --force             ignore errors\n"
238            "  -h, --help              display this help message\n"
239            "  -V, --version           display version information\n",
240            program_name, program_name);
241     exit(EXIT_SUCCESS);
242 }
243
244 static void
245 cond_error(int err_no, const char *format, ...)
246 {
247     if (!force) {
248         va_list args;
249
250         fprintf(stderr, "%s: ", program_name);
251         va_start(args, format);
252         vfprintf(stderr, format, args);
253         va_end(args);
254         if (err_no != 0)
255             fprintf(stderr, " (%s)", strerror(err_no));
256         putc('\n', stderr);
257     }
258 }