aboutsummaryrefslogtreecommitdiffstats
path: root/ctrl/libhicnctrl/src/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'ctrl/libhicnctrl/src/command.c')
-rw-r--r--ctrl/libhicnctrl/src/command.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/ctrl/libhicnctrl/src/command.c b/ctrl/libhicnctrl/src/command.c
new file mode 100644
index 000000000..77b6eb7e8
--- /dev/null
+++ b/ctrl/libhicnctrl/src/command.c
@@ -0,0 +1,127 @@
+
+/**
+ * @file command.c
+ * @brief Implementation of commands.
+ */
+
+#ifdef __linux__
+#define _GNU_SOURCE
+#endif /* __linux__ */
+#include <search.h> /* tfind, tdestroy, twalk */
+#include <stdio.h>
+#include <ctype.h>
+#include <hicn/ctrl/command.h>
+
+#include <hicn/util/log.h>
+
+#include <hicn/ctrl/parse.h>
+
+/* Commands are registered in the following tree. */
+static void *commands_root = NULL; /**< Tree ordered by name */
+
+#ifdef __linux__
+static void nothing_to_free() {}
+
+__attribute__((destructor)) static void command_clear() {
+ tdestroy(commands_root, nothing_to_free);
+}
+#endif /* __linux__ */
+
+static int _command_compare(const command_parser_t *c1,
+ const command_parser_t *c2) {
+ if (c1->object_type != c2->object_type)
+ return c2->object_type - c1->object_type;
+ if (c1->action != c2->action) return c2->action - c1->action;
+ if (c1->nparams != c2->nparams) return c2->nparams - c1->nparams;
+ return 0;
+}
+
+#define command_compare (int (*)(const void *, const void *))(_command_compare)
+
+void command_register(const command_parser_t *command) {
+ // Insert the command in the tree if the keys does not exist yet
+ tsearch(command, &commands_root, command_compare);
+}
+
+const command_parser_t *command_search(const hc_action_t action,
+ hc_object_type_t object_type,
+ unsigned nparams) {
+ command_parser_t **command, search;
+
+ search.action = action;
+ search.object_type = object_type;
+ search.nparams = nparams;
+ command = tfind(&search, &commands_root, command_compare);
+
+ return command ? *command : NULL;
+}
+
+static inline void to_lowercase(char *p) {
+ for (; *p; ++p) *p = tolower(*p);
+}
+
+typedef struct {
+ hc_object_type_t object_type;
+ hc_action_t action;
+} cmd_search_params_t;
+
+static hc_object_type_t prev_obj = OBJECT_TYPE_UNDEFINED;
+static hc_action_t prev_action = ACTION_UNDEFINED;
+static void traversal_action(const void *nodep, VISIT which,
+ void *cmd_params0) {
+ cmd_search_params_t *cmd_params = cmd_params0;
+
+ // Execute this function during inorder traversal
+ if (which != postorder && which != leaf) return;
+
+ command_parser_t *datap;
+ datap = *(command_parser_t **)nodep;
+ char *obj_str = strdup(object_type_str(datap->object_type));
+ to_lowercase(obj_str);
+
+ // List all objects
+ if (cmd_params->object_type == OBJECT_TYPE_UNDEFINED &&
+ cmd_params->action == ACTION_UNDEFINED) {
+ if (datap->object_type == prev_obj) goto FREE_STR;
+ prev_obj = datap->object_type;
+
+ printf("\thelp %s\n", obj_str);
+ goto FREE_STR;
+ }
+
+ // List actions for specific object
+ if (datap->object_type != cmd_params->object_type) goto FREE_STR;
+ if (cmd_params->action == ACTION_UNDEFINED) {
+ if (datap->action == prev_action) goto FREE_STR;
+ prev_action = datap->action;
+
+ printf("\thelp %s %s\n", obj_str, action_to_cmd_action(datap->action));
+ goto FREE_STR;
+ }
+
+ // List commands for specific object and action
+ if (datap->action != cmd_params->action) goto FREE_STR;
+ printf(" %s %s ", action_to_cmd_action(datap->action), obj_str);
+ for (int i = 0; i < datap->nparams; i++)
+ printf("<%s> ", datap->parameters[i].name);
+ printf("\n\n");
+ // List options' details
+ if (datap->nparams == 0) goto FREE_STR;
+ for (int i = 0; i < datap->nparams; i++)
+ printf("%16s: %s\n", datap->parameters[i].name, datap->parameters[i].help);
+ printf("\n");
+
+FREE_STR:
+ free(obj_str);
+}
+
+void command_list(hc_object_type_t object_type, hc_action_t action) {
+#if defined(__linux__) && !defined(__ANDROID__)
+ cmd_search_params_t cmd_params = {.object_type = object_type,
+ .action = action};
+ twalk_r(commands_root, traversal_action, &cmd_params);
+#else
+ fprintf(stderr, "twalk_r() function only available on linux");
+ (void)traversal_action;
+#endif
+}