+ /* Dummy popt context for generating help */
+ cmdline->pc = poptGetContext(cmdline->prog,
+ cmdline->argc,
+ cmdline->argv,
+ cmdline->options,
+ 0);
+ if (cmdline->pc == NULL) {
+ talloc_free(cmdline);
+ return ENOMEM;
+ }
+
+ talloc_set_destructor(cmdline, cmdline_context_destructor);
+
+ *result = cmdline;
+ return 0;
+}
+
+static int cmdline_context_destructor(struct cmdline_context *cmdline)
+{
+ if (cmdline->pc != NULL) {
+ poptFreeContext(cmdline->pc);
+ }
+
+ return 0;
+}
+
+static int cmdline_parse_options(struct cmdline_context *cmdline,
+ int argc,
+ const char **argv)
+{
+ int opt;
+
+ if (cmdline->pc != NULL) {
+ poptFreeContext(cmdline->pc);
+ }
+
+ cmdline->pc = poptGetContext(cmdline->prog,
+ argc,
+ argv,
+ cmdline->options,
+ 0);
+ if (cmdline->pc == NULL) {
+ return ENOMEM;
+ }
+
+ while ((opt = poptGetNextOpt(cmdline->pc)) != -1) {
+ D_ERR("Invalid option %s: %s\n",
+ poptBadOption(cmdline->pc, 0),
+ poptStrerror(opt));
+ return EINVAL;
+ }
+
+ /* Set up remaining arguments for commands */
+ cmdline->argc = 0;
+ cmdline->argv = poptGetArgs(cmdline->pc);
+ if (cmdline->argv != NULL) {
+ while (cmdline->argv[cmdline->argc] != NULL) {
+ cmdline->argc++;
+ }
+ }
+
+ return 0;
+}
+
+static int cmdline_match(struct cmdline_context *cmdline)
+{
+ int i;
+
+ if (cmdline->argc == 0 || cmdline->argv == NULL) {
+ cmdline->match_cmd = NULL;
+ return EINVAL;
+ }
+
+ for (i=0; cmdline->commands[i].name != NULL; i++) {
+ struct cmdline_command *cmd;
+ char name[CMDLINE_MAX_LEN+1];
+ size_t len;
+ char *t, *str;
+ int n = 0;
+ bool match = false;
+
+ cmd = &cmdline->commands[i];
+ len = strlcpy(name, cmd->name, sizeof(name));
+ if (len >= sizeof(name)) {
+ D_ERR("Skipping long command '%s'\n", cmd->name);
+ continue;
+ }
+
+ str = name;
+ while ((t = strtok(str, " ")) != NULL) {
+ if (n >= cmdline->argc) {
+ match = false;
+ break;
+ }
+ if (cmdline->argv[n] == NULL) {
+ match = false;
+ break;
+ }
+ if (strcmp(cmdline->argv[n], t) == 0) {
+ match = true;
+ cmdline->arg0 = n+1;
+ } else {
+ match = false;
+ break;
+ }
+
+ n += 1;
+ str = NULL;
+ }
+
+ if (match) {
+ cmdline->match_cmd = cmd;
+ return 0;
+ }
+ }
+
+ cmdline->match_cmd = NULL;
+ return ENOENT;
+}
+
+int cmdline_parse(struct cmdline_context *cmdline,
+ int argc,
+ const char **argv,
+ bool parse_options)
+{
+ int ret;
+
+ if (argc < 2) {
+ return EINVAL;
+ }
+
+ cmdline_show_help = false;
+
+ if (parse_options) {
+ ret = cmdline_parse_options(cmdline, argc, argv);
+ if (ret != 0) {
+ return ret;