Add support for vendor-defined and variable-length actions.
[sliver-openvswitch.git] / utilities / vlogconf.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 #include <config.h>
34 #include "vlog.h"
35
36 #include <dirent.h>
37 #include <errno.h>
38 #include <getopt.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdlib.h>
43
44 #include "command-line.h"
45 #include "compiler.h"
46 #include "timeval.h"
47 #include "util.h"
48 #include "vlog-socket.h"
49
50 void
51 usage(char *prog_name, int exit_code)
52 {
53     printf("Usage: %s [TARGET] [ACTION...]\n"
54            "Targets:\n"
55            "  -a, --all            Apply to all targets (default)\n"
56            "  -t, --target=TARGET  Specify target program, as a pid or an\n"
57            "                       absolute path to a Unix domain socket\n"
58            "Actions:\n"
59            "  -l, --list         List current settings\n"
60            "  -s, --set=MODULE[:FACILITY[:LEVEL]]\n"
61            "        Set MODULE and FACILITY log level to LEVEL\n"
62            "        MODULE may be any valid module name or 'ANY'\n"
63            "        FACILITY may be 'syslog' or 'console' or 'ANY' (default)\n"
64            "        LEVEL may be 'emer', 'err', 'warn', or 'dbg (default)'\n"
65            "  -h, --help         Print this helpful information\n",
66            prog_name);
67     exit(exit_code);
68 }
69
70 static char *
71 transact(struct vlog_client *client, const char *request, bool *ok)
72 {
73     char *reply;
74     int error = vlog_client_transact(client, request, &reply);
75     if (error) {
76         fprintf(stderr, "%s: transaction error: %s\n",
77                 vlog_client_target(client), strerror(error));
78         *ok = false;
79     }
80     return reply ? reply : xstrdup("");
81 }
82
83 static void
84 transact_ack(struct vlog_client *client, const char* request, bool *ok)
85 {
86     char *reply;
87     int error = vlog_client_transact(client, request, &reply);
88     if (error) {
89         fprintf(stderr, "%s: transaction error: %s\n",
90                 vlog_client_target(client), strerror(error));
91         *ok = false;
92     } else if (strcmp(reply, "ack")) {
93         fprintf(stderr, "Received unexpected reply from %s: %s\n",
94                 vlog_client_target(client), reply);
95         *ok = false;
96     }
97     free(reply);
98 }
99
100 static void
101 add_target(struct vlog_client ***clients, size_t *n_clients,
102            const char *path, bool *ok)
103 {
104     struct vlog_client *client;
105     int error = vlog_client_connect(path, &client);
106     if (error) {
107         fprintf(stderr, "Error connecting to \"%s\": %s\n",
108                 path, strerror(error));
109         *ok = false;
110     } else {
111         *clients = xrealloc(*clients, sizeof *clients * (*n_clients + 1));
112         (*clients)[*n_clients] = client;
113         ++*n_clients;
114     }
115 }
116
117 static void
118 add_all_targets(struct vlog_client ***clients, size_t *n_clients, bool *ok)
119 {
120     DIR *directory;
121     struct dirent* de;
122
123     directory = opendir("/tmp");
124     if (!directory) {
125         fprintf(stderr, "/tmp: opendir: %s\n", strerror(errno));
126     }
127
128     while ((de = readdir(directory)) != NULL) {
129         if (!strncmp(de->d_name, "vlogs.", 5)) {
130             char *path = xasprintf("/tmp/%s", de->d_name);
131             add_target(clients, n_clients, path, ok);
132             free(path);
133         }
134     }
135
136     closedir(directory);
137 }
138
139 int main(int argc, char *argv[])
140 {
141     static const struct option long_options[] = {
142         /* Target options must come first. */
143         {"all", no_argument, NULL, 'a'},
144         {"target", required_argument, NULL, 't'},
145         {"help", no_argument, NULL, 'h'},
146
147         /* Action options come afterward. */
148         {"list", no_argument, NULL, 'l'},
149         {"set", required_argument, NULL, 's'},
150         {0, 0, 0, 0},
151     };
152     char *short_options;
153
154     /* Determine targets. */
155     bool ok = true;
156     int n_actions = 0;
157     struct vlog_client **clients = NULL;
158     size_t n_clients = 0;
159
160     set_program_name(argv[0]);
161     time_init();
162
163     short_options = long_options_to_short_options(long_options);
164     for (;;) {
165         int option;
166         size_t i;
167
168         option = getopt_long(argc, argv, short_options, long_options, NULL);
169         if (option == -1) {
170             break;
171         }
172         if (!strchr("ath", option) && n_clients == 0) {
173             ofp_fatal(0, "no targets specified (use --help for help)");
174         } else {
175             ++n_actions;
176         }
177         switch (option) {
178         case 'a':
179             add_all_targets(&clients, &n_clients, &ok);
180             break;
181
182         case 't':
183             add_target(&clients, &n_clients, optarg, &ok);
184             break;
185
186         case 'l':
187             for (i = 0; i < n_clients; i++) {
188                 struct vlog_client *client = clients[i];
189                 char *reply;
190
191                 printf("%s:\n", vlog_client_target(client));
192                 reply = transact(client, "list", &ok);
193                 fputs(reply, stdout);
194                 free(reply);
195             }
196             break;
197
198         case 's':
199             for (i = 0; i < n_clients; i++) {
200                 struct vlog_client *client = clients[i];
201                 char *request = xasprintf("set %s", optarg);
202                 transact_ack(client, request, &ok);
203                 free(request);
204             }
205             break;
206
207         case 'h':
208             usage(argv[0], EXIT_SUCCESS);
209             break;
210
211         case '?':
212             exit(EXIT_FAILURE);
213
214         default:
215             NOT_REACHED();
216         }
217     }
218     if (!n_actions) {
219         fprintf(stderr,
220                 "warning: no actions specified (use --help for help)\n");
221     }
222     exit(ok ? 0 : 1);
223 }