static struct shash all_commands = SHASH_INITIALIZER(&all_commands);
\f
+static struct option *
+find_option(const char *name, struct option *options, size_t n_options)
+{
+ size_t i;
+
+ for (i = 0; i < n_options; i++) {
+ if (!strcmp(options[i].name, name)) {
+ return &options[i];
+ }
+ }
+ return NULL;
+}
+
+static struct option *
+add_option(struct option **optionsp, size_t *n_optionsp,
+ size_t *allocated_optionsp)
+{
+ if (*n_optionsp >= *allocated_optionsp) {
+ *optionsp = x2nrealloc(*optionsp, allocated_optionsp,
+ sizeof **optionsp);
+ }
+ return &(*optionsp)[(*n_optionsp)++];
+}
+
+/* Converts the command arguments into format that can be parsed by
+ * bash completion script.
+ *
+ * Therein, arguments will be attached with following prefixes:
+ *
+ * !argument :: The argument is required
+ * ?argument :: The argument is optional
+ * *argument :: The argument may appear any number (0 or more) times
+ * +argument :: The argument may appear one or more times
+ *
+ */
+static void
+print_command_arguments(const struct ctl_command_syntax *command)
+{
+ /*
+ * The argument string is parsed in reverse. We use a stack 'oew_stack' to
+ * keep track of nested optionals. Whenever a ']' is encountered, we push
+ * a bit to 'oew_stack'. The bit is set to 1 if the ']' is not nested.
+ * Subsequently, we pop an entry everytime '[' is met.
+ *
+ * We use 'whole_word_is_optional' value to decide whether or not a ! or +
+ * should be added on encountering a space: if the optional surrounds the
+ * whole word then it shouldn't be, but if it is only a part of the word
+ * (i.e. [key=]value), it should be.
+ */
+ uint32_t oew_stack = 0;
+
+ const char *arguments = command->arguments;
+ int length = strlen(arguments);
+ if (!length) {
+ return;
+ }
+
+ /* Output buffer, written backward from end. */
+ char *output = xmalloc(2 * length);
+ char *outp = output + 2 * length;
+ *--outp = '\0';
+
+ bool in_repeated = false;
+ bool whole_word_is_optional = false;
+
+ for (const char *inp = arguments + length; inp > arguments; ) {
+ switch (*--inp) {
+ case ']':
+ oew_stack <<= 1;
+ if (inp[1] == '\0' || inp[1] == ' ' || inp[1] == '.') {
+ oew_stack |= 1;
+ }
+ break;
+ case '[':
+ /* Checks if the whole word is optional, and sets the
+ * 'whole_word_is_optional' accordingly. */
+ if ((inp == arguments || inp[-1] == ' ') && oew_stack & 1) {
+ *--outp = in_repeated ? '*' : '?';
+ whole_word_is_optional = true;
+ } else {
+ *--outp = '?';
+ whole_word_is_optional = false;
+ }
+ oew_stack >>= 1;
+ break;
+ case ' ':
+ if (!whole_word_is_optional) {
+ *--outp = in_repeated ? '+' : '!';
+ }
+ *--outp = ' ';
+ in_repeated = false;
+ whole_word_is_optional = false;
+ break;
+ case '.':
+ in_repeated = true;
+ break;
+ default:
+ *--outp = *inp;
+ break;
+ }
+ }
+ if (arguments[0] != '[' && outp != output + 2 * length - 1) {
+ *--outp = in_repeated ? '+' : '!';
+ }
+ printf("%s", outp);
+ free(output);
+}
+
static void
die_if_error(char *error)
{
}
\f
+/* Given pointer to dynamic array 'options_p', array's current size
+ * 'allocated_options_p' and number of added options 'n_options_p',
+ * adds all command options to the array. Enlarges the array if
+ * necessary. */
+void
+ctl_add_cmd_options(struct option **options_p, size_t *n_options_p,
+ size_t *allocated_options_p, int opt_val)
+{
+ struct option *o;
+ const struct shash_node *node;
+ size_t n_existing_options = *n_options_p;
+
+ SHASH_FOR_EACH (node, ctl_get_all_commands()) {
+ const struct ctl_command_syntax *p = node->data;
+
+ if (p->options[0]) {
+ char *save_ptr = NULL;
+ char *name;
+ char *s;
+
+ s = xstrdup(p->options);
+ for (name = strtok_r(s, ",", &save_ptr); name != NULL;
+ name = strtok_r(NULL, ",", &save_ptr)) {
+ char *equals;
+ int has_arg;
+
+ ovs_assert(name[0] == '-' && name[1] == '-' && name[2]);
+ name += 2;
+
+ equals = strchr(name, '=');
+ if (equals) {
+ has_arg = required_argument;
+ *equals = '\0';
+ } else {
+ has_arg = no_argument;
+ }
+
+ o = find_option(name, *options_p, *n_options_p);
+ if (o) {
+ ovs_assert(o - *options_p >= n_existing_options);
+ ovs_assert(o->has_arg == has_arg);
+ } else {
+ o = add_option(options_p, n_options_p, allocated_options_p);
+ o->name = xstrdup(name);
+ o->has_arg = has_arg;
+ o->flag = NULL;
+ o->val = opt_val;
+ }
+ }
+
+ free(s);
+ }
+ }
+ o = add_option(options_p, n_options_p, allocated_options_p);
+ memset(o, 0, sizeof *o);
+}
+
/* Parses command-line input for commands. */
struct ctl_command *
ctl_parse_commands(int argc, char *argv[], struct shash *local_options,
return commands;
}
+/* Prints all registered commands. */
+void
+ctl_print_commands(void)
+{
+ const struct shash_node *node;
+
+ SHASH_FOR_EACH (node, ctl_get_all_commands()) {
+ const struct ctl_command_syntax *p = node->data;
+ char *options = xstrdup(p->options);
+ char *options_begin = options;
+ char *item;
+
+ for (item = strsep(&options, ","); item != NULL;
+ item = strsep(&options, ",")) {
+ if (item[0] != '\0') {
+ printf("[%s] ", item);
+ }
+ }
+ printf(",%s,", p->name);
+ print_command_arguments(p);
+ printf("\n");
+
+ free(options_begin);
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
+/* Given array of options 'options', prints them. */
+void
+ctl_print_options(const struct option *options)
+{
+ for (; options->name; options++) {
+ const struct option *o = options;
+
+ printf("--%s%s\n", o->name, o->has_arg ? "=ARG" : "");
+ if (o->flag == NULL && o->val > 0 && o->val <= UCHAR_MAX) {
+ printf("-%c%s\n", o->val, o->has_arg ? " ARG" : "");
+ }
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
+/* Returns the default local database path. */
+char *
+ctl_default_db(void)
+{
+ static char *def;
+ if (!def) {
+ def = xasprintf("unix:%s/db.sock", ovs_rundir());
+ }
+ return def;
+}
+
/* Returns true if it looks like this set of arguments might modify the
* database, otherwise false. (Not very smart, so it's prone to false
* positives.) */
#include "command-line.h"
#include "compiler.h"
-#include "dirs.h"
#include "dynamic-string.h"
#include "fatal-signal.h"
#include "hash.h"
static struct table_style table_style = TABLE_STYLE_DEFAULT;
static void vsctl_cmd_init(void);
-static char *default_db(void);
OVS_NO_RETURN static void usage(void);
-OVS_NO_RETURN static void print_vsctl_commands(void);
-OVS_NO_RETURN static void print_vsctl_options(const struct option *options);
static void parse_options(int argc, char *argv[], struct shash *local_options);
static void run_prerequisites(struct ctl_command[], size_t n_commands,
struct ovsdb_idl *);
}
}
-static struct option *
-find_option(const char *name, struct option *options, size_t n_options)
-{
- size_t i;
-
- for (i = 0; i < n_options; i++) {
- if (!strcmp(options[i].name, name)) {
- return &options[i];
- }
- }
- return NULL;
-}
-
-static struct option *
-add_option(struct option **optionsp, size_t *n_optionsp,
- size_t *allocated_optionsp)
-{
- if (*n_optionsp >= *allocated_optionsp) {
- *optionsp = x2nrealloc(*optionsp, allocated_optionsp,
- sizeof **optionsp);
- }
- return &(*optionsp)[(*n_optionsp)++];
-}
-
static void
parse_options(int argc, char *argv[], struct shash *local_options)
{
const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
char *tmp, *short_options;
- const struct shash_node *node;
- struct option *options, *o;
+ struct option *options;
size_t allocated_options;
size_t n_options;
size_t i;
options = xmemdup(global_long_options, sizeof global_long_options);
allocated_options = ARRAY_SIZE(global_long_options);
n_options = n_global_long_options;
- SHASH_FOR_EACH (node, ctl_get_all_commands()) {
- const struct ctl_command_syntax *p = node->data;
-
- if (p->options[0]) {
- char *save_ptr = NULL;
- char *name;
- char *s;
-
- s = xstrdup(p->options);
- for (name = strtok_r(s, ",", &save_ptr); name != NULL;
- name = strtok_r(NULL, ",", &save_ptr)) {
- char *equals;
- int has_arg;
-
- ovs_assert(name[0] == '-' && name[1] == '-' && name[2]);
- name += 2;
-
- equals = strchr(name, '=');
- if (equals) {
- has_arg = required_argument;
- *equals = '\0';
- } else {
- has_arg = no_argument;
- }
-
- o = find_option(name, options, n_options);
- if (o) {
- ovs_assert(o - options >= n_global_long_options);
- ovs_assert(o->has_arg == has_arg);
- } else {
- o = add_option(&options, &n_options, &allocated_options);
- o->name = xstrdup(name);
- o->has_arg = has_arg;
- o->flag = NULL;
- o->val = OPT_LOCAL;
- }
- }
-
- free(s);
- }
- }
- o = add_option(&options, &n_options, &allocated_options);
- memset(o, 0, sizeof *o);
-
+ ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
table_style.format = TF_LIST;
for (;;) {
usage();
case OPT_COMMANDS:
- print_vsctl_commands();
+ ctl_print_commands();
case OPT_OPTIONS:
- print_vsctl_options(global_long_options);
+ ctl_print_options(global_long_options);
case 'V':
ovs_print_version(0, 0);
free(short_options);
if (!db) {
- db = default_db();
+ db = ctl_default_db();
}
for (i = n_global_long_options; options[i].name; i++) {
-t, --timeout=SECS wait at most SECS seconds for ovs-vswitchd\n\
--dry-run do not commit changes to database\n\
--oneline print exactly one line of output per command\n",
- program_name, program_name, ctl_get_db_cmd_usage(), default_db());
+ program_name, program_name, ctl_get_db_cmd_usage(), ctl_default_db());
vlog_usage();
printf("\
--no-syslog equivalent to --verbose=vsctl:syslog:warn\n");
exit(EXIT_SUCCESS);
}
-/* Converts the command arguments into format that can be parsed by
- * bash completion script.
- *
- * Therein, arguments will be attached with following prefixes:
- *
- * !argument :: The argument is required
- * ?argument :: The argument is optional
- * *argument :: The argument may appear any number (0 or more) times
- * +argument :: The argument may appear one or more times
- *
- */
-static void
-print_command_arguments(const struct ctl_command_syntax *command)
-{
- /*
- * The argument string is parsed in reverse. We use a stack 'oew_stack' to
- * keep track of nested optionals. Whenever a ']' is encountered, we push
- * a bit to 'oew_stack'. The bit is set to 1 if the ']' is not nested.
- * Subsequently, we pop an entry everytime '[' is met.
- *
- * We use 'whole_word_is_optional' value to decide whether or not a ! or +
- * should be added on encountering a space: if the optional surrounds the
- * whole word then it shouldn't be, but if it is only a part of the word
- * (i.e. [key=]value), it should be.
- */
- uint32_t oew_stack = 0;
-
- const char *arguments = command->arguments;
- int length = strlen(arguments);
- if (!length) {
- return;
- }
-
- /* Output buffer, written backward from end. */
- char *output = xmalloc(2 * length);
- char *outp = output + 2 * length;
- *--outp = '\0';
-
- bool in_repeated = false;
- bool whole_word_is_optional = false;
-
- for (const char *inp = arguments + length; inp > arguments; ) {
- switch (*--inp) {
- case ']':
- oew_stack <<= 1;
- if (inp[1] == '\0' || inp[1] == ' ' || inp[1] == '.') {
- oew_stack |= 1;
- }
- break;
- case '[':
- /* Checks if the whole word is optional, and sets the
- * 'whole_word_is_optional' accordingly. */
- if ((inp == arguments || inp[-1] == ' ') && oew_stack & 1) {
- *--outp = in_repeated ? '*' : '?';
- whole_word_is_optional = true;
- } else {
- *--outp = '?';
- whole_word_is_optional = false;
- }
- oew_stack >>= 1;
- break;
- case ' ':
- if (!whole_word_is_optional) {
- *--outp = in_repeated ? '+' : '!';
- }
- *--outp = ' ';
- in_repeated = false;
- whole_word_is_optional = false;
- break;
- case '.':
- in_repeated = true;
- break;
- default:
- *--outp = *inp;
- break;
- }
- }
- if (arguments[0] != '[' && outp != output + 2 * length - 1) {
- *--outp = in_repeated ? '+' : '!';
- }
- printf("%s", outp);
- free(output);
-}
-
-static void
-print_vsctl_commands(void)
-{
- const struct shash_node *node;
-
- SHASH_FOR_EACH (node, ctl_get_all_commands()) {
- const struct ctl_command_syntax *p = node->data;
- char *options = xstrdup(p->options);
- char *options_begin = options;
- char *item;
-
- for (item = strsep(&options, ","); item != NULL;
- item = strsep(&options, ",")) {
- if (item[0] != '\0') {
- printf("[%s] ", item);
- }
- }
- printf(",%s,", p->name);
- print_command_arguments(p);
- printf("\n");
-
- free(options_begin);
- }
-
- exit(EXIT_SUCCESS);
-}
-
-static void
-print_vsctl_options(const struct option *options)
-{
- for (; options->name; options++) {
- const struct option *o = options;
-
- printf("--%s%s\n", o->name, o->has_arg ? "=ARG" : "");
- if (o->flag == NULL && o->val > 0 && o->val <= UCHAR_MAX) {
- printf("-%c%s\n", o->val, o->has_arg ? " ARG" : "");
- }
- }
-
- exit(EXIT_SUCCESS);
-}
-
-static char *
-default_db(void)
-{
- static char *def;
- if (!def) {
- def = xasprintf("unix:%s/db.sock", ovs_rundir());
- }
- return def;
-}
-
\f
/* ovs-vsctl specific context. Inherits the 'struct ctl_context' as base. */
struct vsctl_context {