Implemented uniproc_unix.c for unix platforms

This commit is contained in:
2025-03-04 13:27:33 +11:00
parent 01602578fd
commit 4df03647ba

95
src/uniproc_unix.c Normal file
View File

@@ -0,0 +1,95 @@
#if defined(__linux__) || defined(__unix__)
#include <uniproc.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
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