Add support for OFPFC_MODIFY Flow Mod command.
[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 "timeval.h"
45 #include "util.h"
46
47 /* -s, --signal: signal to send. */
48 static int sig_nr = SIGTERM;
49
50 /* -f, --force: ignore errors. */
51 static bool force;
52
53 static void cond_error(int err_no, const char *, ...) PRINTF_FORMAT(2, 3);
54 static bool kill_pidfile(const char *pidfile, FILE *);
55
56 static void parse_options(int argc, char *argv[]);
57 static void usage(void);
58
59 int
60 main(int argc, char *argv[])
61 {
62     bool ok = true;
63     int i;
64
65     set_program_name(argv[0]);
66     time_init();
67     parse_options(argc, argv);
68
69     argc -= optind;
70     argv += optind;
71     if (argc < 1) {
72         if (!force) {
73             fatal(0, "need at least one non-option argument; "
74                   "use --help for usage");
75         }
76     }
77
78     for (i = 0; i < argc; i++) {
79         char *pidfile;
80         FILE *file;
81
82         pidfile = make_pidfile_name(argv[i]);
83         file = fopen(pidfile, "r");
84         if (!file) {
85             ok = false;
86             cond_error(errno, "%s: open", pidfile);
87         } else {
88             ok = kill_pidfile(argv[i], file) && ok;
89             fclose(file);
90         }
91         free(pidfile);
92     }
93
94     return ok || force ? EXIT_SUCCESS : EXIT_FAILURE;
95 }
96
97 static bool
98 kill_pidfile(const char *pidfile, FILE *file)
99 {
100     char line[128];
101     struct flock lck;
102
103     lck.l_type = F_WRLCK;
104     lck.l_whence = SEEK_SET;
105     lck.l_start = 0;
106     lck.l_len = 0;
107     if (fcntl(fileno(file), F_GETLK, &lck)) {
108         cond_error(errno, "%s: fcntl", pidfile); 
109         return false;
110     }
111
112     if (!fgets(line, sizeof line, file)) {
113         cond_error(errno, "%s: read", pidfile);
114         return false;
115     }
116
117     if (lck.l_pid != strtoul(line, NULL, 10)) {
118         cond_error(errno, "l_pid (%ld) != %s pid (%s)",
119                    (long int) lck.l_pid, pidfile, line);
120         return false;
121     }
122
123     if (kill(lck.l_pid, sig_nr) < 0) {
124         cond_error(errno, "%s: kill(%ld)", pidfile, (long int) lck.l_pid);
125         return false;
126     }
127
128     return true;
129 }
130
131 static void
132 parse_options(int argc, char *argv[])
133 {
134     static struct option long_options[] = {
135         {"signal",      required_argument, 0, 's'},
136         {"force",       no_argument, 0, 'f'},
137         {"help",        no_argument, 0, 'h'},
138         {"version",     no_argument, 0, 'V'},
139         {0, 0, 0, 0},
140     };
141     char *short_options = long_options_to_short_options(long_options);
142
143     for (;;) {
144         int c;
145
146         c = getopt_long(argc, argv, short_options, long_options, NULL);
147         if (c == -1) {
148             break;
149         }
150
151         switch (c) {
152         case 's':
153             if (atoi(optarg) || !strcmp(optarg, "0")) {
154                 sig_nr = atoi(optarg);
155             } else {
156                 struct signal_name {
157                     const char *name;
158                     int number;
159                 };
160
161                 static const struct signal_name signals[] = {
162 #define SIGNAL(NAME) { #NAME, NAME }
163                     SIGNAL(SIGABRT),
164                     SIGNAL(SIGALRM),
165                     SIGNAL(SIGBUS),
166                     SIGNAL(SIGCHLD),
167                     SIGNAL(SIGCONT),
168                     SIGNAL(SIGFPE),
169                     SIGNAL(SIGHUP),
170                     SIGNAL(SIGILL),
171                     SIGNAL(SIGINT),
172                     SIGNAL(SIGKILL),
173                     SIGNAL(SIGPIPE),
174                     SIGNAL(SIGQUIT),
175                     SIGNAL(SIGSEGV),
176                     SIGNAL(SIGSTOP),
177                     SIGNAL(SIGTERM),
178                     SIGNAL(SIGTSTP),
179                     SIGNAL(SIGTTIN),
180                     SIGNAL(SIGTTOU),
181                     SIGNAL(SIGUSR1),
182                     SIGNAL(SIGUSR2),
183 #ifdef SIGPOLL
184                     SIGNAL(SIGPOLL),
185 #endif
186                     SIGNAL(SIGPROF),
187                     SIGNAL(SIGSYS),
188                     SIGNAL(SIGTRAP),
189                     SIGNAL(SIGURG),
190                     SIGNAL(SIGVTALRM),
191                     SIGNAL(SIGXCPU),
192                     SIGNAL(SIGXFSZ),
193 #undef SIGNAL
194                 };
195                 int i;
196
197                 for (i = 0; i < ARRAY_SIZE(signals); i++) {
198                     const struct signal_name *s = &signals[i];
199                     if (!strcmp(optarg, s->name)
200                         || !strcmp(optarg, s->name + 3)) {
201                         sig_nr = s->number;
202                         goto got_name;
203                     }
204                 }
205                 fatal(0, "unknown signal \"%s\"", optarg);
206             got_name: ;
207             }
208             break;
209
210         case 'f':
211             force = true;
212             break;
213
214         case 'h':
215             usage();
216
217         case 'V':
218             printf("%s "VERSION" compiled "__DATE__" "__TIME__"\n", argv[0]);
219             exit(EXIT_SUCCESS);
220
221         case '?':
222             exit(EXIT_FAILURE);
223
224         default:
225             abort();
226         }
227     }
228     free(short_options);
229 }
230
231 static void
232 usage(void)
233 {
234     printf("%s: kills a program using a pidfile\n"
235            "usage: %s [OPTIONS] PIDFILE [PIDFILE...]\n"
236            "where each PIDFILE is a pidfile created by an OpenFlow daemon.\n"
237            "\nOptions:\n"
238            "  -s, --signal=NUMBER|NAME  signal to send (default: TERM)\n"
239            "  -f, --force             ignore errors\n"
240            "  -h, --help              display this help message\n"
241            "  -V, --version           display version information\n",
242            program_name, program_name);
243     exit(EXIT_SUCCESS);
244 }
245
246 static void
247 cond_error(int err_no, const char *format, ...)
248 {
249     if (!force) {
250         va_list args;
251
252         fprintf(stderr, "%s: ", program_name);
253         va_start(args, format);
254         vfprintf(stderr, format, args);
255         va_end(args);
256         if (err_no != 0)
257             fprintf(stderr, " (%s)", strerror(err_no));
258         putc('\n', stderr);
259     }
260 }