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