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