]>
Commit | Line | Data |
---|---|---|
064af421 | 1 | /* |
65f92a50 | 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 | 15 | */ |
3fbe1d30 | 16 | |
064af421 | 17 | #include <config.h> |
064af421 | 18 | |
064af421 BP |
19 | #include <errno.h> |
20 | #include <getopt.h> | |
064af421 BP |
21 | #include <stdio.h> |
22 | #include <string.h> | |
23 | #include <stdlib.h> | |
24 | ||
25 | #include "command-line.h" | |
3fbe1d30 BP |
26 | #include "daemon.h" |
27 | #include "dirs.h" | |
28 | #include "dynamic-string.h" | |
064af421 BP |
29 | #include "timeval.h" |
30 | #include "unixctl.h" | |
31 | #include "util.h" | |
32 | ||
3fbe1d30 BP |
33 | static void usage(void); |
34 | static const char *parse_command_line(int argc, char *argv[]); | |
35 | static struct unixctl_client *connect_to_target(const char *target); | |
064af421 | 36 | |
3fbe1d30 BP |
37 | int |
38 | main(int argc, char *argv[]) | |
064af421 | 39 | { |
3fbe1d30 BP |
40 | struct unixctl_client *client; |
41 | const char *target; | |
42 | struct ds request; | |
43 | int code, error; | |
064af421 | 44 | char *reply; |
3fbe1d30 BP |
45 | int i; |
46 | ||
47 | set_program_name(argv[0]); | |
48 | time_init(); | |
49 | ||
50 | /* Parse command line and connect to target. */ | |
51 | target = parse_command_line(argc, argv); | |
52 | client = connect_to_target(target); | |
53 | ||
54 | /* Compose request. */ | |
55 | ds_init(&request); | |
56 | for (i = optind; i < argc; i++) { | |
57 | if (i != optind) { | |
58 | ds_put_char(&request, ' '); | |
064af421 | 59 | } |
3fbe1d30 | 60 | ds_put_cstr(&request, argv[i]); |
064af421 | 61 | } |
064af421 | 62 | |
3fbe1d30 BP |
63 | /* Transact request and process reply. */ |
64 | error = unixctl_client_transact(client, ds_cstr(&request), &code, &reply); | |
064af421 | 65 | if (error) { |
3fbe1d30 BP |
66 | ovs_fatal(error, "%s: transaction error", target); |
67 | } | |
68 | if (code / 100 != 2) { | |
69 | ovs_error(0, "%s: server returned reply code %03d", target, code); | |
70 | exit(2); | |
064af421 | 71 | } |
3fbe1d30 BP |
72 | fputs(reply, stdout); |
73 | ||
65f92a50 BP |
74 | unixctl_client_destroy(client); |
75 | free(reply); | |
76 | ds_destroy(&request); | |
77 | ||
3fbe1d30 | 78 | return 0; |
064af421 BP |
79 | } |
80 | ||
81 | static void | |
3fbe1d30 | 82 | usage(void) |
064af421 | 83 | { |
3fbe1d30 BP |
84 | printf("%s, for querying and controlling Open vSwitch daemon\n" |
85 | "usage: %s [TARGET] COMMAND [ARG...]\n" | |
86 | "Targets:\n" | |
87 | " -t, --target=TARGET pidfile or socket to contact\n" | |
88 | "Common commands:" | |
89 | " help List commands supported by the target\n" | |
90 | " vlog/list List current logging levels\n" | |
91 | " vlog/set MODULE[:FACILITY[:LEVEL]]\n" | |
92 | " Set MODULE and FACILITY log level to LEVEL\n" | |
93 | " MODULE may be any valid module name or 'ANY'\n" | |
94 | " FACILITY may be 'syslog', 'console', 'file', or 'ANY' (default)\n" | |
95 | " LEVEL may be 'emer', 'err', 'warn', 'info', or 'dbg' (default)\n" | |
96 | " vlog/reopen Make the program reopen its log file\n" | |
97 | "Other options:\n" | |
98 | " -h, --help Print this helpful information\n" | |
99 | " -V, --version Display version information\n", | |
100 | program_name, program_name); | |
101 | exit(EXIT_SUCCESS); | |
064af421 BP |
102 | } |
103 | ||
3fbe1d30 BP |
104 | static const char * |
105 | parse_command_line(int argc, char *argv[]) | |
064af421 BP |
106 | { |
107 | static const struct option long_options[] = { | |
064af421 | 108 | {"target", required_argument, NULL, 't'}, |
3fbe1d30 | 109 | {"execute", no_argument, NULL, 'e'}, |
064af421 BP |
110 | {"help", no_argument, NULL, 'h'}, |
111 | {"version", no_argument, NULL, 'V'}, | |
064af421 BP |
112 | {0, 0, 0, 0}, |
113 | }; | |
3fbe1d30 BP |
114 | const char *target; |
115 | int e_options; | |
064af421 | 116 | |
3fbe1d30 BP |
117 | target = NULL; |
118 | e_options = 0; | |
064af421 BP |
119 | for (;;) { |
120 | int option; | |
064af421 | 121 | |
3fbe1d30 | 122 | option = getopt_long(argc, argv, "+t:hVe", long_options, NULL); |
064af421 BP |
123 | if (option == -1) { |
124 | break; | |
125 | } | |
064af421 BP |
126 | switch (option) { |
127 | case 't': | |
3fbe1d30 BP |
128 | if (target) { |
129 | ovs_fatal(0, "-t or --target may be specified only once"); | |
064af421 | 130 | } |
3fbe1d30 | 131 | target = optarg; |
064af421 BP |
132 | break; |
133 | ||
134 | case 'e': | |
3fbe1d30 BP |
135 | /* We ignore -e for compatibility. Older versions specified the |
136 | * command as the argument to -e. Since the current version takes | |
137 | * the command as non-option arguments and we say that -e has no | |
138 | * arguments, this just works in the common case. */ | |
139 | if (e_options++) { | |
140 | ovs_fatal(0, "-e or --execute may be speciifed only once"); | |
064af421 BP |
141 | } |
142 | break; | |
143 | ||
144 | case 'h': | |
3fbe1d30 | 145 | usage(); |
064af421 BP |
146 | break; |
147 | ||
148 | case 'V': | |
149 | OVS_PRINT_VERSION(0, 0); | |
150 | exit(EXIT_SUCCESS); | |
151 | ||
152 | case '?': | |
153 | exit(EXIT_FAILURE); | |
154 | ||
155 | default: | |
156 | NOT_REACHED(); | |
157 | } | |
158 | } | |
3fbe1d30 BP |
159 | |
160 | if (optind >= argc) { | |
161 | ovs_fatal(0, "at least one non-option argument is required " | |
162 | "(use --help for help)"); | |
163 | } | |
164 | ||
165 | return target ? target : "ovs-vswitchd"; | |
166 | } | |
167 | ||
168 | static struct unixctl_client * | |
169 | connect_to_target(const char *target) | |
170 | { | |
171 | struct unixctl_client *client; | |
172 | char *socket_name; | |
173 | int error; | |
174 | ||
175 | if (target[0] != '/') { | |
176 | char *pidfile_name; | |
3fbe1d30 BP |
177 | pid_t pid; |
178 | ||
179 | pidfile_name = xasprintf("%s/%s.pid", ovs_rundir, target); | |
180 | pid = read_pidfile(pidfile_name); | |
181 | if (pid < 0) { | |
182 | ovs_fatal(-pid, "cannot read pidfile \"%s\"", pidfile_name); | |
183 | } | |
184 | free(pidfile_name); | |
185 | socket_name = xasprintf("%s/%s.%ld.ctl", | |
186 | ovs_rundir, target, (long int) pid); | |
187 | } else { | |
188 | socket_name = xstrdup(target); | |
189 | } | |
190 | ||
191 | error = unixctl_client_create(socket_name, &client); | |
192 | if (error) { | |
193 | ovs_fatal(error, "cannot connect to \"%s\"", socket_name); | |
064af421 | 194 | } |
3fbe1d30 BP |
195 | free(socket_name); |
196 | ||
197 | return client; | |
064af421 | 198 | } |
3fbe1d30 | 199 |