21#ifndef G_NEW_PROCESS_H
22#define G_NEW_PROCESS_H
41 class NewProcessWaitable ;
64 G_EXCEPTION( Error ,
tx(
"cannot spawn new process") )
65 G_EXCEPTION( CannotFork ,
tx(
"cannot fork") )
66 G_EXCEPTION( WaitError ,
tx(
"failed waiting for child process") )
67 G_EXCEPTION( ChildError ,
tx(
"child process terminated abnormally") )
68 G_EXCEPTION( Insecure ,
tx(
"refusing to exec while the user-id is zero") )
69 G_EXCEPTION( PipeError ,
tx(
"pipe error") )
70 G_EXCEPTION( InvalidPath ,
tx(
"invalid executable path -- must be absolute") )
71 G_EXCEPTION( InvalidParameter ,
tx(
"invalid parameter") )
72 G_EXCEPTION( CreateProcessError ,
tx(
"CreateProcess error") ) ;
73 G_EXCEPTION( SystemError ,
tx(
"system error") ) ;
80 Fd(
bool null_ ,
bool pipe_ ,
int fd_ ) : m_null(null_) , m_pipe(pipe_) , m_fd(fd_) {}
81 static Fd pipe() {
return {
false,
true,-1} ; }
82 static Fd devnull() {
return {
true,
false,-1} ; }
83 static Fd fd(
int fd_) {
return fd_ < 0 ? devnull() :
Fd(
false,
false,fd_) ; }
84 bool operator==(
const Fd & other )
const {
return m_null == other.m_null && m_pipe == other.m_pipe && m_fd == other.m_fd ; }
85 bool operator!=(
const Fd & other )
const {
return !(*
this == other) ; }
91 using FormatFn = std::string (*)(std::string,int) ;
97 bool strict_exe {
true} ;
98 std::string exec_search_path ;
100 bool strict_id {
true} ;
101 bool close_other_fds {
true} ;
102 int exec_error_exit {127} ;
103 std::string exec_error_format ;
104 FormatFn exec_error_format_fn {
nullptr} ;
105 HANDLE keep_handle_1 {HNULL} ;
106 HANDLE keep_handle_2 {HNULL} ;
110 Config & set_stdout(
Fd ) noexcept ;
111 Config & set_stderr(
Fd ) noexcept ;
113 Config & set_strict_exe(
bool =
true ) noexcept ;
114 Config & set_exec_search_path(
const std::string & ) ;
116 Config & set_strict_id(
bool =
true ) noexcept ;
117 Config & set_close_other_fds(
bool =
true ) noexcept ;
118 Config & set_exec_error_exit(
int ) noexcept ;
119 Config & set_exec_error_format(
const std::string & ) ;
120 Config & set_exec_error_format_fn( FormatFn ) ;
165 int id() const noexcept ;
172 void kill(
bool yield = false ) noexcept ;
176 static
std::pair<
bool,pid_t>
fork() ;
189 static
std::
string execErrorFormat( const
std::
string & ,
int ) ;
192 std::unique_ptr<NewProcessImp> m_imp ;
219 void assign( pid_t pid ,
int fd ) ;
223 void assign( HANDLE hprocess , HANDLE hpipe ,
int ) ;
232 void waitp( std::promise<std::pair<int,std::string>> ) noexcept ;
251 int get( std::nothrow_t ,
int exit_code_on_error = 127 )
const noexcept ;
254 std::string output()
const ;
266 std::vector<char> m_buffer ;
267 std::size_t m_data_size {0U} ;
268 HANDLE m_hprocess {0} ;
275 int m_read_error {0} ;
276 bool m_test_mode {
false} ;
280inline G::NewProcess::Config & G::NewProcess::Config::set_stdin( Fd fd )
noexcept { stdin = fd ;
return *this ; }
281inline G::NewProcess::Config & G::NewProcess::Config::set_stdout( Fd fd )
noexcept { stdout = fd ;
return *this ; }
282inline G::NewProcess::Config & G::NewProcess::Config::set_stderr( Fd fd )
noexcept { stderr = fd ;
return *this ; }
283inline G::NewProcess::Config & G::NewProcess::Config::set_cd(
const Path & p ) { cd = p ;
return *this ; }
284inline G::NewProcess::Config & G::NewProcess::Config::set_strict_exe(
bool b )
noexcept { strict_exe = b ;
return *this ; }
285inline G::NewProcess::Config & G::NewProcess::Config::set_exec_search_path(
const std::string & s ) { exec_search_path = s ;
return *this ; }
286inline G::NewProcess::Config & G::NewProcess::Config::set_run_as( Identity i ) { run_as = i ;
return *this ; }
287inline G::NewProcess::Config & G::NewProcess::Config::set_strict_id(
bool b )
noexcept { strict_id = b ;
return *this ; }
288inline G::NewProcess::Config & G::NewProcess::Config::set_close_other_fds(
bool b )
noexcept { close_other_fds = b ;
return *this ; }
289inline G::NewProcess::Config & G::NewProcess::Config::set_exec_error_exit(
int n )
noexcept { exec_error_exit = n ;
return *this ; }
290inline G::NewProcess::Config & G::NewProcess::Config::set_exec_error_format(
const std::string & s ) { exec_error_format = s ;
return *this ; }
291inline G::NewProcess::Config & G::NewProcess::Config::set_exec_error_format_fn( FormatFn f ) { exec_error_format_fn = f ;
return *this ; }
Holds a set of environment variables and also provides static methods to wrap getenv() and putenv().
static Environment minimal(bool sbin=false)
Returns a minimal, safe set of environment variables.
A combination of user-id and group-id, with a very low-level interface to the get/set/e/uid/gid funct...
static Identity invalid() noexcept
Returns an invalid identity.
Holds the parameters and future results of a waitpid() system call.
A class for creating new processes.
int id() const noexcept
Returns the process id.
void kill(bool yield=false) noexcept
Tries to kill the spawned process and optionally yield to a thread that might be waiting on it.
static std::pair< bool, pid_t > fork()
A utility function that forks the calling process and returns twice; once in the parent and once in t...
NewProcessWaitable & waitable() noexcept
Returns a reference to the Waitable sub-object so that the caller can wait for the child process to e...
NewProcess(const Path &exe, const G::StringArray &args, const Config &)
Constructor.
A Path object represents a file system path.
std::vector< std::string > StringArray
A std::vector of std::strings.
constexpr const char * tx(const char *p) noexcept
A briefer alternative to G::gettext_noop().
Configuration structure for G::NewProcess.
Wraps up a file descriptor for passing to G::NewProcess.