From 4df03647baa31ea42cd3f3df724a586f2a376726 Mon Sep 17 00:00:00 2001 From: Riley King-Saunders Date: Tue, 4 Mar 2025 13:27:33 +1100 Subject: [PATCH] Implemented uniproc_unix.c for unix platforms --- src/uniproc_unix.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/uniproc_unix.c diff --git a/src/uniproc_unix.c b/src/uniproc_unix.c new file mode 100644 index 0000000..aa7043b --- /dev/null +++ b/src/uniproc_unix.c @@ -0,0 +1,95 @@ +#if defined(__linux__) || defined(__unix__) +#include +#include +#include +#include +#include + + +uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, const char** argv) +{ + (void)num_args; + // Create pipes + int stdin_pipe[2]; + int stdout_pipe[2]; + int stderr_pipe[2]; + + if (pipe(stdin_pipe) == -1) + exit(EXIT_FAILURE); + if (pipe(stdout_pipe) == -1) + exit(EXIT_FAILURE); + if (pipe(stderr_pipe) == -1) + exit(EXIT_FAILURE); + + // Fork process + uniproc_process p; + p.in = stdin_pipe[1]; // Write handle + p.out = stdout_pipe[0]; // Read handle + p.err = stderr_pipe[0]; // Read handle + + pid_t pid = fork(); + if (pid == -1) + exit(EXIT_FAILURE); + // Child + else if (pid == 0) + { + // Redirect the child's std. files to the pipes created above + if (dup2(stdin_pipe[0], STDIN_FILENO) == -1) + exit(EXIT_FAILURE); + if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1) + exit(EXIT_FAILURE); + if (dup2(stdout_pipe[2], STDERR_FILENO) == -1) + exit(EXIT_FAILURE); + + // Close file handle references that are not needed + if (stdin_pipe[0] != -1) close(stdin_pipe[0]); + if (stdin_pipe[1] != -1) close(stdin_pipe[1]); + if (stdout_pipe[0] != -1) close(stdout_pipe[0]); + if (stdout_pipe[1] != -1) close(stdout_pipe[1]); + if (stderr_pipe[0] != -1) close(stderr_pipe[0]); + if (stderr_pipe[1] != -1) close(stderr_pipe[1]); + + // And execute the command provided + if (execvp(cmd, argv) == -1) + exit(EXIT_FAILURE); + } + // Parent + else + { + // Assign the process ID of the child to a variable + p._proc_hdl = pid; + + // Close reading its stdin and writing its stdouts + if (stdin_pipe[0] != -1) close(stdin_pipe[0]); + if (stdout_pipe[1] != -1) close(stdout_pipe[1]); + if (stderr_pipe[1] != -1) close(stderr_pipe[1]); + + // Get appropriate streams from descriptors and store them + p.in = fdopen(stdin_pipe[1], "a"); + p.out = fdopen(stdout_pipe[0], "r"); + p.out = fdopen(stderr_pipe[0], "r"); + } + return p; +} + +void uniproc_await_processes(uniproc_process* p, int* return_codes, size_t num_processes) +{ + int rc; + if (return_codes == NULL) + for (size_t i = 0; i < num_processes; ++i) + waitpid(p._proc_hdl, &rc, 0); + else + for (size_t i = 0; i < num_processes; ++i) + waitpid(p._proc_hdl, return_codes+i, 0); +} + +void uniproc_close_process(uniproc_process* p) +{ + kill(p->_proc_hdl, SIGKILL); + fclose(p->in); + fclose(p->out); + fclose(p->err); +} + + +#endif \ No newline at end of file