Implemented uniproc_unix.c for unix platforms
This commit is contained in:
95
src/uniproc_unix.c
Normal file
95
src/uniproc_unix.c
Normal 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
|
||||
Reference in New Issue
Block a user