-static struct vsctl_command *
-parse_commands(int argc, char *argv[], struct shash *local_options,
- size_t *n_commandsp)
-{
- struct vsctl_command *commands;
- size_t n_commands, allocated_commands;
- int i, start;
-
- commands = NULL;
- n_commands = allocated_commands = 0;
-
- for (start = i = 0; i <= argc; i++) {
- if (i == argc || !strcmp(argv[i], "--")) {
- if (i > start) {
- if (n_commands >= allocated_commands) {
- struct vsctl_command *c;
-
- commands = x2nrealloc(commands, &allocated_commands,
- sizeof *commands);
- for (c = commands; c < &commands[n_commands]; c++) {
- shash_moved(&c->options);
- }
- }
- parse_command(i - start, &argv[start], local_options,
- &commands[n_commands++]);
- } else if (!shash_is_empty(local_options)) {
- vsctl_fatal("missing command name (use --help for help)");
- }
- start = i + 1;
- }
- }
- if (!n_commands) {
- vsctl_fatal("missing command name (use --help for help)");
- }
- *n_commandsp = n_commands;
- return commands;
-}
-
-static void
-parse_command(int argc, char *argv[], struct shash *local_options,
- struct vsctl_command *command)
-{
- const struct vsctl_command_syntax *p;
- struct shash_node *node;
- int n_arg;
- int i;
-
- shash_init(&command->options);
- shash_swap(local_options, &command->options);
- for (i = 0; i < argc; i++) {
- const char *option = argv[i];
- const char *equals;
- char *key, *value;
-
- if (option[0] != '-') {
- break;
- }
-
- equals = strchr(option, '=');
- if (equals) {
- key = xmemdup0(option, equals - option);
- value = xstrdup(equals + 1);
- } else {
- key = xstrdup(option);
- value = NULL;
- }
-
- if (shash_find(&command->options, key)) {
- vsctl_fatal("'%s' option specified multiple times", argv[i]);
- }
- shash_add_nocopy(&command->options, key, value);
- }
- if (i == argc) {
- vsctl_fatal("missing command name (use --help for help)");
- }
-
- p = find_command(argv[i]);
- if (!p) {
- vsctl_fatal("unknown command '%s'; use --help for help", argv[i]);
- }
-
- SHASH_FOR_EACH (node, &command->options) {
- const char *s = strstr(p->options, node->name);
- int end = s ? s[strlen(node->name)] : EOF;
-
- if (end != '=' && end != ',' && end != ' ' && end != '\0') {
- vsctl_fatal("'%s' command has no '%s' option",
- argv[i], node->name);
- }
- if ((end == '=') != (node->data != NULL)) {
- if (end == '=') {
- vsctl_fatal("missing argument to '%s' option on '%s' "
- "command", node->name, argv[i]);
- } else {
- vsctl_fatal("'%s' option on '%s' does not accept an "
- "argument", node->name, argv[i]);
- }
- }
- }
-
- n_arg = argc - i - 1;
- if (n_arg < p->min_args) {
- vsctl_fatal("'%s' command requires at least %d arguments",
- p->name, p->min_args);
- } else if (n_arg > p->max_args) {
- int j;
-
- for (j = i + 1; j < argc; j++) {
- if (argv[j][0] == '-') {
- vsctl_fatal("'%s' command takes at most %d arguments "
- "(note that options must precede command "
- "names and follow a \"--\" argument)",
- p->name, p->max_args);
- }
- }
-
- vsctl_fatal("'%s' command takes at most %d arguments",
- p->name, p->max_args);
- }
-
- command->syntax = p;
- command->argc = n_arg + 1;
- command->argv = &argv[i];
-}
-
-/* Returns the "struct vsctl_command_syntax" for a given command 'name', or a
- * null pointer if there is none. */
-static const struct vsctl_command_syntax *
-find_command(const char *name)
-{
- static struct shash commands = SHASH_INITIALIZER(&commands);
-
- if (shash_is_empty(&commands)) {
- const struct vsctl_command_syntax *p;
-
- for (p = all_commands; p->name; p++) {
- shash_add_assert(&commands, p->name, p);
- }
- }
-
- return shash_find_data(&commands, name);
-}
-
-static void
-vsctl_fatal(const char *format, ...)
-{
- char *message;
- va_list args;
-
- va_start(args, format);
- message = xvasprintf(format, args);
- va_end(args);
-
- vlog_set_levels(&VLM_vsctl, VLF_CONSOLE, VLL_OFF);
- VLOG_ERR("%s", message);
- ovs_error(0, "%s", message);
- vsctl_exit(EXIT_FAILURE);
-}
-
-/* Frees the current transaction and the underlying IDL and then calls
- * exit(status).
- *
- * Freeing the transaction and the IDL is not strictly necessary, but it makes
- * for a clean memory leak report from valgrind in the normal case. That makes
- * it easier to notice real memory leaks. */
-static void
-vsctl_exit(int status)
-{
- if (the_idl_txn) {
- ovsdb_idl_txn_abort(the_idl_txn);
- ovsdb_idl_txn_destroy(the_idl_txn);
- }
- ovsdb_idl_destroy(the_idl);
- exit(status);
-}
-