Files
cppipe/childProcess.cpp
T
2023-10-07 19:38:27 +03:00

190 lines
3.3 KiB
C++

#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <cstring>
#include "childProcess.hpp"
RetProc::RetProc(Proc origin, int status)
: Proc(origin)
, normal_exit(WIFEXITED(status))
, returned(WEXITSTATUS(status))
{}
RetProc::operator bool()
{
return normal_exit && returned == 0;
}
/* create a process taking input from pipe childIn */
static Proc createProc(const char* const argv[], const fd_t childIn[2])
{
Proc childproc;
childproc.in = childIn[1];
childproc.out = STDOUT_FILENO;
childproc.pid = fork();
if(childproc.pid == 0) /* child */
{
close(childIn[1]);
dup2(childIn[0], STDIN_FILENO);
exec_or_die(argv);
}
return childproc;
}
/* create a process and redirect it's output to a pipe */
static Proc createRedirProc(const char* const argv[])
{
fd_t childOut[2];
pipe(childOut);
Proc childproc;
childproc.in = STDIN_FILENO;
childproc.out = childOut[0];
childproc.pid = fork();
/* close(STDIN_FILENO); flush?*/
if(childproc.pid != 0) /* parent */
{
close(childOut[1]);
}
else
{
dup2(childOut[1], STDOUT_FILENO);
exec_or_die(argv);
}
return childproc;
}
/* create a process redirecting both in and out */
static Proc createRedirProc(const char* const argv[], const fd_t childIn[2])
{
fd_t childOut[2]; /* todo: add error #include "processTypes.hpp"*/
pipe(childOut);
Proc childproc;
childproc.in = childIn[1];
childproc.out = childOut[0];
childproc.pid = fork();
/* close(STDIN_FILENO); flush?*/
if(childproc.pid != 0) /* parent */
{
close(childOut[1]);
}
else
{
close(childIn[1]);
dup2(childIn[0], STDIN_FILENO);
dup2(childOut[1], STDOUT_FILENO);
exec_or_die(argv);
}
return childproc;
}
Proc createRedirProcess(const char* const argv[], U32 flags) /* todo rename */
{
fd_t childIn[2];
Proc proc;
if(flags & INPUT)
{
pipe(childIn);
if(flags & OUTPUT)
proc = createRedirProc(argv, childIn);
else
proc = createProc(argv, childIn);
}
else if(flags & OUTPUT)
proc = createRedirProc(argv);
else
proc = createProcess(argv);
return proc;
}
Proc createCapProcess(const char* const argv[], fd_t in, fd_t err)
{
fd_t childOut[2];
pipe(childOut);
Proc proc;
proc.in = in;
proc.out = childOut[0];
proc.err = err;
proc.pid = fork();
if(proc.pid == 0) /* child */
{
if(in != STDIN_FILENO)
dup2(in, STDIN_FILENO);
dup2(childOut[1], STDOUT_FILENO);
if(err != STDERR_FILENO)
dup2(err, STDERR_FILENO);
exec_or_die(argv);
}
else
{
close(childOut[1]);
}
return proc;
}
Proc createProcess(const char* const argv[], fd_t in, fd_t out, fd_t err)
{
Proc proc;
proc.in = in;
proc.out = out;
proc.err = err;
proc.pid = fork();
if(proc.pid == 0) /* child */
{
if(in != STDIN_FILENO)
dup2(in, STDIN_FILENO);
if(out != STDOUT_FILENO)
dup2(out, STDOUT_FILENO);
if(err != STDERR_FILENO)
dup2(err, STDERR_FILENO);
exec_or_die(argv);
}
return proc;
}
RetProc runProcess(const char* const argv[], fd_t in, fd_t out, fd_t err)
{
Proc p = createProcess(argv, in, out, err);
// Wait to end
int status;
waitpid(p.pid, &status, 0);
return RetProc(p, status);
}
void exec_or_die(const char* const argv[])
{
execvp(argv[0], (char* const *)argv);
std::cerr << "Can't execute: " << argv[0] << ' ' << strerror(errno) << std::endl;
_exit(1); // _exit since we are a child
}