#include #include #include #include "ds.h" #include "log.h" #include "api.h" ds_sll_t *subcmds; int register_subcmd(char *name, void (*cb)(void *, int argc, char *argv[]), void *data) { char *c; ds_sll_t *newnode = calloc(1, sizeof(ds_sll_t)); wom_subcmd_t *newsubcmd = calloc(1, sizeof(wom_subcmd_t)); /* make sure the subcmd name doesn't contain a space */ for (c = name; *c != '\0'; c++) { if (isspace(*c)) { log_fatal("subcmd '%s' can't contain any whitespace characters", name); return 1; } } /* setup data */ newsubcmd->name = name; newsubcmd->cb = cb; newsubcmd->data = data; newnode->data = newsubcmd; newnode->next = NULL; /* if this is the first node */ if (!subcmds) { subcmds = newnode; return 0; } /* otherwise append the node to the end of the current nodes */ ds_ll_foreach(ds_sll_t, subcmds) { if (!cur->next) { cur->next = newnode; break; } } return 0; } char **list_subcmds(void) { int i; char **subcmdp; ds_sll_t *node; wom_subcmd_t *subcmd; /* get the number of elements in the linked list */ /* TEST: for some reason we need to allocate an extra space in the array or * else */ for (i = 1, node = subcmds; node; node = node->next, i++) ; subcmdp = calloc(i, sizeof(char *)); for (i = 0, node = subcmds; node; node = node->next, i++) { subcmd = node->data; if (subcmd->name) { subcmdp[i] = subcmd->name; } } return subcmdp; } void run_subcmds(int argc, char *argv[]) { int i, j; char **args; wom_subcmd_t *subcmd; /* check for subcommands to run */ for (i = 1; i < argc; i++) { ds_ll_foreach(ds_sll_t, subcmds) { subcmd = cur->data; if (strcmp(argv[i], subcmd->name) == 0) { goto args; } } } return; args: args = calloc(argc - i, sizeof(char *)); for (j = 0; i < argc; i++, j++) { args[j] = argv[i]; } subcmd->cb(subcmd->data, j, args); free(args); } int cleanup_subcmds(void) { ds_sll_t *prevnode, *node; for (node = subcmds; node;) { free(node->data); prevnode = node; node = node->next; free(prevnode); } free(node); return 0; }