164 lines
5.0 KiB
C++
164 lines
5.0 KiB
C++
#pragma once
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
#include "childProcess.hpp"
|
|
|
|
/* All CONST references are used and cast away to allow for taking
|
|
both l and r values without using templates or making copies
|
|
|
|
implicitly convert to it but not to const char* and we want the
|
|
implicit conversion for quick scripting
|
|
arg pointers are kept and used not copied */
|
|
|
|
/* A shell command */
|
|
class Cmd
|
|
{
|
|
public:
|
|
/* all args must be const char* */
|
|
template<typename... Args>
|
|
explicit Cmd(Args... args)
|
|
: argv({args...})
|
|
{
|
|
argv.push_back(nullptr);
|
|
}
|
|
|
|
/* Execute the command, if arguments are not given use stdin,out,err
|
|
else use the given file desciptors. this can also be used
|
|
to redirect err to out by giving err=1 like in shell */
|
|
RetProc operator()(fd_t in=0, fd_t out=1, fd_t err=2);
|
|
|
|
/* Run the command, don't wait to return like shell's & */
|
|
Proc detach(fd_t in=0, fd_t out=1, fd_t err=2);
|
|
|
|
/* Append arguments */
|
|
void append_args(std::initializer_list<const char*>);
|
|
/* Append an argument and return the new command */
|
|
Cmd operator+(const char* arg);
|
|
/* Append an argument */
|
|
Cmd& operator+=(const char* arg);
|
|
|
|
std::vector<const char*> argv; /* null terminateded arg list */
|
|
};
|
|
|
|
/* An instance of a shell comand that is pending execution
|
|
if the command is not executed during the life of the obj
|
|
its executed on destruction */
|
|
class PendingCmd
|
|
{
|
|
public:
|
|
/* Can be implicitly created from a command */
|
|
PendingCmd(const Cmd&, fd_t in=0, fd_t out=1, fd_t err=2);
|
|
/* Execute the command on destruction */
|
|
~PendingCmd();
|
|
|
|
/* No copy we use unnamed return value optimization to return PendingCmd without destruction */
|
|
PendingCmd(const PendingCmd&) = delete;
|
|
PendingCmd& operator=(const PendingCmd&) = delete;
|
|
|
|
/* Run the command */
|
|
RetProc operator()();
|
|
/* Run the command, capturing the output in a new pipe */
|
|
RetProc runRedir();
|
|
|
|
/* Run the command async
|
|
shell: cmd &
|
|
becomes: cmd.detach() */
|
|
Proc detach();
|
|
/* Detach but redirect output to a pipe */
|
|
Proc detachRedirOut();
|
|
|
|
/* Prevent a pending command from being executed on destruction */
|
|
void cancel();
|
|
|
|
Cmd cmd;
|
|
fd_t in, out, err;
|
|
private:
|
|
bool execed_;
|
|
};
|
|
|
|
|
|
/* Anything that takes PendingCmd can take Cmd aswell */
|
|
|
|
/* Like shell's exec */
|
|
void exec(const Cmd&); /* todo: take Pending? */
|
|
|
|
/* Run commands in sequence
|
|
shell:
|
|
ls
|
|
cd
|
|
becomes:
|
|
ls,
|
|
cd;
|
|
*/
|
|
PendingCmd operator,(const PendingCmd&, const Cmd&);
|
|
PendingCmd operator,(RetProc, const Cmd&);
|
|
/* Forbiden funcion to prevent wrong sequencing such as:
|
|
echo, echo && echo
|
|
here the 2nd and 3rd echos would be ran before 1st
|
|
due to the C++ operator precedence*/
|
|
PendingCmd operator,(const PendingCmd&, RetProc) = delete;
|
|
|
|
|
|
/* Shell pipe operator | - execute two commands, second takes input
|
|
from first can be chained many times */
|
|
PendingCmd operator|(const PendingCmd&, const Cmd&);
|
|
|
|
/* Shell operator && - run the second command only if first returns 0 (no errors)*/
|
|
RetProc operator&&(const PendingCmd&, const Cmd&);
|
|
RetProc operator&&(RetProc, const Cmd&);
|
|
|
|
/* Shell operator || - run second only if first returns != 0
|
|
Operator precedence is different from shell, C precendence is && > ||
|
|
so mixing || and && may not compile, but shouldn't cause other issues,
|
|
use () to resolve these cases */
|
|
RetProc operator||(const PendingCmd&, const Cmd&);
|
|
RetProc operator||(RetProc, const Cmd&);
|
|
|
|
/* Shell operator > - redirect output to file
|
|
shell: cmd > file 2>&1
|
|
becomes: cmd > "file" >=1 */
|
|
PendingCmd& operator>(const PendingCmd&, const char* file);
|
|
/* A file descriptor can be given istead of a file path in which case
|
|
* no truncation occurs */
|
|
PendingCmd& operator>(const PendingCmd&, fd_t);
|
|
/* Same but append rather then truncate the file */
|
|
PendingCmd& operator>>(const PendingCmd&, const char* file);
|
|
PendingCmd& operator>>(const PendingCmd&, fd_t);
|
|
|
|
/* Redirect errors to file */
|
|
PendingCmd& operator>=(const PendingCmd&, const char* file);
|
|
PendingCmd& operator>=(const PendingCmd&, fd_t);
|
|
/* Same but append rather then truncate the file */
|
|
PendingCmd& operator>>=(const PendingCmd&, const char* file);
|
|
PendingCmd& operator>>=(const PendingCmd&, fd_t);
|
|
|
|
/* Shell oprator < use file as input */
|
|
PendingCmd& operator<(const PendingCmd&, const char* file);
|
|
PendingCmd& operator<(const PendingCmd&, fd_t);
|
|
|
|
/* Shell operator & but only for single processes
|
|
e.g.: echo a && echo b & echo c
|
|
in shell would detach "echo a && echo b" but here
|
|
this is not possible */
|
|
PendingCmd operator&(const PendingCmd&, const Cmd&);
|
|
|
|
/* string that is implicitly cast to const char* and doesn't deallocate
|
|
to allow for simpler synthax, speed and safety
|
|
e.g: echo + some_string
|
|
rather then: echo + some_string.c_str() */
|
|
class LeakStr: public std::basic_string<char> /* todo: allocator */
|
|
{
|
|
public:
|
|
using std::basic_string<char>::basic_string;
|
|
operator const char*() { return c_str();}
|
|
};
|
|
|
|
/* Execute a command and capture the output
|
|
shell:
|
|
var=$(ls)
|
|
becomes:
|
|
auto var = $(ls);
|
|
*/
|
|
LeakStr $(const PendingCmd&);
|