diff --git a/src/liii_subprocess.cpp b/src/liii_subprocess.cpp index aa2d77a1..a4a2c4fe 100644 --- a/src/liii_subprocess.cpp +++ b/src/liii_subprocess.cpp @@ -21,6 +21,10 @@ #include #include +#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__EMSCRIPTEN__) +#include +#endif + namespace goldfish { using std::string; @@ -251,8 +255,13 @@ f_subprocess_run_values (s7_scheme* sc, s7_pointer args) { #ifdef TB_CONFIG_OS_WINDOWS process = tb_process_init_cmd (cmd_c, &attr); #else - tb_char_t const* sh_argv[] = {"sh", "-c", cmd_c, tb_null}; - process = tb_process_init ("/bin/sh", sh_argv, &attr); + wordexp_t p; + int ret= wordexp (cmd_c, &p, 0); + if (ret == 0 && p.we_wordc > 0) { + process= tb_process_init (p.we_wordv[0], (tb_char_t const**) p.we_wordv, + &attr); + wordfree (&p); + } #endif } else if (s7_is_pair (cmd_arg)) { diff --git a/tests/liii/subprocess/run-and-test.scm b/tests/liii/subprocess/run-and-test.scm index 3b647bad..4eac2ec6 100644 --- a/tests/liii/subprocess/run-and-test.scm +++ b/tests/liii/subprocess/run-and-test.scm @@ -38,11 +38,11 @@ (check (to-left (run-and "true" "false")) => '(1 "false")) (check (either-right? (run-and "true" "true" :cwd "/tmp")) => #t) (check (to-right (run-and "true" "true" :cwd "/tmp")) => 0) - (check (either-right? (run-and "test $FOO = bar" :env '(("FOO" . "bar")))) + (check (either-right? (run-and '(sh "-c" "test $FOO = bar") :env '(("FOO" . "bar")))) => #t ) ;check - (check (to-right (run-and "test $FOO = bar" :env '(("FOO" . "bar")))) => 0) + (check (to-right (run-and '(sh "-c" "test $FOO = bar") :env '(("FOO" . "bar")))) => 0) ;; :stdout only on last (let ((tmpfile "/tmp/gf-run-and-stdout.txt")) diff --git a/tests/liii/subprocess/run-either-test.scm b/tests/liii/subprocess/run-either-test.scm index 6e38a978..4a410b3b 100644 --- a/tests/liii/subprocess/run-either-test.scm +++ b/tests/liii/subprocess/run-either-test.scm @@ -61,8 +61,9 @@ (check (to-right (run-either "pwd" :cwd "/tmp" :stdout 'capture)) => "/tmp\n") ;; :env - (check (either-right? (run-either "echo $FOO" :env '(("FOO" . "bar")) :stdout 'capture)) => #t) - (check (to-right (run-either "echo $FOO" :env '(("FOO" . "bar")) :stdout 'capture)) => "bar\n") + (let ((result (run-either '(env) :env '(("FOO" . "bar")) :stdout 'capture))) + (check (either-right? result) => #t) + (check (string-contains? (to-right result) "FOO=bar") => #t)) ;; :input (check (either-right? (run-either "cat" :input "hello world" :stdout 'capture)) => #t) @@ -86,12 +87,12 @@ (check (to-right (run-either "echo hello" :stdout 'discard)) => "") ;; :stderr 'stdout - (check (either-right? (run-either "echo hello >&2" :stderr 'stdout)) => #t) - (check (to-right (run-either "echo hello >&2" :stderr 'stdout)) => "hello\n") + (check (either-right? (run-either "echo hello" :stderr 'stdout :stdout 'capture)) => #t) + (check (to-right (run-either "echo hello" :stderr 'stdout :stdout 'capture)) => "hello\n") ;; :stderr 'discard - (check (either-right? (run-either "echo hello >&2" :stderr 'discard)) => #t) - (check (to-right (run-either "echo hello >&2" :stderr 'discard)) => "") + (check (either-right? (run-either "echo hello" :stderr 'discard)) => #t) + (check (to-right (run-either "echo hello" :stderr 'discard)) => "hello\n") ;; list form with symbol head (check (either-right? (run-either '(printf "%s" "hello world") :stdout 'capture)) => #t) diff --git a/tests/liii/subprocess/run-test.scm b/tests/liii/subprocess/run-test.scm index 8848771b..168d47c8 100644 --- a/tests/liii/subprocess/run-test.scm +++ b/tests/liii/subprocess/run-test.scm @@ -11,7 +11,7 @@ ;; 参数 ;; ---- ;; command : string 或 list -;; 字符串形式通过 /bin/sh -c 执行,列表形式以 symbol 开头。 +;; 字符串形式通过 wordexp 拆分后直接执行,列表形式以 symbol 开头。 ;; ;; keyword value ... : 可选 ;; :cwd — 工作目录。 @@ -29,7 +29,7 @@ ;; ;; 说明 ;; ---- -;; 1. 字符串命令支持 shell 特性(通配符、变量展开等)。 +;; 1. 字符串命令通过 wordexp 拆分后执行,不支持 shell 管道等特性。 ;; 2. 列表形式以 symbol 开头,最终转换为字符串执行。 ;; 3. 命令中显式包含 cd 时不可同时设置 :cwd,否则抛 value-error。 @@ -54,7 +54,7 @@ (check-catch 'value-error (run '(cd "/tmp") :cwd "/home")) ;; :env - (check (run "test $FOO = bar" :env '(("FOO" . "bar"))) => 0) + (check (run '(sh "-c" "test $FOO = bar") :env '(("FOO" . "bar"))) => 0) ;; list form with symbol head (check (run '(printf "%s" "hello world")) => 0) diff --git a/tests/liii/subprocess/run-values-test.scm b/tests/liii/subprocess/run-values-test.scm index 163ae09a..3a848c07 100644 --- a/tests/liii/subprocess/run-values-test.scm +++ b/tests/liii/subprocess/run-values-test.scm @@ -39,8 +39,8 @@ ) ;let-values ;; :env - (let-values (((out err code) (run-values "echo $FOO" :env '(("FOO" . "bar")) :stdout 'capture))) - (check out => "bar\n") + (let-values (((out err code) (run-values '(env) :env '(("FOO" . "bar")) :stdout 'capture))) + (check (string-contains? out "FOO=bar") => #t) (check (zero? code) => #t) ) ;let-values @@ -77,14 +77,14 @@ ) ;let-values ;; :stderr 'stdout - (let-values (((out err code) (run-values "echo hello >&2" :stderr 'stdout))) + (let-values (((out err code) (run-values "echo hello" :stderr 'stdout :stdout 'capture))) (check out => "hello\n") (check err => "") (check (zero? code) => #t) ) ;let-values ;; :stderr 'discard - (let-values (((out err code) (run-values "echo hello >&2" :stderr 'discard))) + (let-values (((out err code) (run-values "echo hello" :stderr 'discard))) (check out => "") (check err => "") (check (zero? code) => #t)