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