diff options
Diffstat (limited to 'src/rt/rust_run_program.cpp')
| -rw-r--r-- | src/rt/rust_run_program.cpp | 92 |
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: +// |
