From aaeb54d534cd42fffb6f9dcb7cbd3456ceaa13b1 Mon Sep 17 00:00:00 2001 From: vaclavt Date: Sat, 2 Apr 2022 16:21:48 +0200 Subject: [PATCH] system-cmd-fork added --- debug.lsp | 19 +------------------ doc/Doc.md | 3 ++- ml.cpp | 17 +++++++++++++++++ ml_io.cpp | 29 +++++++++++++++++++++++++++++ ml_io.h | 3 +-- 5 files changed, 50 insertions(+), 21 deletions(-) diff --git a/debug.lsp b/debug.lsp index 2f6113c..979d01e 100644 --- a/debug.lsp +++ b/debug.lsp @@ -1,18 +1 @@ - -(def #sql_srv_address "stocksriddle.one") -(def #sql_srv_port 5388) - -(defn exec-sql (sql) -(do - (def r (tcp-client #sql_srv_address #sql_srv_port sql)) - (print r) - (first (eval (parse r))) -)) - -(def sql "select distinct to_string(datetime, '%d.%m.%Y'),symbol,time,title from history_earnings_dates where datetime>=to_date('2022-03-02', '%Y-%m-%d') and datetime<=to_date('2022-03-19', '%Y-%m-%d')") -(print "*" sql "*") -(def row (exec-sql sql)) -(print row) - -(exit 1) - +(system-cmd-fork "ml" "-c" "(print 123) (sleep 1) (print \"aaa\")") \ No newline at end of file diff --git a/doc/Doc.md b/doc/Doc.md index 67beb7d..82892ae 100644 --- a/doc/Doc.md +++ b/doc/Doc.md @@ -88,7 +88,8 @@ |`(read-file-lines filename lambda)`|Reads file and for each line call lambda with passing the line as a parameter|`(read-file-lines "/tmp/f.txt" (lambda (ln) (print ln))`|IO| |`(write-file filename content-str)`|Write a string to a file|`>>> (write-file "/tmp/a.txt" "test") => #t`|IO| |`(read-url url [headers] [body] [method])`|Reads URL. Returns list (status-code content)||IO| -|`(system-cmd command_str)`|Execute system command|`>>> (system-cmd "date") => (0 "Fri Feb 25 12:35:28 CET 2022\n")`|System| +|`(system-cmd command_str)`|Execute system command|`>>> (system-cmd-fork "ml" "-c" "(print 123) (sleep 1) (print \"aaa\")") => (0 "") >>> 123\n aaa`|System| +|`(system-cmd-fork cmd [par ..])`|Execute system command as an independent process|`>>> (system-cmd "date") => (0 "Fri Feb 25 12:35:28 CET 2022\n")`|System| |`(ls-dir dir)`|List a dir|List of directory entries|`>>> (ls-dir "/tmp") => ("." ".." "vscode-ipc-cccbe1dd-8c71-4028-a863-df975ad5887b.sock" "vscode-ipc-1163bb52-d088-41dc-80a5-81b6a7c7fa36.sock" "vscode-ipc-630f21df-26b5-43d4-8b2e-5175d53ce317.sock")`|IO| |`(is-file? filename)`|Returns true if passed filename is a file|`>>> (is-file? "/tmp") => nil`|IO| |`(is-dir? filename)`|Returns true if passed filename is a directory|`>>> (is-dir? "/tmp") => #t`|IO| diff --git a/ml.cpp b/ml.cpp index 5407ef7..40f1730 100644 --- a/ml.cpp +++ b/ml.cpp @@ -1331,6 +1331,22 @@ MlValue system_cmd(std::vector args, MlEnvironment &env) { return exec_system_cmd(args[0].as_string()); } +// Execute system command as forked process so its independent from its parrent +MlValue system_cmd_fork(std::vector args, MlEnvironment &env) { + eval_args(args, env); + + // TODO add support for more params constructing options as one string + if (args.size() < 1) + throw MlError(MlValue("system-cmd-fork", system_cmd_fork), env, TOO_FEW_ARGS); + + std::vector exec_args; + exec_args.reserve(args.size()); + for (auto const& a : args) + exec_args.emplace_back(a.as_string()); + + return exec_system_cmd_fork(exec_args); +} + // list directory MlValue ls_dir(std::vector args, MlEnvironment &env) { @@ -2241,6 +2257,7 @@ std::map builtin_funcs std::make_pair("write-file", builtin::write_file), std::make_pair("read-url", builtin::read_url), std::make_pair("system-cmd", builtin::system_cmd), + std::make_pair("system-cmd-fork", builtin::system_cmd_fork), std::make_pair("ls-dir", builtin::ls_dir), std::make_pair("is-file?", builtin::is_file), std::make_pair("is-dir?", builtin::is_dir), diff --git a/ml_io.cpp b/ml_io.cpp index c6fc4b4..918f7d6 100644 --- a/ml_io.cpp +++ b/ml_io.cpp @@ -109,3 +109,32 @@ MlValue exec_system_cmd(const std::string &cmd) { return std::vector { MlValue((long)cmd_retval), MlValue::string(cmd_output) }; } + + +MlValue exec_system_cmd_fork(const std::vector &args) { + int pid = fork(); + if (pid == 0) { + // Child process, execute the command + + std::vector exec_args; + exec_args.reserve(args.size()); + + for (auto const& a : args) + exec_args.emplace_back(const_cast(a.c_str())); + + exec_args.push_back(nullptr); // exec must end with null + + execvp(args[0].c_str(), exec_args.data()); + + std::cerr << "execvp error: " << errno << ", " << strerror(errno) << std::endl; + exit(1); // indicate error, if here + + } else if (pid > 0) { + // Parent process, child process is now independent + return std::vector { MlValue((long)0), MlValue::string("") }; + + } else { + // Fork error, still in parent process (there are no child process at this point) + return std::vector { MlValue((long)errno), MlValue::string(strerror(errno) ) }; + } +} \ No newline at end of file diff --git a/ml_io.h b/ml_io.h index 3939d77..b4771de 100644 --- a/ml_io.h +++ b/ml_io.h @@ -14,11 +14,10 @@ bool write_file_contents(const std::string &filename, const std::string &content MlValue list_dir(const std::string &path); bool is_path_file(const std::string &path); - bool is_path_dir(const std::string &path); bool mk_path_dir(const std::string &path); - bool rm_path_dir(const std::string &path); MlValue exec_system_cmd(const std::string &path); +MlValue exec_system_cmd_fork(const std::vector &args);