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