Skip to content

Commit 0481255

Browse files
radaretrufae
authored andcommitted
Unify r2 and system shell command boundaries ##shell
1 parent 13be512 commit 0481255

3 files changed

Lines changed: 86 additions & 5 deletions

File tree

libr/core/cmd.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ static RCoreHelpMessage help_msg_triple_exclamation = {
436436
static RCoreHelpMessage help_msg_vertical_bar = {
437437
"Usage:", "[cmd] | [program|H|T|.|]", "",
438438
"|", " [program]", "pipe output of command to program",
439+
"|", " [program] | [program]", "pipe through multiple system programs",
440+
"|", " [program] \\&\\& ...", "escape ;, && and || to handle them in the system shell",
439441
"|", "", "disable scr.html and scr.color",
440442
"|.", "", "alias for .[cmd]",
441443
"|?", "", "show this help",
@@ -4389,11 +4391,45 @@ static char *find_unescaped_conditional(char *cmd, const char *quotes) {
43894391
cmd += 2;
43904392
}
43914393
char *and = find_unescaped_double_operator (cmd, '&', quotes);
4392-
char *pipe = (char *)r_str_firstbut_escape (cmd, '|', quotes);
4393-
if (!pipe || (and && and < pipe)) {
4394+
char *or = find_unescaped_double_operator (cmd, '|', quotes);
4395+
if (!or || (and && and < or)) {
43944396
return and;
43954397
}
4396-
return pipe[1] == '|'? pipe: NULL;
4398+
return or;
4399+
}
4400+
4401+
static void unescape_shell_control_operators(char *cmd) {
4402+
char quote = 0;
4403+
char *src = cmd;
4404+
char *dst = cmd;
4405+
while (*src) {
4406+
if (*src == '\\' && src[1]) {
4407+
if (!quote && src[1] == ';') {
4408+
*dst++ = ';';
4409+
src += 2;
4410+
continue;
4411+
}
4412+
if (!quote && (src[1] == '&' || src[1] == '|') &&
4413+
src[2] == '\\' && src[3] == src[1]) {
4414+
*dst++ = src[1];
4415+
*dst++ = src[1];
4416+
src += 4;
4417+
continue;
4418+
}
4419+
*dst++ = *src++;
4420+
*dst++ = *src++;
4421+
continue;
4422+
}
4423+
if (*src == '\'' || *src == '"') {
4424+
if (!quote) {
4425+
quote = *src;
4426+
} else if (quote == *src) {
4427+
quote = 0;
4428+
}
4429+
}
4430+
*dst++ = *src++;
4431+
}
4432+
*dst = 0;
43974433
}
43984434

43994435
static char *getarg(char *ptr) {
@@ -4733,6 +4769,11 @@ static int r_core_cmd_subst_i(RCore *core, char *cmd, char *colon, bool *tmpseek
47334769
return ret;
47344770
}
47354771
}
4772+
if (*cmd == '!') {
4773+
ret = r_cmd_call (core->rcmd, cmd);
4774+
r_list_free (tmpenvs);
4775+
return ret;
4776+
}
47364777
char *backtick = find_subcmd_begin (cmd, NULL);
47374778
if (backtick) {
47384779
goto escape_redir;
@@ -4821,8 +4862,9 @@ static int r_core_cmd_subst_i(RCore *core, char *cmd, char *colon, bool *tmpseek
48214862
return ret;
48224863
} else if (ptr[1]) { // "| grep .."
48234864
int value = core->num->value;
4865+
unescape_shell_control_operators (ptr + 1);
48244866
if (*cmd) {
4825-
r_core_cmd_pipe (core, cmd, ptr + 1);
4867+
ret = r_core_cmd_pipe (core, cmd, ptr + 1);
48264868
} else {
48274869
char *res = r_io_system (core->io, ptr + 1);
48284870
if (res) {
@@ -4832,7 +4874,7 @@ static int r_core_cmd_subst_i(RCore *core, char *cmd, char *colon, bool *tmpseek
48324874
}
48334875
r_core_return_value (core, value);
48344876
r_list_free (tmpenvs);
4835-
return 0;
4877+
return ret;
48364878
} else { // "|"
48374879
scr_html = r_config_get_b (core->config, "scr.html");
48384880
r_config_set_b (core->config, "scr.html", false);

test/db/cmd/cmd_system

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ yeah
1414
EOF
1515
RUN
1616

17+
NAME=system shell owns conditional operators
18+
FILE=-
19+
CMDS=<<EOF
20+
!echo LEFT && echo RIGHT
21+
!false || echo RECOVERED
22+
!printf PIPE 2>/dev/null | grep PIPE
23+
EOF
24+
EXPECT=<<EOF
25+
LEFT
26+
RIGHT
27+
RECOVERED
28+
PIPE
29+
EOF
30+
RUN
31+
1732
NAME=!| grep
1833
FILE=-
1934
CMDS=!echo fuck|grep bob

test/db/cmd/shell

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,30 @@ ERROR: Cannot find project file: /this/path/does/not/exist/r2-or.prj
8686
EOF
8787
RUN
8888

89+
NAME=system pipeline and r2 control boundaries
90+
FILE=malloc://32
91+
CMDS=<<EOF
92+
?e foo | grep foo | grep foo && ?e R2_AND
93+
?e nope | grep foo || ?e R2_OR
94+
?e foo | grep foo \&\& echo SHELL_AND && ?e R2_AFTER_SHELL_AND
95+
?e nope | grep foo \|\| echo SHELL_OR && ?e R2_AFTER_SHELL_OR
96+
?e foo | grep foo \; echo SHELL_SEMI;?e R2_SEMI
97+
EOF
98+
EXPECT=<<EOF
99+
foo
100+
R2_AND
101+
R2_OR
102+
foo
103+
SHELL_AND
104+
R2_AFTER_SHELL_AND
105+
SHELL_OR
106+
R2_AFTER_SHELL_OR
107+
foo
108+
SHELL_SEMI
109+
R2_SEMI
110+
EOF
111+
RUN
112+
89113
NAME=touch
90114
FILE=malloc://32-
91115
CMDS=<<EOF

0 commit comments

Comments
 (0)