about summary refs log tree commit diff
path: root/src/rt/rust_run_program.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rt/rust_run_program.cpp')
-rw-r--r--src/rt/rust_run_program.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/rt/rust_run_program.cpp b/src/rt/rust_run_program.cpp
new file mode 100644
index 00000000000..5919f68e844
--- /dev/null
+++ b/src/rt/rust_run_program.cpp
@@ -0,0 +1,92 @@
+#include "rust_internal.h"
+
+#if defined(__WIN32__)
+
+#include <process.h>
+#include <io.h>
+
+extern "C" CDECL int
+rust_run_program(void* task, const char* argv[],
+                 int in_fd, int out_fd, int err_fd) {
+    STARTUPINFO si;
+    ZeroMemory(&si, sizeof(STARTUPINFO));
+    si.cb = sizeof(STARTUPINFO);
+    si.dwFlags = STARTF_USESTDHANDLES;
+    si.hStdInput = (HANDLE)_get_osfhandle(in_fd ? in_fd : 0);
+    si.hStdOutput = (HANDLE)_get_osfhandle(out_fd ? out_fd : 1);
+    si.hStdError = (HANDLE)_get_osfhandle(err_fd ? err_fd : 2);
+
+    size_t cmd_len = 0;
+    for (const char** arg = argv; *arg; arg++) {
+        cmd_len += strlen(*arg);
+        cmd_len++; // Space or \0
+    }
+    char* cmd = (char*)malloc(cmd_len);
+    char* pos = cmd;
+    for (const char** arg = argv; *arg; arg++) {
+        strcpy(pos, *arg);
+        pos += strlen(*arg);
+        if (*(arg+1)) *(pos++) = ' ';
+    }
+
+    PROCESS_INFORMATION pi;
+    BOOL created = CreateProcess(NULL, cmd, NULL, NULL, TRUE,
+                                 0, NULL, NULL, &si, &pi);
+    free(cmd);
+
+    if (!created) return -1;
+    return (int)pi.hProcess;
+}
+
+extern "C" CDECL int
+rust_process_wait(void* task, int proc) {
+    DWORD status;
+    while (true) {
+        if (GetExitCodeProcess((HANDLE)proc, &status) &&
+            status != STILL_ACTIVE)
+            return (int)status;
+        WaitForSingleObject((HANDLE)proc, INFINITE);
+    }
+}
+
+#elif defined(__GNUC__)
+
+#include <sys/file.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <termios.h>
+
+extern "C" CDECL int
+rust_run_program(rust_task* task, char* argv[],
+                 int in_fd, int out_fd, int err_fd) {
+    int pid = fork();
+    if (pid != 0) return pid;
+
+    sigset_t sset;
+    sigemptyset(&sset);
+    sigprocmask(SIG_SETMASK, &sset, NULL);
+
+    if (in_fd) dup2(in_fd, 0);
+    if (out_fd) dup2(out_fd, 1);
+    if (err_fd) dup2(err_fd, 2);
+    /* Close all other fds. */
+    for (int fd = getdtablesize() - 1; fd >= 3; fd--) close(fd);
+    execvp(argv[0], argv);
+    exit(1);
+}
+
+#else
+#error "Platform not supported."
+#endif
+
+//
+// Local Variables:
+// mode: C++
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
+//