Skip to content

Commit

Permalink
Initial implementation of r2pipe2 ##shell
Browse files Browse the repository at this point in the history
  • Loading branch information
trufae authored May 27, 2024
1 parent 7d4f360 commit 5f76b95
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 15 deletions.
98 changes: 96 additions & 2 deletions libr/core/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <r_core.h>
#include <r_vec.h>
#include <r_util/r_json.h>
#if R2__UNIX__
#include <sys/utsname.h>
#ifndef __wasi__
Expand Down Expand Up @@ -596,7 +597,6 @@ static bool print_aliases(void *use_b64, const void *key, const void *val) {
char *val_str = base64
? r_cmd_alias_val_strdup_b64 (v)
: r_cmd_alias_val_strdup (v);

r_cons_printf ("$%s=%s%s\n", k, base64? "base64:": "", val_str);
free (val_str);
}
Expand Down Expand Up @@ -956,8 +956,10 @@ static int cmd_alias(void *data, const char *input) {
} else {
r_core_cmd0 (core, (char *)v->data);
}
r_core_return_value (core, 0);
} else {
R_LOG_WARN ("No such alias \"$%s\"", buf);
R_LOG_ERROR ("No such alias \"$%s\"", buf);
r_core_return_value (core, 1);
}
}
free (buf);
Expand Down Expand Up @@ -3304,6 +3306,96 @@ static int cmd_last(void *data, const char *input) {
return 0;
}

static bool stderr_cb(void *user, int type, const char *origin, const char *msg) {
RList *stderr_list = (RList*)user;
if (!msg) {
return false;
}
PJ *j = pj_new ();
pj_o (j);
pj_ks (j, "type", r_log_level_tostring (type));
if (origin) {
pj_ks (j, "origin", origin);
}
if (msg) {
pj_ks (j, "message", msg);
}
pj_end (j);
r_list_append (stderr_list, pj_drain (j));
return true;
}

static int cmd_json(void *data, const char *input) {
RCore *core = (RCore *)data;
if (*input == '?') {
r_cons_printf ("Usage: {\"cmd\":\"...\",\"json\":false,\"trim\":true}\n");
r_cons_printf ("| The only required element is `cmd`\n");
return 0;
}
char *s_input = strdup (input - 1);
const RJson *j_cmd = NULL;
RJson *j = r_json_parse (s_input);
if (j) {
j_cmd = r_json_get (j, "cmd");
}
PJ *pj = pj_new ();
pj_o (pj);
if (j_cmd) {
const RJson *j_json = r_json_get (j, "json");
const RJson *j_trim = r_json_get (j, "trim");
bool is_json = false;
if (j_json && j_json->type == R_JSON_BOOLEAN) {
is_json = j_json->num.u_value == 1;
}
bool is_trim = false;
if (j_trim && j_trim->type == R_JSON_BOOLEAN) {
is_trim = j_trim->num.u_value == 1;
}
const char *r_cmd = j_cmd->str_value;
RList *stderr_list = r_list_newf (free);
// capture stderr
r_log_add_callback (stderr_cb, stderr_list);
char *res = r_core_cmd_str (core, r_cmd);
r_log_del_callback (stderr_cb);
if (is_trim) {
r_str_trim (res);
}
if (is_json) {
pj_k (pj, "res");
pj_raw (pj, res);
} else {
pj_ks (pj, "res", res);
}
free (res);
pj_kb (pj, "error", false);
pj_kn (pj, "value", core->num->value);
pj_kn (pj, "code", core->rc);
if (!r_list_empty (stderr_list)) {
pj_ka (pj, "logs");
char *m;
RListIter *iter;
r_list_foreach (stderr_list, iter, m) {
pj_raw (pj, m);
}
pj_end (pj);
}
r_list_free (stderr_list);
pj_kn (pj, "code", core->rc);
} else {
pj_ks (pj, "res", "");
pj_kb (pj, "error", true);
pj_kn (pj, "value", core->num->value);
pj_kn (pj, "code", core->rc);
}
pj_end (pj);
char *j_res = pj_drain (pj);
r_cons_printf ("%s\n", j_res);
free (j_res);
r_json_free (j);
free (s_input);
return 0;
}

static int cmd_system(void *data, const char *input) {
RCore *core = (RCore*)data;
ut64 n;
Expand Down Expand Up @@ -6112,6 +6204,7 @@ static int run_cmd_depth(RCore *core, char *cmd) {
R_API int r_core_cmd(RCore *core, const char *cstr, bool log) {
R_RETURN_VAL_IF_FAIL (core && cstr, 0);
R_LOG_DEBUG ("RCoreCmd: %s", cstr);
r_core_return_code (core, 0);
int ret = handle_command_call (core, cstr);
if (ret != -1) {
if (log) {
Expand Down Expand Up @@ -6565,6 +6658,7 @@ R_API void r_core_cmd_init(RCore *core) {
} cmds[] = {
{ "!", "run system command", cmd_system },
{ "_", "print last output", cmd_last },
{ "{", "run a command in json", cmd_json },
{ "#", "calculate hash", cmd_hash },
{ "$", "alias", cmd_alias },
{ "%", "short version of 'env' command", cmd_env },
Expand Down
38 changes: 25 additions & 13 deletions libr/util/json_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ static char *parse_key(const char **key, char *p) {
return NULL; // error
}

static char *parse_value(RJson *parent, const char *key, char *p) {
static char *parse_value(RJson *parent, R_NULLABLE const char *key, char *p) {
R_RETURN_VAL_IF_FAIL (parent && p, NULL);
RJson *js;
p = skip_whitespace (p); // TODO: use r_str_trim_head_ro()
if (!p) {
Expand Down Expand Up @@ -291,11 +292,14 @@ static char *parse_value(RJson *parent, const char *key, char *p) {
case '"':
p++;
js = create_json (R_JSON_STRING, key, parent);
js->str_value = unescape_string (p, &p);
if (!js->str_value) {
return NULL; // propagate error
if (js) {
js->str_value = unescape_string (p, &p);
if (!js->str_value) {
return NULL; // propagate error
}
return p;
}
return p;
return NULL;
case '-':
case '0':
case '1':
Expand Down Expand Up @@ -339,16 +343,22 @@ static char *parse_value(RJson *parent, const char *key, char *p) {
case 't':
if (r_str_startswith (p, "true")) {
js = create_json (R_JSON_BOOLEAN, key, parent);
js->num.u_value = 1;
return p + 4;
if (js) {
js->num.u_value = 1;
return p + 4;
}
return NULL;
}
R_LOG_ERROR ("unexpected chars (%s)", p);
return NULL; // error
case 'f':
if (r_str_startswith (p, "false")) {
js = create_json (R_JSON_BOOLEAN, key, parent);
js->num.u_value = 0;
return p + 5;
if (R_LIKELY (js)) {
js->num.u_value = 0;
return p + 5;
}
return NULL;
}
R_LOG_ERROR ("unexpected chars (%s)", p);
return NULL; // error
Expand All @@ -367,18 +377,18 @@ static char *parse_value(RJson *parent, const char *key, char *p) {
}

R_API R_MUSTUSE RJson *r_json_parse(R_BORROW char *text) {
R_RETURN_VAL_IF_FAIL (text, NULL);
RJson js = {0};
bool res = parse_value (&js, 0, text);
if (!res) {
if (js.children.first) {
r_json_free (js.children.first);
}
return 0;
r_json_free (js.children.first);
return NULL;
}
return js.children.first;
}

R_API const RJson *r_json_get(const RJson *json, const char *key) {
R_RETURN_VAL_IF_FAIL (json, NULL);
RJson *js;
for (js = json->children.first; js; js = js->next) {
if (js->key && !strcmp (js->key, key)) {
Expand All @@ -389,6 +399,7 @@ R_API const RJson *r_json_get(const RJson *json, const char *key) {
}

R_API const RJson *r_json_item(const RJson *json, size_t idx) {
R_RETURN_VAL_IF_FAIL (json, NULL);
RJson *js;
for (js = json->children.first; js; js = js->next) {
if (!idx--) {
Expand All @@ -399,6 +410,7 @@ R_API const RJson *r_json_item(const RJson *json, size_t idx) {
}

R_API const char *r_json_type(const RJson *json) {
R_RETURN_VAL_IF_FAIL (json, NULL);
switch (json->type) {
case R_JSON_ARRAY:
return "array";
Expand Down

0 comments on commit 5f76b95

Please sign in to comment.