@@ -436,6 +436,8 @@ static RCoreHelpMessage help_msg_triple_exclamation = {
436436static 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
43994435static 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);
0 commit comments