Import from old repository commit 61ef2b42a9c4ba8e1600f15bb0236765edc2ad45.
[cascardo/ovs.git] / utilities / ovs-appctl.c
1 /*
2  * Copyright (c) 2008, 2009 Nicira Networks.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 #include <config.h>
17 #include "vlog.h"
18
19 #include <dirent.h>
20 #include <errno.h>
21 #include <getopt.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 #include "command-line.h"
28 #include "compiler.h"
29 #include "timeval.h"
30 #include "unixctl.h"
31 #include "util.h"
32
33 static void
34 usage(char *prog_name, int exit_code)
35 {
36     printf("Usage: %s [TARGET] [ACTION...]\n"
37            "Targets:\n"
38            "  -t, --target=TARGET  Path to Unix domain socket\n"
39            "Actions:\n"
40            "  -l, --list         List current settings\n"
41            "  -s, --set=MODULE[:FACILITY[:LEVEL]]\n"
42            "        Set MODULE and FACILITY log level to LEVEL\n"
43            "        MODULE may be any valid module name or 'ANY'\n"
44            "        FACILITY may be 'syslog', 'console', 'file', or 'ANY' (default)\n"
45            "        LEVEL may be 'emer', 'err', 'warn', 'info', or 'dbg' (default)\n"
46            "  -r, --reopen       Make the program reopen its log file\n"
47            "  -e, --execute=COMMAND  Execute control COMMAND and print its output\n"
48            "Other options:\n"
49            "  -h, --help         Print this helpful information\n"
50            "  -V, --version      Display version information\n",
51            prog_name);
52     exit(exit_code);
53 }
54
55 static char *
56 transact(struct unixctl_client *client, const char *request, bool *ok)
57 {
58     int code;
59     char *reply;
60     int error = unixctl_client_transact(client, request, &code, &reply);
61     if (error) {
62         fprintf(stderr, "%s: transaction error: %s\n",
63                 unixctl_client_target(client), strerror(error));
64         *ok = false;
65         return xstrdup("");
66     } else {
67         if (code / 100 != 2) {
68             fprintf(stderr, "%s: server returned reply code %03d\n",
69                     unixctl_client_target(client), code);
70         }
71         return reply;
72     }
73 }
74
75 static void
76 transact_ack(struct unixctl_client *client, const char *request, bool *ok)
77 {
78     free(transact(client, request, ok));
79 }
80
81 static void
82 execute_command(struct unixctl_client *client, const char *request, bool *ok)
83 {
84     int code;
85     char *reply;
86     int error = unixctl_client_transact(client, request, &code, &reply);
87     if (error) {
88         fprintf(stderr, "%s: transaction error: %s\n",
89                 unixctl_client_target(client), strerror(error));
90         *ok = false;
91     } else {
92         if (code / 100 != 2) {
93             fprintf(stderr, "%s: server returned reply code %03d\n",
94                     unixctl_client_target(client), code);
95             fputs(reply, stderr);
96             *ok = false;
97         } else {
98             fputs(reply, stdout);
99         }
100     }
101 }
102
103 static void
104 add_target(struct unixctl_client ***clients, size_t *n_clients,
105            const char *path, bool *ok)
106 {
107     struct unixctl_client *client;
108     int error = unixctl_client_create(path, &client);
109     if (error) {
110         fprintf(stderr, "Error connecting to \"%s\": %s\n",
111                 path, strerror(error));
112         *ok = false;
113     } else {
114         *clients = xrealloc(*clients, sizeof *clients * (*n_clients + 1));
115         (*clients)[*n_clients] = client;
116         ++*n_clients;
117     }
118 }
119
120 int main(int argc, char *argv[])
121 {
122     static const struct option long_options[] = {
123         /* Target options must come first. */
124         {"target", required_argument, NULL, 't'},
125         {"help", no_argument, NULL, 'h'},
126         {"version", no_argument, NULL, 'V'},
127
128         /* Action options come afterward. */
129         {"list", no_argument, NULL, 'l'},
130         {"set", required_argument, NULL, 's'},
131         {"reopen", no_argument, NULL, 'r'},
132         {"execute", required_argument, NULL, 'e'},
133         {0, 0, 0, 0},
134     };
135     char *short_options;
136
137     /* Determine targets. */
138     bool ok = true;
139     int n_actions = 0;
140     struct unixctl_client **clients = NULL;
141     size_t n_clients = 0;
142
143     set_program_name(argv[0]);
144     time_init();
145
146     short_options = long_options_to_short_options(long_options);
147     for (;;) {
148         int option;
149         size_t i;
150
151         option = getopt_long(argc, argv, short_options, long_options, NULL);
152         if (option == -1) {
153             break;
154         }
155         if (!strchr("thV", option) && n_clients == 0) {
156             ovs_fatal(0, "no targets specified (use --help for help)");
157         } else {
158             ++n_actions;
159         }
160         switch (option) {
161         case 't':
162             add_target(&clients, &n_clients, optarg, &ok);
163             break;
164
165         case 'l':
166             for (i = 0; i < n_clients; i++) {
167                 struct unixctl_client *client = clients[i];
168                 char *reply;
169
170                 printf("%s:\n", unixctl_client_target(client));
171                 reply = transact(client, "vlog/list", &ok);
172                 fputs(reply, stdout);
173                 free(reply);
174             }
175             break;
176
177         case 's':
178             for (i = 0; i < n_clients; i++) {
179                 struct unixctl_client *client = clients[i];
180                 char *request = xasprintf("vlog/set %s", optarg);
181                 transact_ack(client, request, &ok);
182                 free(request);
183             }
184             break;
185
186         case 'r':
187             for (i = 0; i < n_clients; i++) {
188                 struct unixctl_client *client = clients[i];
189                 char *request = xstrdup("vlog/reopen");
190                 transact_ack(client, request, &ok);
191                 free(request);
192             }
193             break;
194
195         case 'e':
196             for (i = 0; i < n_clients; i++) {
197                 execute_command(clients[i], optarg, &ok);
198             }
199             break;
200
201         case 'h':
202             usage(argv[0], EXIT_SUCCESS);
203             break;
204
205         case 'V':
206             OVS_PRINT_VERSION(0, 0);
207             exit(EXIT_SUCCESS);
208
209         case '?':
210             exit(EXIT_FAILURE);
211
212         default:
213             NOT_REACHED();
214         }
215     }
216     if (!n_actions) {
217         fprintf(stderr,
218                 "warning: no actions specified (use --help for help)\n");
219     }
220     exit(ok ? 0 : 1);
221 }