diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c72fe0f --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +################################################################################ +# This .gitignore file was automatically created by Microsoft(R) Visual Studio. +################################################################################ + +/.vs/uniproc/FileContentIndex +/.vs/uniproc/v17/ipch/AutoPCH +/.vs +/CppProperties.json +/include/tmp.cpp +/test.exe +/test.ilk +/test.pdb +/src/main.c diff --git a/include/uniproc.h b/include/uniproc.h new file mode 100644 index 0000000..5b35ed3 --- /dev/null +++ b/include/uniproc.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include +#include +#include +typedef struct { + FILE* in; + FILE* out; + FILE* err; + + // OS-dependent handle to the process + uint32_t _proc_hdl; + +} uniproc_process; + +uniproc_process uniproc_create_process(const char* cmd); +void uniproc_await_processes(uniproc_process* p, int* return_codes, size_t num_processes); +void uniproc_close_process(uniproc_process* p); diff --git a/src/uniproc_win64.c b/src/uniproc_win64.c new file mode 100644 index 0000000..5054c4e --- /dev/null +++ b/src/uniproc_win64.c @@ -0,0 +1,110 @@ +#if defined(_WIN32) || defined(_WIN64) +#include "uniproc.h" +#include +#include +#include + +uniproc_process uniproc_create_process(const char* cmd) +{ + // Create pipes + HANDLE child_in; + HANDLE in; + HANDLE child_out; + HANDLE out; + HANDLE child_err; + HANDLE err; + + SECURITY_ATTRIBUTES pipe_attribs; + pipe_attribs.nLength = sizeof(SECURITY_ATTRIBUTES); + pipe_attribs.bInheritHandle = 1; + pipe_attribs.lpSecurityDescriptor = NULL; + + // Actually create the pipes + if (!CreatePipe(&out, &child_out, &pipe_attribs, 0)) + exit(EXIT_FAILURE); + if (!CreatePipe(&err, &child_err, &pipe_attribs, 0)) + exit(EXIT_FAILURE); + if (!CreatePipe(&child_in, &in, &pipe_attribs, 0)) + exit(EXIT_FAILURE); + + // Unset inherrit flags for the pipes + if (!SetHandleInformation(out, HANDLE_FLAG_INHERIT, 0)) + exit(EXIT_FAILURE); + if (!SetHandleInformation(err, HANDLE_FLAG_INHERIT, 0)) + exit(EXIT_FAILURE); + if (!SetHandleInformation(in, HANDLE_FLAG_INHERIT, 0)) + exit(EXIT_FAILURE); + + // Create child process + uniproc_process p; + + size_t cmd_len = strlen(cmd); + char* p_cmd = malloc((cmd_len+1) * sizeof(char)); + memcpy(p_cmd, cmd, cmd_len * sizeof(char)); + p_cmd[cmd_len] = '\0'; + + PROCESS_INFORMATION p_info; + STARTUPINFOA p_startup; + memset(&p_info, 0, sizeof(PROCESS_INFORMATION)); + memset(&p_startup, 0, sizeof(STARTUPINFOA)); + + p_startup.cb = sizeof(STARTUPINFOA); + p_startup.dwFlags |= STARTF_USESTDHANDLES; + p_startup.hStdInput = child_in; + p_startup.hStdOutput = child_out; + p_startup.hStdError = child_err; + + int is_ok = CreateProcessA( + NULL,// Application name + p_cmd, // Command to execute + NULL,// Security attributes + NULL,// Primary thread security + 1, // Inherrit handles + 0, // Creation flags + NULL,// Environment (use parent's) + NULL,// Current directory (use parent's) + &p_startup, + &p_info + ); + free(p_cmd); + + if (!is_ok) + exit(EXIT_FAILURE); + + p.err = _fdopen(_open_osfhandle((intptr_t)err, _O_RDONLY), "r"); + p.out = _fdopen(_open_osfhandle((intptr_t)out, _O_RDONLY), "r"); + p.in = _fdopen(_open_osfhandle( (intptr_t)in, _O_WRONLY), "w"); + p._proc_hdl = (uint32_t)p_info.hProcess; + + CloseHandle(child_in); + CloseHandle(child_out); + CloseHandle(child_err); + CloseHandle(p_info.hThread); + + return p; +} + +void uniproc_await_processes(uniproc_process* p, int* return_codes, size_t num_processes) +{ + HANDLE* h = (HANDLE*)malloc(num_processes*sizeof(HANDLE)); + for (size_t i = 0; i < num_processes; ++i) + h[i] = (HANDLE)p[i]._proc_hdl; + + WaitForMultipleObjects(num_processes, h, 1, INFINITE); + free(h); + + if (return_codes == NULL) return; + for (size_t i = 0; i < num_processes; ++i) + GetExitCodeProcess((HANDLE)p[i]._proc_hdl, (LPDWORD)(return_codes+i)); +} + +void uniproc_close_process(uniproc_process* p) +{ + fclose(p->in); + fclose(p->out); + fclose(p->err); + + CloseHandle((HANDLE)p->_proc_hdl); +} + +#endif \ No newline at end of file