Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add command descriptor property to automatically sort subcommands #732

Merged
merged 4 commits into from
Mar 2, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions librz/core/cautocmpl.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ static void autocmplt_cmd_arg_file(RzLineNSCompletionResult *res, const char *s,

static void autocmplt_cmd_arg_env(RzLineNSCompletionResult *res, const char *s, size_t len) {
char **env;
res->end_string = "";
for (env = rz_sys_get_environ(); *env; env++) {
const char *eq = strchr(*env, '=');
char *envkey = eq ? rz_str_ndup(*env, eq - *env) : strdup(*env);
Expand Down
2 changes: 1 addition & 1 deletion librz/core/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -6638,7 +6638,7 @@ RZ_API void rz_core_cmd_init(RzCore *core) {
{ "z", "zignatures", rz_cmd_zign },
};

core->rcmd = rz_cmd_new(!!core->cons, true);
core->rcmd = rz_cmd_new(!!core->cons);
core->rcmd->macro.user = core;
core->rcmd->macro.num = core->num;
core->rcmd->macro.cmd = core_cmd0_wrapper;
Expand Down
88 changes: 51 additions & 37 deletions librz/core/cmd_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ static const RzCmdDescHelp not_defined_help = {
static const RzCmdDescHelp root_help = {
.usage = "[.][times][cmd][~grep][@[@iter]addr!size][|>pipe] ; ...",
.description = "",
.sort_subcommands = true,
};

static const struct argv_modes_t {
Expand Down Expand Up @@ -81,7 +82,13 @@ static int value = 0;
#define NCMDS (sizeof(cmd->cmds) / sizeof(*cmd->cmds))
RZ_LIB_VERSION(rz_cmd);

static bool cmd_desc_set_parent(RzCmdDesc *cd, RzCmdDesc *parent) {
static int cd_sort(const void *a, const void *b) {
RzCmdDesc *ca = (RzCmdDesc *)a;
RzCmdDesc *cb = (RzCmdDesc *)b;
return rz_str_casecmp(ca->name, cb->name);
}

static bool cmd_desc_set_parent(RzCmd *cmd, RzCmdDesc *cd, RzCmdDesc *parent) {
rz_return_val_if_fail(cd && !cd->parent, false);
if (parent) {
switch (parent->type) {
Expand All @@ -99,6 +106,9 @@ static bool cmd_desc_set_parent(RzCmdDesc *cd, RzCmdDesc *parent) {
if (parent) {
cd->parent = parent;
rz_pvector_push(&parent->children, cd);
if (!cmd->batch && parent->help->sort_subcommands) {
rz_pvector_sort(&parent->children, cd_sort);
}
parent->n_children++;
}
return true;
Expand Down Expand Up @@ -148,7 +158,7 @@ static RzCmdDesc *create_cmd_desc(RzCmd *cmd, RzCmdDesc *parent, RzCmdDescType t
if (ht_insert && !ht_pp_insert(cmd->ht_cmds, name, res)) {
goto err;
}
cmd_desc_set_parent(res, parent);
cmd_desc_set_parent(cmd, res, parent);
return res;
err:
cmd_desc_free(res);
Expand All @@ -161,7 +171,7 @@ RZ_API void rz_cmd_alias_init(RzCmd *cmd) {
cmd->aliases.values = NULL;
}

RZ_API RzCmd *rz_cmd_new(bool has_cons, bool add_core_plugins) {
RZ_API RzCmd *rz_cmd_new(bool has_cons) {
int i;
RzCmd *cmd = RZ_NEW0(RzCmd);
if (!cmd) {
Expand All @@ -175,9 +185,6 @@ RZ_API RzCmd *rz_cmd_new(bool has_cons, bool add_core_plugins) {
cmd->nullcallback = cmd->data = NULL;
cmd->ht_cmds = ht_pp_new0();
cmd->root_cmd_desc = create_cmd_desc(cmd, NULL, RZ_CMD_DESC_TYPE_GROUP, "", &root_help, true);
if (add_core_plugins) {
rz_core_plugin_init(cmd);
}
rz_cmd_macro_init(&cmd->macro);
rz_cmd_alias_init(cmd);
return cmd;
Expand All @@ -192,9 +199,6 @@ RZ_API RzCmd *rz_cmd_free(RzCmd *cmd) {
rz_cmd_alias_free(cmd);
rz_cmd_macro_fini(&cmd->macro);
ht_pp_free(cmd->ht_cmds);
// dinitialize plugin commands
rz_core_plugin_fini(cmd);
rz_list_free(cmd->plist);
rz_list_free(cmd->lcmds);
for (i = 0; i < NCMDS; i++) {
if (cmd->cmds[i]) {
Expand All @@ -206,10 +210,48 @@ RZ_API RzCmd *rz_cmd_free(RzCmd *cmd) {
return NULL;
}

/**
* \brief Get the root command descriptor
*/
RZ_API RzCmdDesc *rz_cmd_get_root(RzCmd *cmd) {
return cmd->root_cmd_desc;
}

/**
* \brief Mark the start of the batched changes to RzCmd
*
* Commands added after this call won't be sorted until \p rz_cmd_batch_end is
* called.
*/
RZ_API void rz_cmd_batch_start(RzCmd *cmd) {
cmd->batch = true;
}

static void sort_groups(RzCmdDesc *group) {
void **it_cd;

if (group->help->sort_subcommands) {
rz_pvector_sort(&group->children, cd_sort);
}
rz_cmd_desc_children_foreach(group, it_cd) {
RzCmdDesc *cd = *(RzCmdDesc **)it_cd;
if (cd->n_children) {
sort_groups(cd);
}
}
}

/**
* \brief Mark the end of the batched changes to RzCmd
*
* All groups are sorted, if necessary. Call \p rz_cmd_batch_start before using
* this function.
*/
RZ_API void rz_cmd_batch_end(RzCmd *cmd) {
cmd->batch = false;
sort_groups(rz_cmd_get_root(cmd));
}

static RzOutputMode suffix2mode(const char *suffix) {
size_t i;
for (i = 0; i < RZ_ARRAY_SIZE(argv_modes); i++) {
Expand Down Expand Up @@ -417,8 +459,6 @@ RZ_API int rz_cmd_del(RzCmd *cmd, const char *command) {
RZ_API int rz_cmd_call(RzCmd *cmd, const char *input) {
struct rz_cmd_item_t *c;
int ret = -1;
RzListIter *iter;
RzCorePlugin *cp;
rz_return_val_if_fail(cmd && input, -1);
if (!*input) {
if (cmd->nullcallback) {
Expand All @@ -436,12 +476,6 @@ RZ_API int rz_cmd_call(RzCmd *cmd, const char *input) {
input = nstr;
}
}
rz_list_foreach (cmd->plist, iter, cp) {
if (cp->call && cp->call(cmd->data, input)) {
free(nstr);
return true;
}
}
if (!*input) {
free(nstr);
return -1;
Expand Down Expand Up @@ -626,26 +660,6 @@ static RzCmdStatus call_cd(RzCmd *cmd, RzCmdDesc *cd, RzCmdParsedArgs *args) {
}

RZ_API RzCmdStatus rz_cmd_call_parsed_args(RzCmd *cmd, RzCmdParsedArgs *args) {
RzCmdStatus res = RZ_CMD_STATUS_INVALID;

// As old RzCorePlugin do not register new commands in RzCmd, we have no
// way of knowing if one of those is able to handle the input, so we
// have to pass the input to all of them before looking into the
// RzCmdDesc tree
RzListIter *iter;
RzCorePlugin *cp;
char *exec_string = rz_cmd_parsed_args_execstr(args);
rz_list_foreach (cmd->plist, iter, cp) {
if (cp->call && cp->call(cmd->data, exec_string)) {
res = RZ_CMD_STATUS_OK;
break;
}
}
RZ_FREE(exec_string);
if (res == RZ_CMD_STATUS_OK) {
return res;
}

RzCmdDesc *cd = rz_cmd_get_desc(cmd, rz_cmd_parsed_args_cmd(args));
if (!cd) {
return RZ_CMD_STATUS_NONEXISTINGCMD;
Expand Down
2 changes: 2 additions & 0 deletions librz/core/cmd_descs/cmd_descs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3269,6 +3269,7 @@ static const RzCmdDescHelp grep_help = {

RZ_IPI void newshell_cmddescs_init(RzCore *core) {
RzCmdDesc *root_cd = rz_cmd_get_root(core->rcmd);
rz_cmd_batch_start(core->rcmd);

RzCmdDesc *cmd_system_cd = rz_cmd_desc_oldinput_new(core->rcmd, root_cd, "!", rz_cmd_system, &cmd_system_help);
rz_warn_if_fail(cmd_system_cd);
Expand Down Expand Up @@ -3944,4 +3945,5 @@ RZ_IPI void newshell_cmddescs_init(RzCore *core) {

RzCmdDesc *grep_cd = rz_cmd_desc_fake_new(core->rcmd, root_cd, "~", &grep_help);
rz_warn_if_fail(grep_cd);
rz_cmd_batch_end(core->rcmd);
}
2 changes: 2 additions & 0 deletions librz/core/cmd_descs/cmd_descs_generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
{helps}
RZ_IPI void newshell_cmddescs_init(RzCore *core) {{
\tRzCmdDesc *root_cd = rz_cmd_get_root(core->rcmd);
\trz_cmd_batch_start(core->rcmd);
{init_code}
\trz_cmd_batch_end(core->rcmd);
}}
"""

Expand Down
4 changes: 2 additions & 2 deletions librz/core/cmd_plugins.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ RZ_IPI int rz_cmd_plugins(void *data, const char *input) {
case 'j': {
rz_cons_printf("[");
bool is_first_element = true;
rz_list_foreach (core->rcmd->plist, iter, cp) {
rz_list_foreach (core->plugins, iter, cp) {
rz_cons_printf("%s{\"Name\":\"%s\",\"Description\":\"%s\"}",
is_first_element ? "" : ",", cp->name, cp->desc);
is_first_element = false;
Expand All @@ -81,7 +81,7 @@ RZ_IPI int rz_cmd_plugins(void *data, const char *input) {
}
case 0:
rz_lib_list(core->lib);
rz_list_foreach (core->rcmd->plist, iter, cp) {
rz_list_foreach (core->plugins, iter, cp) {
rz_cons_printf("%s: %s\n", cp->name, cp->desc);
}
break;
Expand Down
3 changes: 3 additions & 0 deletions librz/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2605,6 +2605,8 @@ RZ_API bool rz_core_init(RzCore *core) {
core->offset = 0LL;
core->prompt_offset = 0LL;
rz_core_cmd_init(core);
rz_core_plugin_init(core);

core->dbg = rz_debug_new(true);

rz_io_bind(core->io, &(core->dbg->iob));
Expand Down Expand Up @@ -2680,6 +2682,7 @@ RZ_API void rz_core_fini(RzCore *c) {
if (!c) {
return;
}
rz_core_plugin_fini(c);
rz_core_task_break_all(&c->tasks);
rz_core_task_join(&c->tasks, NULL, -1);
rz_core_wait(c);
Expand Down
53 changes: 20 additions & 33 deletions librz/core/cplugin.c
Original file line number Diff line number Diff line change
@@ -1,61 +1,48 @@
// SPDX-License-Identifier: LGPL-3.0-only

/* covardly copied from rz_cmd */

#include <config.h>
#include <rz_core.h>
#include <rz_cmd.h>
#include <rz_list.h>
#include <stdio.h>

static RzCorePlugin *cmd_static_plugins[] = {
static RzCorePlugin *core_static_plugins[] = {
RZ_CORE_STATIC_PLUGINS
};

RZ_API int rz_core_plugin_fini(RzCmd *cmd) {
RZ_API bool rz_core_plugin_fini(RzCore *core) {
rz_return_val_if_fail(core->plugins, false);

RzListIter *iter;
RzCorePlugin *plugin;
if (!cmd->plist) {
return false;
}
rz_list_foreach (cmd->plist, iter, plugin) {
if (plugin && plugin->fini) {
plugin->fini(cmd, NULL);
rz_list_foreach (core->plugins, iter, plugin) {
if (plugin->fini) {
plugin->fini(core);
}
}
/* empty the list */
rz_list_free(cmd->plist);
cmd->plist = NULL;
rz_list_free(core->plugins);
core->plugins = NULL;
return true;
}

RZ_API int rz_core_plugin_add(RzCmd *cmd, RzCorePlugin *plugin) {
if (!cmd || (plugin && plugin->init && !plugin->init(cmd, NULL))) {
RZ_API bool rz_core_plugin_add(RzCore *core, RzCorePlugin *plugin) {
rz_return_val_if_fail(core, false);
rz_return_val_if_fail(plugin && plugin->init && plugin->name && plugin->author && plugin->license, false);
if (!plugin->init(core)) {
return false;
}
rz_list_append(cmd->plist, plugin);
rz_list_append(core->plugins, plugin);
return true;
}

RZ_API int rz_core_plugin_init(RzCmd *cmd) {
RZ_API bool rz_core_plugin_init(RzCore *core) {
int i;
cmd->plist = rz_list_newf(NULL); // memleak or dblfree
for (i = 0; cmd_static_plugins[i]; i++) {
if (!rz_core_plugin_add(cmd, cmd_static_plugins[i])) {
eprintf("Error loading cmd plugin\n");
core->plugins = rz_list_newf(NULL); // memleak or dblfree
for (i = 0; core_static_plugins[i]; i++) {
if (!rz_core_plugin_add(core, core_static_plugins[i])) {
eprintf("Error loading core plugin\n");
return false;
}
}
return true;
}

RZ_API int rz_core_plugin_check(RzCmd *cmd, const char *a0) {
RzListIter *iter;
RzCorePlugin *cp;
rz_list_foreach (cmd->plist, iter, cp) {
if (cp->call(NULL, a0)) {
return true;
}
}
return false;
}
}
14 changes: 12 additions & 2 deletions librz/core/libs.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,20 @@
static int __lib_##x##_dt(RzLibPlugin *pl, void *p, void *u) { return true; }

// XXX api consistency issues
static int __lib_core_cb(RzLibPlugin *pl, void *user, void *data) {
struct rz_core_plugin_t *hand = (struct rz_core_plugin_t *)data;
RzCore *core = (RzCore *)user;
pl->free = NULL;
rz_core_plugin_add(core, hand);
return true;
}

static int __lib_core_dt(RzLibPlugin *pl, void *p, void *u) {
return true;
}

#define rz_io_add rz_io_plugin_add
CB_COPY(io, io)
#define rz_core_add rz_core_plugin_add
CB(core, rcmd)
#define rz_debug_add rz_debug_plugin_add
CB(debug, dbg)
#define rz_bp_add rz_bp_plugin_add
Expand Down
14 changes: 3 additions & 11 deletions librz/core/p/core_java.c
Original file line number Diff line number Diff line change
Expand Up @@ -1643,12 +1643,8 @@ static const RzCmdDescHelp cmd_java_help = {
.args = cmd_java_args,
};

static int rz_cmd_java_init_handler(void *user, const char *unused) {
RzCmd *cmd = (RzCmd *)user;
if (!cmd) {
return false;
}

static bool rz_cmd_java_init_handler(RzCore *core) {
RzCmd *cmd = core->rcmd;
RzCmdDesc *root_cd = rz_cmd_get_root(cmd);
if (!root_cd) {
return false;
Expand All @@ -1659,17 +1655,13 @@ static int rz_cmd_java_init_handler(void *user, const char *unused) {
return cmd_java_cd != NULL;
}

static int rz_cmd_java_call_handler(void *user, const char *unused) {
return false;
}

// PLUGIN Definition Info
RzCorePlugin rz_core_plugin_java = {
.name = "java",
.desc = "Suite of java commands, java help for more info",
.author = "RizinOrg",
.license = "Apache",
.init = rz_cmd_java_init_handler,
.call = rz_cmd_java_call_handler,
};

#ifndef RZ_PLUGIN_INCORE
Expand Down
Loading