template <typename CmdT>
std::string capture_exec(CmdT command, ExecResult &rescode,
const bool out, const bool err,
- const bool path)
+ const bool path, const bool env)
{
std::string output;
try
{
{
- inpipestream ips(command, out, err, path);
+ inpipestream ips(command, out, err, path, env);
ips.store_exit_status(&exit_set, &exit_status_waitpid);
* passed.
*/
std::string capture_exec (const std::string &command, ExecResult &res)
-{ return capture_exec<const std::string &>(command, res, true, false, false); }
+{ return capture_exec<const std::string &>(command, res, true, false, false, false); }
/** @brief Instantiation of \c capture_exec for argument lists. The
* pipestream used to run the command will not shell out.
* @returns Captured output, combined into one string.
*/
std::string capture_exec (const char *const *command, ExecResult &res,
- const bool out, const bool err, const bool path)
-{ return capture_exec<const char *const *>(command, res, out, err, path); }
+ const bool out, const bool err, const bool path,
+ const bool env)
+{ return capture_exec<const char *const *>(command, res, out, err, path, env); }
/** @brief Instantiation of \c capture_exec for argument lists. The
* pipestream used to run the command will not shell out.
* @returns Captured output, combined into one string.
*/
std::string capture_exec (const std::vector<std::string> &command, ExecResult &res,
- const bool out, const bool err, const bool path)
+ const bool out, const bool err, const bool path,
+ const bool env)
{
return capture_exec<const std::vector<std::string> &>
- (command, res, out, err, path);
+ (command, res, out, err, path, env);
}
#define PIPE_CTOR_FAIL(where) \
inpipebuf::init_without_shell (const char *const *argv,
const bool out,
const bool err,
- const bool path) const
+ const bool path,
+ const bool env) const
{
FILE *pipeobj = NULL;
int pipefd [2]; /* for reading output from the child */
int errfd [2]; /* for determining a successful exec() */
sigset_t oldmask, newmask;
+ char *const *envp = env ? environ : NULL;
if (!out && !err) {
errno = EINVAL;
errno = 0;
if (path) {
- execvpe (argv [0], const_cast <char *const *>(argv), environ);
+ execvpe (argv [0], const_cast <char *const *>(argv), envp);
} else {
- execve (argv [0], const_cast <char *const *>(argv), NULL);
+ execve (argv [0], const_cast <char *const *>(argv), envp);
}
(void)write (errfd [1], (char *)&errno, sizeof(errno));
inpipebuf::inpipebuf(const char *const *command,
const bool out,
const bool err,
- const bool path)
+ const bool path,
+ const bool env)
: pipe (NULL) /* brr: shadowing global ident */
, pid (-1)
, status_set (NULL)
}
std::pair <pid_t, FILE *> tmp =
- this->init_without_shell (command, out, err, path);
+ this->init_without_shell (command, out, err, path, env);
this->pid = tmp.first; /* no std::tie :/ */
this->pipe = tmp.second;
inpipebuf::inpipebuf(const std::vector<std::string> &command,
const bool out,
const bool err,
- const bool path)
+ const bool path,
+ const bool env)
: pipe (NULL) /* brr: shadowing global ident */
, pid (-1)
, status_set (NULL)
}
std::pair <pid_t, FILE *> tmp =
- this->init_without_shell (argv.get (), out, err, path);
+ this->init_without_shell (argv.get (), out, err, path, env);
this->pid = tmp.first;
this->pipe = tmp.second;
inpipebuf::inpipebuf(const std::string& command,
const bool _ignored_out,
const bool _ignored_err,
- const bool _ignored_path)
+ const bool _ignored_path,
+ const bool _ignored_env)
: pid (-1)
, status_set (NULL)
, exit_status (NULL)
std::string capture_exec(const std::string& command, ExecResult &rescode);
std::string capture_exec(const char *const *command, ExecResult &rescode,
const bool out=true, const bool err=false,
- const bool path=false);
+ const bool path=false, const bool env=false);
std::string capture_exec(const std::vector<std::string>& command, ExecResult &rescode,
const bool out=true, const bool err=false,
- const bool path=false);
+ const bool path=false, const bool env=false);
inline std::string capture_exec (const std::string &command)
{
public:
inpipebuf(const std::string& command,
- const bool out, const bool err, const bool path);
+ const bool out, const bool err, const bool path, const bool env);
inpipebuf(const char *const *command,
- const bool out, const bool err, const bool path);
+ const bool out, const bool err, const bool path, const bool env);
inpipebuf(const std::vector<std::string> &command,
- const bool out, const bool err, const bool path);
+ const bool out, const bool err, const bool path, const bool env);
~inpipebuf();
std::pair <pid_t, FILE *>
init_without_shell (const char *const *argv,
const bool out, const bool err,
- const bool path) const;
+ const bool path, const bool env) const;
};
/** @brief stream around inpipebuf -- see comment there */
public:
inpipestream(const std::string& command,
const bool out=true, const bool err=false,
- const bool path=false)
- : std::istream(&buf), buf(command, out, err, path)
+ const bool path=false, const bool env=false)
+ : std::istream(&buf), buf(command, out, err, path, env)
{}
inpipestream(const char *const command[],
const bool out=true, const bool err=false,
- const bool path=false)
- : std::istream(&buf), buf(command, out, err, path)
+ const bool path=false, const bool env=false)
+ : std::istream(&buf), buf(command, out, err, path, env)
{}
inpipestream(const std::vector<std::string> &command,
const bool out=true, const bool err=false,
- const bool path=false)
- : std::istream(&buf), buf(command, out, err, path)
+ const bool path=false, const bool env=false)
+ : std::istream(&buf), buf(command, out, err, path, env)
{}
void store_exit_status(bool *_status_set, int *_exit_status)
#define TO_CHARP_TOK(x) #x
#define TO_CHARP(x) TO_CHARP_TOK(x)
-BOOST_AUTO_TEST_SUITE(pipestream)
+#define I2N_EXTRA_ENV "I2N_EXTRA_ENV"
+
+struct Test_Pipestream_Fixture
+{
+ char **saved_environ;
+
+ Test_Pipestream_Fixture (void) : saved_environ (environ) { }
+
+ ~Test_Pipestream_Fixture (void) {
+ environ = this->saved_environ;
+ (void)unsetenv (I2N_EXTRA_ENV);
+ }
+};
+
+BOOST_FIXTURE_TEST_SUITE(pipestream, Test_Pipestream_Fixture)
BOOST_AUTO_TEST_SUITE(read)
BOOST_AUTO_TEST_SUITE_END() /* [pipestream->read] */
+ BOOST_AUTO_TEST_SUITE(env)
+
+ static const char *const env_argv_abs [] = { "/usr/bin/env", NULL };
+
+ #define I2N_EXTRA_ENVIRON I2N_EXTRA_ENV "=Yet verily, the rose is within the thorn."
+ static char *i2n_extra_environ [] =
+ { const_cast<char*> (I2N_EXTRA_ENVIRON)
+ , NULL
+ };
+
+ BOOST_AUTO_TEST_CASE(env_passthrough)
+ {
+ ExecResult exres = ExecResult ();
+ environ = i2n_extra_environ;
+
+ const std::string result =
+ capture_exec (env_argv_abs, exres, true, true, false, true);
+
+ BOOST_CHECK(exres.normal_exit);
+ BOOST_CHECK_EQUAL(exres.return_code, EXIT_SUCCESS);
+ BOOST_CHECK_EQUAL(result, (std::string)(I2N_EXTRA_ENVIRON "\n"));
+ }
+
+ BOOST_AUTO_TEST_CASE(env_nil)
+ {
+ ExecResult exres = ExecResult ();
+ environ = i2n_extra_environ;
+
+ const std::string result =
+ capture_exec (env_argv_abs, exres, true, true, false, false);
+
+ BOOST_CHECK(exres.normal_exit);
+ BOOST_CHECK_EQUAL(exres.return_code, EXIT_SUCCESS);
+ BOOST_CHECK_EQUAL(result, std::string());
+ }
+
+ BOOST_AUTO_TEST_SUITE_END() /* [pipestream->env] */
+
BOOST_AUTO_TEST_SUITE_END() /* [pipestream] */