/** * Converts an environment to a char** table as used by execve(). * * Converts the environment's contents to the format used by the * execve() system call. The returned char** array is allocated * in dynamic memory; the caller must free it when not used any * more. Each entry is also allocated in dynamic memory and is a * NULL-terminated string of the form var=value; these must also be * released by the caller. * * This operation is only available on POSIX systems. * * \return The first argument of the pair is an integer that indicates * how many strings are stored in the second argument. The * second argument is a NULL-terminated, dynamically allocated * array of dynamically allocated strings representing the * enviroment's content. Each array entry is a NULL-terminated * string of the form var=value. The caller is responsible for * freeing them. */ inline std::pair<std::size_t, char **> environment_to_envp(const environment &env) { std::size_t nargs = env.size(); char **envp = new char *[nargs + 1]; environment::size_type i = 0; for (environment::const_iterator it = env.begin(); it != env.end(); ++it) { std::string s = it->first + "=" + it->second; envp[i] = new char[s.size() + 1]; std::strncpy(envp[i], s.c_str(), s.size() + 1); ++i; } envp[i] = 0; return std::pair<std::size_t, char **>(nargs, envp); } // environment_to_envp
inline pid_t posix_start(const Executable& exe, const Arguments& args, const environment& env, info_map& infoin, info_map& infoout, const posix_setup& setup) { pid_t pid = ::fork(); if (pid == -1) { boost::throw_exception (system_error("boost::process::detail::posix_start", "fork(2) failed", errno)); } else if (pid == 0) { #if defined(F_MAXFD) int maxdescs = std::max(::fcntl(0, F_MAXFD), 128); // XXX #else int maxdescs = 128; // XXX #endif try { boost::scoped_array< bool > closeflags(new bool[maxdescs]); for (int i = 0; i < maxdescs; i++) closeflags.get()[i] = true; setup_input(infoin, closeflags.get(), maxdescs); setup_output(infoout, closeflags.get(), maxdescs); for (int i = 0; i < maxdescs; i++) if (closeflags.get()[i]) ::close(i); setup(); } catch (const system_error& e) { ::write(STDERR_FILENO, e.what(), std::strlen(e.what())); ::write(STDERR_FILENO, "\n", 1); ::exit(EXIT_FAILURE); } std::pair< std::size_t, char** > argcv = collection_to_posix_argv(args); char** envp = environment_to_envp(env); ::execve(exe.c_str(), argcv.second, envp); system_error e("boost::process::detail::posix_start", "execve(2) failed", errno); for (std::size_t i = 0; i < argcv.first; i++) delete [] argcv.second[i]; delete [] argcv.second; for (std::size_t i = 0; i < env.size(); i++) delete [] envp[i]; delete [] envp; ::write(STDERR_FILENO, e.what(), std::strlen(e.what())); ::write(STDERR_FILENO, "\n", 1); ::exit(EXIT_FAILURE); } BOOST_ASSERT(pid > 0); for (info_map::iterator iter = infoin.begin(); iter != infoin.end(); iter++) { stream_info& si = (*iter).second; if (si.m_type == stream_info::use_pipe) si.m_pipe->rend().close(); } for (info_map::iterator iter = infoout.begin(); iter != infoout.end(); iter++) { stream_info& si = (*iter).second; if (si.m_type == stream_info::use_pipe) si.m_pipe->wend().close(); } return pid; }