diff options
author | Alexander Gluzsky <sss123next@list.ru> | 2013-02-03 12:54:02 +0000 |
---|---|---|
committer | Alexander Gluzsky <sss123next@list.ru> | 2013-02-03 12:54:02 +0000 |
commit | 2637b7479c3e531f891346dbe84c73805a8b5e36 (patch) | |
tree | bdfe96ed34c5f08b856fa760c2cdc70ba6763352 | |
parent | 32e17cfa965980f07e8321fb29d38d62a2e1ad27 (diff) |
ability to change key password (because of fucked gpg which does not want to give us his stdin/stdout only via ugly windows console)
git-svn-id: http://svn.miranda-ng.org/main/trunk@3406 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
147 files changed, 10561 insertions, 8 deletions
diff --git a/plugins/New_GPG/src/commonheaders.h b/plugins/New_GPG/src/commonheaders.h index a3c451e2cd..e788db4375 100755 --- a/plugins/New_GPG/src/commonheaders.h +++ b/plugins/New_GPG/src/commonheaders.h @@ -52,11 +52,15 @@ using std::fstream; #include <boost/random/variate_generator.hpp> #include <boost/random/uniform_int.hpp> #include <boost/date_time.hpp> +#include <boost/iostreams/stream.hpp> +//boost process +#include <boost/process.hpp> //utf8cpp #include <utf8.h> + //miranda #include <newpluginapi.h> #include <m_database.h> diff --git a/plugins/New_GPG/src/gpg_wrapper.cpp b/plugins/New_GPG/src/gpg_wrapper.cpp index f253b2571e..adce958b50 100755 --- a/plugins/New_GPG/src/gpg_wrapper.cpp +++ b/plugins/New_GPG/src/gpg_wrapper.cpp @@ -173,3 +173,180 @@ void pxEexcute_thread(void *param) gpg_execution_params *params = (gpg_execution_params*)param; pxResult result = pxExecute(params->cmd, params->useless, params->out, params->code, params->result, params->hProcess, params->proc); } + + + +pxResult pxExecute_passwd_change(std::vector<std::wstring> &aargv, char *ainput, string *aoutput, LPDWORD aexitcode, pxResult *result, HANDLE hProcess, PROCESS_INFORMATION *pr, string &old_pass, string &new_pass) +{ +// gpg_mutex.lock(); + if(!gpg_valid) + return pxNotConfigured; + extern logtofile debuglog; + + TCHAR *bin_path = UniGetContactSettingUtf(NULL, szGPGModuleName, "szGpgBinPath", _T("")); + { + if(_waccess(bin_path, 0) == -1) + { + if(errno == ENOENT) + { + mir_free(bin_path); + if(bDebugLog) + debuglog<<std::string(time_str()+": GPG executable not found"); + *result = pxNotFound; + return pxNotFound; + } + } + } + + using namespace boost::process; + using namespace boost::process::initializers; + using namespace boost::iostreams; + + + std::vector<std::wstring> argv; + std::vector<std::wstring> env; + env.push_back(L"LANGUAGE=en@quot"); + env.push_back(L"LC_ALL=English"); + argv.push_back(bin_path); + argv.push_back(L"--homedir"); + TCHAR *home_dir = UniGetContactSettingUtf(NULL, szGPGModuleName, "szHomePath", _T("")); + argv.push_back(home_dir); + mir_free(home_dir); + argv.push_back(L"--display-charset"); + argv.push_back(L"utf-8"); + argv.push_back(L"-z9"); + argv.insert(argv.end(), aargv.begin(), aargv.end()); + +// pipe pout = create_pipe(); + pipe pin = create_pipe(); +// file_descriptor_sink sout(pout.sink, close_handle); + file_descriptor_source sin(pin.source, close_handle); + + char *mir_path = new char [MAX_PATH]; + CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path); + + //execute(set_args(argv), bind_stdout(sout), bind_stdin(sin), show_window(SW_HIDE), hide_console(), inherit_env(), set_env(env), start_in_dir(toUTF16(mir_path))); + child c = execute(set_args(argv), bind_stdin(sin), inherit_env(), set_env(env), start_in_dir(toUTF16(mir_path))); + //child c = execute(run_exe("c:\\windows\\system32\\cmd.exe"), bind_stdin(sin), inherit_env(), set_env(env), start_in_dir(toUTF16(mir_path))); + + delete [] mir_path; + +// file_descriptor_source source(pout.source, close_handle); +/* file_descriptor_sink _sin(pin.sink, close_handle); + + stream<file_descriptor_sink> out(_sin); + + + std::wstring cmd; + for(int i = 0; i < argv.size(); i++) + { + cmd += argv[i]; + cmd += L" "; + } + */ +// out<<toUTF8(cmd)<<std::endl; + + //fucked gpg does not want to give us stdin/stdout + wait_for_exit(c); + +/* out<<old_pass<<std::endl; + out<<new_pass<<std::endl; + out<<new_pass<<std::endl; + out<<"save"<<std::endl; */ + +// stream<file_descriptor_source> is(source); +/* std::string s; + + is>>s; + + MessageBoxA(NULL, s.c_str(), "", MB_OK); */ + + +/* ctx.environment = boost::process::self::get_environment(); + ctx.environment.insert(boost::process::environment::value_type("LANGUAGE", "en@quot")); + ctx.environment["LC_ALL"] = "English"; + + char *mir_path = new char [MAX_PATH]; + CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)"\\", (LPARAM)mir_path); + ctx.work_directory = mir_path; + delete [] mir_path; + + boost::process::win32_child proc = boost::process::win32_launch(toUTF8(bin_path), argv, ctx); + + mir_free(bin_path); + +// boost::process::pistream &_stdout = proc.get_stdout(); + boost::process::postream &_stdin = proc.get_stdin(); + + boost::this_thread::sleep(boost::posix_time::milliseconds(50)); + + std::string buf; */ + + +/* std::getline(_stdout, buf); + while(_stdout.good()) + { + *aoutput += buf; + if(aoutput->find("Enter passphrase") != std::string::npos) + break; + boost::this_thread::sleep(boost::posix_time::milliseconds(50)); + std::getline(_stdout, buf); + } + *aoutput += buf; */ + + //_stdin<<old_pass<<std::endl; + +/* std::getline(_stdout, buf); + while(_stdout.good()) + { + *aoutput += buf; + if(aoutput->find("Enter the new passphrase for this secret key.") != std::string::npos) + break; + boost::this_thread::sleep(boost::posix_time::milliseconds(50)); + std::getline(_stdout, buf); + } + + *aoutput += buf; + + if(aoutput->find("Enter passphrase") != std::string::npos)*/ + //_stdin<<new_pass<<std::endl; + +/* std::getline(_stdout, buf); + while(_stdout.good()) + { + *aoutput += buf; + if(aoutput->find("Repeat passphrase") != std::string::npos) + break; + boost::this_thread::sleep(boost::posix_time::milliseconds(50)); + std::getline(_stdout, buf); + } + *aoutput += buf; */ + + //_stdin<<new_pass<<std::endl; + +/* std::getline(_stdout, buf); + while(_stdout.good()) + { + *aoutput += buf; + if(aoutput->find("Command") != std::string::npos) + break; + boost::this_thread::sleep(boost::posix_time::milliseconds(50)); + std::getline(_stdout, buf); + } + *aoutput += buf; */ + + //_stdin<<"save"<<std::endl; + + //proc.wait(); + + //MessageBoxA(NULL, aoutput->c_str(), "info", MB_OK); + + return pxSuccess; +} + + +void pxEexcute_passwd_change_thread(void *param) +{ + gpg_execution_params_pass *params = (gpg_execution_params_pass*)param; + pxResult result = pxExecute_passwd_change(params->args, params->useless, params->out, params->code, params->result, params->hProcess, params->proc, params->old_pass, params->new_pass); +} diff --git a/plugins/New_GPG/src/gpg_wrapper.h b/plugins/New_GPG/src/gpg_wrapper.h index 5501297baf..44b2f4f493 100755 --- a/plugins/New_GPG/src/gpg_wrapper.h +++ b/plugins/New_GPG/src/gpg_wrapper.h @@ -32,7 +32,8 @@ typedef enum { } pxResult; -pxResult pxExecute(wstring *acommandline, char *ainput, string *aoutput, LPDWORD aexitcode, pxResult *result); +pxResult pxExecute(wstring *acommandline, char *ainput, string *aoutput, LPDWORD aexitcode, pxResult *result, HANDLE hProcess, PROCESS_INFORMATION *pr); +pxResult pxExecute_passwd_change(std::vector<std::string> &aargv, char *ainput, string *aoutput, LPDWORD aexitcode, pxResult *result, HANDLE hProcess, PROCESS_INFORMATION *pr, string &old_pass, string &new_pass); struct gpg_execution_params { @@ -45,6 +46,22 @@ struct gpg_execution_params PROCESS_INFORMATION *proc; }; +struct gpg_execution_params_pass +{ + std::vector<std::wstring> &args; + string &old_pass, &new_pass; + char *useless; + string *out; + LPDWORD code; + pxResult *result; + HANDLE hProcess; + PROCESS_INFORMATION *proc; + gpg_execution_params_pass(std::vector<std::wstring> &a, std::string &o, std::string &n): args(a), old_pass(o), new_pass(n) + {} +}; + + void pxEexcute_thread(void *param); +void pxEexcute_passwd_change_thread(void *param); #endif
\ No newline at end of file diff --git a/plugins/New_GPG/src/include/boost/process.hpp b/plugins/New_GPG/src/include/boost/process.hpp new file mode 100644 index 0000000000..2271e9b49e --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process.hpp @@ -0,0 +1,22 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011 Jeff Flinn, Boris Schaeling +// Copyright (c) 2012 Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process.hpp + * + * Convenience header which includes all public Boost.Process header files. + */ + +#ifndef BOOST_PROCESS_HPP +#define BOOST_PROCESS_HPP + +#include <boost/process/all.hpp> + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/all.hpp b/plugins/New_GPG/src/include/boost/process/all.hpp new file mode 100644 index 0000000000..234dd05d4c --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/all.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/all.hpp + * + * Convenience header which includes all public Boost.Process header files. + */ + +#ifndef BOOST_PROCESS_ALL_HPP +#define BOOST_PROCESS_ALL_HPP + +#include <boost/process/child.hpp> +#include <boost/process/create_pipe.hpp> +#include <boost/process/execute.hpp> +#include <boost/process/executor.hpp> +#include <boost/process/initializers.hpp> +#include <boost/process/pipe.hpp> +#include <boost/process/search_path.hpp> +#include <boost/process/shell_path.hpp> +#include <boost/process/terminate.hpp> +#include <boost/process/wait_for_exit.hpp> + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/child.hpp b/plugins/New_GPG/src/include/boost/process/child.hpp new file mode 100644 index 0000000000..ec129fc936 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/child.hpp @@ -0,0 +1,74 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/child.hpp + * + * Defines a child process class. + */ + +#ifndef BOOST_PROCESS_CHILD_HPP +#define BOOST_PROCESS_CHILD_HPP + +#include <boost/process/config.hpp> + +#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(child) +BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(child) + +#if defined(BOOST_PROCESS_DOXYGEN) +namespace boost { namespace process { + +/** + * Represents a child process. + * + * On Windows child is movable but non-copyable. The destructor + * automatically closes handles to the child process. + */ +struct child +{ + /** + * Process information. + * + * \remark <em>Windows only.</em> + */ + PROCESS_INFORMATION proc_info; + + /** + * Constructor. + * + * \remark <em>Windows only.<em/> + */ + explicit child(const PROCESS_INFORMATION &pi) : proc_info(pi) {} + + /** + * Returns the process handle. + * + * \remark <em>Windows only.</em> + */ + HANDLE process_handle() const { return proc_info.hProcess; } + + /** + * Process identifier. + * + * \remark <em>POSIX only.</em> + */ + pid_t pid; + + /** + * Constructor. + * + * \remark <em>POSIX only.</em> + */ + explicit child(pid_t p) : pid(p) {} +}; + +}} +#endif + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/config.hpp b/plugins/New_GPG/src/include/boost/process/config.hpp new file mode 100644 index 0000000000..7aae4d3ca4 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/config.hpp @@ -0,0 +1,82 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/config.hpp + * + * Defines various macros. + */ + +#ifndef BOOST_PROCESS_CONFIG_HPP +#define BOOST_PROCESS_CONFIG_HPP + +#include <boost/config.hpp> +#include <boost/system/config.hpp> +#include <boost/system/error_code.hpp> +#include <boost/system/system_error.hpp> + +#if defined(BOOST_POSIX_API) +# include <errno.h> +# define BOOST_PROCESS_LAST_ERROR errno +# define BOOST_PROCESS_PLATFORM posix +#elif defined(BOOST_WINDOWS_API) +# include <Windows.h> +# define BOOST_PROCESS_LAST_ERROR GetLastError() +# define BOOST_PROCESS_PLATFORM windows +#endif + +/** \cond */ +#define BOOST_PROCESS_PLATFORM_PROMOTE_PATH(COMPONENT) \ + <boost/process/BOOST_PROCESS_PLATFORM/COMPONENT.hpp> +#define BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(COMPONENT) \ + namespace boost { namespace process { using BOOST_PROCESS_PLATFORM::COMPONENT; }} +#define BOOST_PROCESS_PLATFORM_PROMOTE_INITIALIZERS_NAMESPACE \ + namespace boost { namespace process { namespace initializers { \ + using namespace boost::process::BOOST_PROCESS_PLATFORM::initializers; }}} +/** \endcond */ + +#if defined(BOOST_PROCESS_DOXYGEN) +/** + * \def BOOST_POSIX_API + * + * This macro is defined on POSIX. + */ +#define BOOST_POSIX_API +/** + * \def BOOST_WINDOWS_API + * + * This macro is defined on Windows. + */ +#define BOOST_WINDOWS_API +#endif + +/** + * \def BOOST_PROCESS_THROW(EX) + * + * Defines how exceptions are thrown. Set this macro for example + * to \c BOOST_THROW_EXCEPTION if you like to use Boost.Exception. + */ +#define BOOST_PROCESS_THROW(EX) throw EX + +/** \cond */ +#define BOOST_PROCESS_SOURCE_LOCATION \ + "in file '" __FILE__ "', line " BOOST_STRINGIZE(__LINE__) ": " + +#define BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(what) \ + BOOST_PROCESS_THROW(boost::system::system_error( \ + boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \ + boost::system::system_category()), \ + BOOST_PROCESS_SOURCE_LOCATION what)) + +#define BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec) \ + ec = boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \ + boost::system::system_category()) +/** \endcond */ + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/create_pipe.hpp b/plugins/New_GPG/src/include/boost/process/create_pipe.hpp new file mode 100644 index 0000000000..6c34ecf44b --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/create_pipe.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/create_pipe.hpp + * + * Defines a function to create a pipe. + */ + +#ifndef BOOST_PROCESS_CREATE_PIPE_HPP +#define BOOST_PROCESS_CREATE_PIPE_HPP + +#include <boost/process/config.hpp> + +#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(create_pipe) +BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(create_pipe) + +#if defined(BOOST_PROCESS_DOXYGEN) +namespace boost { namespace process { + +/** + * Creates an anonymous pipe. + * + * \note On Windows anonymous pipes don't support + * asynchronous I/O. + * + * \throws boost::system::system_error in case of an error + */ +pipe create_pipe(); + +/** + * Creates an anonymous pipe. + * + * \note On Windows anonymous pipes don't support + * asynchronous I/O. + */ +pipe create_pipe(boost::system::error_code &ec); + +}} +#endif + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/execute.hpp b/plugins/New_GPG/src/include/boost/process/execute.hpp new file mode 100644 index 0000000000..608831171e --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/execute.hpp @@ -0,0 +1,38 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/execute.hpp + * + * Defines a function to execute a program. + */ + +#ifndef BOOST_PROCESS_EXECUTE_HPP +#define BOOST_PROCESS_EXECUTE_HPP + +#include <boost/process/config.hpp> + +#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(execute) +BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(execute) + +#if defined(BOOST_PROCESS_DOXYGEN) +namespace boost { namespace process { + +/** + * Starts a program. + * + * \tparam initializers define what and how the program is started + */ +template <class Initializer, class... Initializers> +child execute(const Initializer &initializer, const Initializers... &initializers); + +}} +#endif + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/executor.hpp b/plugins/New_GPG/src/include/boost/process/executor.hpp new file mode 100644 index 0000000000..905d7f84cc --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/executor.hpp @@ -0,0 +1,176 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/executor.hpp + * + * Defines an executor which can create child processes. + */ + +#ifndef BOOST_PROCESS_EXECUTOR_HPP +#define BOOST_PROCESS_EXECUTOR_HPP + +#include <boost/process/config.hpp> + +#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(executor) +BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(executor) + +#if defined(BOOST_PROCESS_DOXYGEN) +namespace boost { namespace process { + +/** + * Starts a program. + * + * boost::process::executor is a functor which calls the system functions + * to start a program. Before system functions are called it iterates + * over initializers and calls a member function passing a reference + * to itself as a parameter. Initializers get then a chance to setup + * the executor. If system functions fail boost::process::executor again + * iterates over initializers and calls another member function passing a + * reference to itself as a parameter. This gives initializers a + * chance to handle the error. + * + * \note Library users shouldn't need to use boost::process::executor. + * It is recommended to call boost::process::execute which uses + * boost::pocess::executor internally. + */ +struct executor +{ + /** + * Default constructor. + */ + executor(); + + /** + * Starts a program. + * + * \tparam initializers define what and how the program is started + */ + template <class Initializer, class... Initializers> + child operator()(const Initializer &initializer, const Initializers... &initializers); + + ///\defgroup WindowsOnly Windows only. + ///@{ + + /** + * Program name. + * + * \remark <em>Windows only.</em> + */ + LPCTSTR exe; + + /** + * Command line. + * + * \remark <em>Windows only.</em> + */ + LPTSTR cmd_line; + + /** + * Process attributes. + * + * \remark <em>Windows only.</em> + */ + LPSECURITY_ATTRIBUTES proc_attrs; + + /** + * Thread attributes. + * + * \remark <em>Windows only.</em> + */ + LPSECURITY_ATTRIBUTES thread_attrs; + + /** + * Flag to inherit handles. + * + * \remark <em>Windows only.</em> + */ + BOOL inherit_handles; + + /** + * Creation flags. + * + * \remark <em>Windows only.</em> + */ + DWORD creation_flags; + + /** + * Environment variables. + * + * \remark <em>Windows only.</em> + */ + LPVOID env; + + /** + * Work directory. + * + * \remark <em>Windows only.</em> + */ + LPCTSTR work_dir; + + /** + * Startupinfo structure. + * + * \remark <em>Windows only.</em> + */ + STARTUPINFO startup_info; + + /** + * Startupinfoex structure. + * + * If this member variable is available, \c startup_info is a reference + * to \c StartupInfo in STARTUPINFOEX. + * + * \remark <em>Windows Vista, Windows Server 2008 or better.</em> + */ + STARTUPINFOEX startup_info_ex; + + /** + * Process information. + * + * \c proc_info contains the result after a child process + * could be started successfully. + * + * \remark <em>Windows only.</em> + */ + PROCESS_INFORMATION proc_info; + + ///@} + + ///\defgroup POSIXOnly POSIX only. + ///@{ + + /** + * Program name. + * + * \remark <em>POSIX only.</em> + */ + const char *exe; + + /** + * Command line arguments. + * + * \remark <em>POSIX only.</em> + */ + char **cmd_line; + + /** + * Environment variables. + * + * \remark <em>POSIX only.</em> + */ + char **env; + + ///@} +}; + +}} +#endif + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/initializers.hpp b/plugins/New_GPG/src/include/boost/process/initializers.hpp new file mode 100644 index 0000000000..c7175d1425 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/initializers.hpp @@ -0,0 +1,497 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/initializers.hpp + * + * Defines initializers. + */ + +#ifndef BOOST_PROCESS_INITIALIZERS_HPP +#define BOOST_PROCESS_INITIALIZERS_HPP + +#include <boost/process/config.hpp> + +#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(initializers) +BOOST_PROCESS_PLATFORM_PROMOTE_INITIALIZERS_NAMESPACE + +#if defined(BOOST_PROCESS_DOXYGEN) +namespace boost { namespace process { namespace initializers { + +/** + * Binds the standard error stream. + */ +class bind_stderr : public initializer_base +{ +public: + /** + * Constructor. + */ + explicit bind_stderr(const boost::iostreams::file_descriptor_sink &sink); +}; + +/** + * Binds the standard input stream. + */ +class bind_stdin : public initializer_base +{ +public: + /** + * Constructor. + */ + explicit bind_stdin(const boost::iostreams::file_descriptor_source &source); +}; + +/** + * Binds the standard output stream. + */ +class bind_stdout : public initializer_base +{ +public: + /** + * Constructor. + */ + explicit bind_stdout(const boost::iostreams::file_descriptor_sink &sink); +}; + +/** + * Binds a file descriptor. + * + * \remark <em>POSIX only.</em> + */ +class bind_fd : public initializer_base +{ +public: + /** + * Constructor. + */ + bind_fd(int id, const boost::iostreams::file_descriptor &fd); +}; + +/** + * Closes a file descriptor. + * + * \remark <em>POSIX only.</em> + */ +class close_fd : public initializer_base +{ + /** + * Constructor. + */ + explicit close_fd(int fd); +}; + +/** + * Closes file descriptors. + * + * \remark <em>POSIX only.</em> + */ +class close_fds : public initializer_base +{ +public: + /** + * Constructor. + * + * \c range_type must be an <tt>int</tt>-range. + */ + explicit close_fds(const range_type &fds); +}; + +/** + * Closes all file descriptors a predicate returns + * true for. + * + * This initializer doesn't close file descriptors + * immediately. Instead it sets the \c FD_CLOEXEC + * flag. File descriptors are closed when \c execve + * is called and the call succeeds. + * + * \remark <em>POSIX only.</em> + */ +class close_fds_if : public initializer_base +{ +public: + /** + * Constructor. + * + * \c predicate_type must be a function or functor with + * this signature: <tt>bool(int)</tt> + */ + explicit close_fds_if(const predicate_type &pred); +}; + +/** + * Closes the standard error stream. + */ +class close_stderr : public initializer_base +{ + /** + * Constructor. + */ + close_stderr(); +}; + +/** + * Closes the standard input stream. + */ +class close_stdin : public initializer_base +{ + /** + * Constructor. + */ + close_stdin(); +}; + +/** + * Closes the standard output stream. + */ +class close_stdout : public initializer_base +{ + /** + * Constructor. + */ + close_stdout(); +}; + +/** + * Hides the console. + */ +class hide_console : public initializer_base +{ +public: + /** + * Constructor. + */ + hide_console(); +}; + +/** + * Inherits environment variables. + */ +class inherit_env : public initializer_base +{ +public: + /** + * Constructor. + */ + inherit_env(); +}; + +/** + * Notifies an I/O service object of fork-related events. + * + * \see boost::asio::io_service::notify_fork + * + * \remark <em>POSIX only.</em> + */ +class notify_io_service : public initializer_base +{ +public: + /** + * Constructor. + */ + explicit notify_io_service(boost::asio::io_service &io_service); +}; + +/** + * Generic initializer to execute any code if \c execve + * failed. + * + * \remark <em>POSIX only.</em> + */ +class on_exec_error : public initializer_base +{ +public: + /** + * Constructor. + * + * \c handler_type must be a function or functor with + * this signature: <tt>void(executor&)</tt> + */ + explicit on_exec_error(handler_type handler); +}; + +/** + * Generic initializer to execute any code before \c execve + * is called. + * + * \remark <em>POSIX only.</em> + */ +class on_exec_setup : public initializer_base +{ +public: + /** + * Constructor. + * + * \c handler_type must be a function or functor with + * this signature: <tt>void(executor&)</tt> + */ + explicit on_exec_setup(handler_type handler); +}; + +/** + * Generic initializer to execute any code if \c fork + * failed. + * + * \remark <em>POSIX only.</em> + */ +class on_fork_error : public initializer_base +{ +public: + /** + * Constructor. + * + * \c handler_type must be a function or functor with + * this signature: <tt>void(executor&)</tt> + */ + explicit on_fork_error(handler_type handler); +}; + +/** + * Generic initializer to execute any code before \c fork + * is called. + * + * \remark <em>POSIX only.</em> + */ +class on_fork_setup : public initializer_base +{ +public: + /** + * Constructor. + * + * \c handler_type must be a function or functor with + * this signature: <tt>void(executor&)</tt> + */ + explicit on_fork_setup(handler_type handler); +}; + +/** + * Generic initializer to execute any code in the parent + * process after \c fork has been called successfully. + * + * \remark <em>POSIX only.</em> + */ +class on_fork_success : public initializer_base +{ +public: + /** + * Constructor. + * + * \c handler_type must be a function or functor with + * this signature: <tt>void(executor&)</tt> + */ + explicit on_fork_success(handler_type handler); +}; + +/** + * Generic initializer to execute any code if \c CreateProcess + * failed. + * + * \remark <em>Windows only.</em> + */ +class on_CreateProcess_error : public initializer_base +{ +public: + /** + * Constructor. + * + * \c handler_type must be a function or functor with + * this signature: <tt>void(executor&)</tt> + */ + explicit on_CreateProcess_error(handler_type handler); +}; + +/** + * Generic initializer to execute any code before \c CreateProcess + * is called. + * + * \remark <em>Windows only.</em> + */ +class on_CreateProcess_setup : public initializer_base +{ +public: + /** + * Constructor. + * + * \c handler_type must be a function or functor with + * this signature: <tt>void(executor&)</tt> + */ + explicit on_CreateProcess_setup(handler_type handler); +}; + +/** + * Generic initializer to execute any code after \c CreateProcess + * has been called successfully. + * + * \remark <em>Windows only.</em> + */ +class on_CreateProcess_success : public initializer_base +{ +public: + /** + * Constructor. + * + * \c handler_type must be a function or functor with + * this signature: <tt>void(executor&)</tt> + */ + explicit on_CreateProcess_success(handler_type handler); +}; + +/** + * Specifies the executable to start. + * + * This initializer must always be used. The only exception is + * if you use \c set_args or a generic initializer which + * specifies the executable. + */ +class run_exe : public initializer_base +{ +public: + /** + * Constructor. + * + * On Windows \c string_type must be <tt>const char*</tt>, + * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>. + * If Unicode is used, \c string_type must be + * <tt>const wchar_t*</tt>, <tt>std::wstring</tt> or + * <tt>boost::filesystem::path</tt>. + * + * On POSIX \c string_type must be <tt>const char*</tt>, + * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>. + */ + explicit run_exe(const string_type &s); +}; + +/** + * Sets the command line arguments. + * + * The first argument specifies the executable to start unless + * \c run_exe is used. + * + * Use \c set_cmd_line if you don't want to pass a collection of + * command line arguments but set the command line as one string. + */ +class set_args : public initializer_base +{ +public: + /** + * Constructor. + * + * On Windows \c range_type must be a <tt>std::string</tt>-range. + * If Unicode is used, \c range_type must be a + * <tt>std::wstring</tt>-range. + * + * On POSIX \c range_type must be a <tt>std::string</tt>-range. + */ + explicit set_args(const range_type &r); +}; + +/** + * Sets the command line. + * + * Use \c set_args if you don't want to set the command line as + * one string but pass a collection of command line arguments. + */ +class set_cmd_line : public initializer_base +{ +public: + /** + * Constructor. + * + * On Windows \c string_type must be <tt>const char*</tt>, + * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>. + * If Unicode is used, \c string_type must be + * <tt>const wchar_t*</tt>, <tt>std::wstring</tt> or + * <tt>boost::filesystem::path</tt>. + * + * On POSIX \c string_type must be <tt>const char*</tt>, + * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>. + */ + explicit set_cmd_line(const string_type &s); +}; + +/** + * Sets the environment. + */ +class set_env : public initializer_base +{ +public: + /** + * Constructor. + * + * On Windows \c range_type must be a <tt>std::string</tt>-range. + * If Unicode is used, \c range_type must be a + * <tt>std::wstring</tt>-range. + * + * On POSIX \c range_type must be a <tt>std::string</tt>-range. + */ + explicit set_env(const range_type &r); +}; + +/** + * Sets an error if a child process can't be created. + */ +class set_on_error : public initializer_base +{ +public: + /** + * Constructor. + */ + explicit set_on_error(boost::system::error_code &ec); +}; + +/** + * Sets the flag \c wShowWindow in \c STARTUPINFO. + * + * \remark <em>Windows only.</em> + */ +class show_window : public initializer_base +{ +public: + /** + * Constructor. + */ + explicit show_window(WORD flags); +}; + +/** + * Sets the work directory. + */ +class start_in_dir : public initializer_base +{ +public: + /** + * Constructor. + * + * On Windows \c string_type must be <tt>const char*</tt>, + * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>. + * If Unicode is used, \c string_type must be + * <tt>const wchar_t*</tt>, <tt>std::wstring</tt> or + * <tt>boost::filesystem::path</tt>. + * + * On POSIX \c string_type must be <tt>const char*</tt>, + * <tt>std::string</tt> or <tt>boost::filesystem::path</tt>. + */ + explicit start_in_dir(const string_type &s); +}; + +/** + * Throws an error if a child process can't be created. + * + * The type of the error thrown is \c boost::system::system_error. + */ +class throw_on_error : public initializer_base +{ +public: +}; + +}}} +#endif + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/mitigate.hpp b/plugins/New_GPG/src/include/boost/process/mitigate.hpp new file mode 100644 index 0000000000..6838984aa1 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/mitigate.hpp @@ -0,0 +1,104 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/mitigate.hpp + * + * Helpers to mitigate platform differences. + */ + +#ifndef BOOST_PROCESS_MITIGATE_HPP +#define BOOST_PROCESS_MITIGATE_HPP + +#include <boost/asio.hpp> +#if defined(BOOST_POSIX_API) +# include <sys/wait.h> +#endif + +namespace boost { namespace process { + +#if defined(BOOST_WINDOWS_API) +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +inline const char *zero_device() +{ +#if defined(BOOST_WINDOWS_API) + return "NUL"; +#elif defined(BOOST_POSIX_API) + return "/dev/zero"; +#endif +} + +inline const char *null_device() +{ +#if defined(BOOST_WINDOWS_API) + return "NUL"; +#elif defined(BOOST_POSIX_API) + return "/dev/null"; +#endif +} + +#if defined(BOOST_WINDOWS_API) +# define BOOST_PROCESS_EXITSTATUS(a) static_cast<int>(a) +#elif defined(BOOST_POSIX_API) +# define BOOST_PROCESS_EXITSTATUS WEXITSTATUS +#endif + +#if defined(BOOST_PROCESS_DOXYGEN) +/** + * Type definition for the end of a pipe. + * + * On Windows the type is based on boost::asio::windows::stream_handle. On + * POSIX it is based on boost::asio::posix::stream_descriptor. + * + * You can use this type definition for asynchronous I/O with streams of + * child processes. + */ +typedef boost_asio_type pipe_end; + +/** + * Gets the name of the zero device. + * + * You can use zero_device to initialize a + * boost::iostreams::file_descriptor_source to read + * null characters from. + * + * \returns NUL on Windows and /dev/zero on POSIX. + */ +const char *zero_device(); + +/** + * Gets the name of the null device. + * + * You can use null_device to initialize a + * boost::iostreams::file_descriptor_sink which discards + * data written to it. + * + * \returns NUL on Windows and /dev/null on POSIX. + */ +const char *null_device(); + +/** + * \def BOOST_PROCESS_EXITSTATUS + * + * On Windows \c BOOST_PROCESS_EXITSTATUS is a static cast to \c int. + * On POSIX it is set to \c WEXITSTATUS. + * + * You can use \c BOOST_PROCESS_EXITSTATUS for the return value of + * boost::process::wait_for_exit to get the exit status of a process. + */ +#define BOOST_PROCESS_EXITSTATUS +#endif + +}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/pipe.hpp b/plugins/New_GPG/src/include/boost/process/pipe.hpp new file mode 100644 index 0000000000..35f2a4470d --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/pipe.hpp @@ -0,0 +1,64 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/pipe.hpp + * + * Defines a pipe. + */ + +#ifndef BOOST_PROCESS_PIPE_HPP +#define BOOST_PROCESS_PIPE_HPP + +#include <boost/process/config.hpp> + +#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(pipe) +BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(pipe) +BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(make_pipe) + +#if defined(BOOST_PROCESS_DOXYGEN) +namespace boost { namespace process { + +/** + * Represents a pipe. + */ +struct pipe +{ + /** + * Read-end. + */ + pipe_end_type source; + + /** + * Write-end. + */ + pipe_end_type sink; + + /** + * Constructor. + */ + pipe(pipe_end_type source, pipe_end_type sink); +}; + +/** + * Returns a pipe instance. + * + * This is a helper function to instantiate boost::process::pipe. + * + * \note boost::process::make_pipe does not create a pipe. + * You must pass existing pipe ends to this function. + * If you want to create an anonymous pipe, call + * boost::process::create_pipe. + */ +pipe make_pipe(pipe_end_type source, pipe_end_type sink); + +}} +#endif + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/child.hpp b/plugins/New_GPG/src/include/boost/process/posix/child.hpp new file mode 100644 index 0000000000..913484529e --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/child.hpp @@ -0,0 +1,26 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_CHILD_HPP +#define BOOST_PROCESS_POSIX_CHILD_HPP + +#include <sys/types.h> + +namespace boost { namespace process { namespace posix { + +struct child +{ + pid_t pid; + + explicit child(pid_t p) : pid(p) {} +}; + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/create_pipe.hpp b/plugins/New_GPG/src/include/boost/process/posix/create_pipe.hpp new file mode 100644 index 0000000000..ecdd523516 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/create_pipe.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_CREATE_PIPE_HPP +#define BOOST_PROCESS_POSIX_CREATE_PIPE_HPP + +#include <boost/process/config.hpp> +#include <boost/process/posix/pipe.hpp> +#include <boost/system/error_code.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { + +inline pipe create_pipe() +{ + int fds[2]; + if (::pipe(fds) == -1) + BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pipe(2) failed"); + return pipe(fds[0], fds[1]); +} + +inline pipe create_pipe(boost::system::error_code &ec) +{ + int fds[2]; + if (::pipe(fds) == -1) + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec); + else + ec.clear(); + return pipe(fds[0], fds[1]); +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/execute.hpp b/plugins/New_GPG/src/include/boost/process/posix/execute.hpp new file mode 100644 index 0000000000..27082196c8 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/execute.hpp @@ -0,0 +1,82 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_EXECUTE_HPP +#define BOOST_PROCESS_POSIX_EXECUTE_HPP + +#include <boost/process/posix/executor.hpp> +#include <boost/process/posix/child.hpp> +#include <boost/fusion/tuple/make_tuple.hpp> +#include <boost/ref.hpp> + +namespace boost { namespace process { namespace posix { + +template <class I0> +child execute(const I0 &i0) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0))); +} + +template <class I0, class I1> +child execute(const I0 &i0, const I1 &i1) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1))); +} + +template <class I0, class I1, class I2> +child execute(const I0 &i0, const I1 &i1, const I2 &i2) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2))); +} + +template <class I0, class I1, class I2, class I3> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3))); +} + +template <class I0, class I1, class I2, class I3, class I4> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4))); +} + +template <class I0, class I1, class I2, class I3, class I4, class I5> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5))); +} + +template <class I0, class I1, class I2, class I3, class I4, class I5, class I6> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6))); +} + +template <class I0, class I1, class I2, class I3, class I4, class I5, class I6, class I7> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6, const I7 &i7) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6), boost::cref(i7))); +} + +template <class I0, class I1, class I2, class I3, class I4, class I5, class I6, class I7, class I8> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6, const I7 &i7, const I8 &i8) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6), boost::cref(i7), boost::cref(i8))); +} + +template <class I0, class I1, class I2, class I3, class I4, class I5, class I6, class I7, class I8, class I9> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6, const I7 &i7, const I8 &i8, const I9 &i9) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6), boost::cref(i7), boost::cref(i8), boost::cref(i9))); +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/executor.hpp b/plugins/New_GPG/src/include/boost/process/posix/executor.hpp new file mode 100644 index 0000000000..a3e81f128f --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/executor.hpp @@ -0,0 +1,120 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_EXECUTOR_HPP +#define BOOST_PROCESS_POSIX_EXECUTOR_HPP + +#include <boost/process/posix/child.hpp> +#include <boost/fusion/algorithm/iteration/for_each.hpp> +#include <cstdlib> +#include <sys/types.h> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { + +struct executor +{ + executor() : exe(0), cmd_line(0), env(0) {} + + struct call_on_fork_setup + { + executor &e_; + + call_on_fork_setup(executor &e) : e_(e) {} + + template <class Arg> + void operator()(const Arg &arg) const + { + arg.on_fork_setup(e_); + } + }; + + struct call_on_fork_error + { + executor &e_; + + call_on_fork_error(executor &e) : e_(e) {} + + template <class Arg> + void operator()(Arg &arg) const + { + arg.on_fork_error(e_); + } + }; + + struct call_on_fork_success + { + executor &e_; + + call_on_fork_success(executor &e) : e_(e) {} + + template <class Arg> + void operator()(Arg &arg) const + { + arg.on_fork_success(e_); + } + }; + + struct call_on_exec_setup + { + executor &e_; + + call_on_exec_setup(executor &e) : e_(e) {} + + template <class Arg> + void operator()(Arg &arg) const + { + arg.on_exec_setup(e_); + } + }; + + struct call_on_exec_error + { + executor &e_; + + call_on_exec_error(executor &e) : e_(e) {} + + template <class Arg> + void operator()(Arg &arg) const + { + arg.on_exec_error(e_); + } + }; + + template <class InitializerSequence> + child operator()(const InitializerSequence &seq) + { + boost::fusion::for_each(seq, call_on_fork_setup(*this)); + + pid_t pid = ::fork(); + if (pid == -1) + { + boost::fusion::for_each(seq, call_on_fork_error(*this)); + } + else if (pid == 0) + { + boost::fusion::for_each(seq, call_on_exec_setup(*this)); + ::execve(exe, cmd_line, env); + boost::fusion::for_each(seq, call_on_exec_error(*this)); + _exit(EXIT_FAILURE); + } + + boost::fusion::for_each(seq, call_on_fork_success(*this)); + + return child(pid); + } + + const char *exe; + char **cmd_line; + char **env; +}; + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers.hpp new file mode 100644 index 0000000000..78295c14cb --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_HPP + +#include <boost/process/posix/initializers/bind_fd.hpp> +#include <boost/process/posix/initializers/bind_stderr.hpp> +#include <boost/process/posix/initializers/bind_stdin.hpp> +#include <boost/process/posix/initializers/bind_stdout.hpp> +#include <boost/process/posix/initializers/close_fd.hpp> +#include <boost/process/posix/initializers/close_fds.hpp> +#include <boost/process/posix/initializers/close_fds_if.hpp> +#include <boost/process/posix/initializers/close_stderr.hpp> +#include <boost/process/posix/initializers/close_stdin.hpp> +#include <boost/process/posix/initializers/close_stdout.hpp> +#include <boost/process/posix/initializers/hide_console.hpp> +#include <boost/process/posix/initializers/inherit_env.hpp> +#include <boost/process/posix/initializers/notify_io_service.hpp> +#include <boost/process/posix/initializers/on_exec_error.hpp> +#include <boost/process/posix/initializers/on_exec_setup.hpp> +#include <boost/process/posix/initializers/on_fork_error.hpp> +#include <boost/process/posix/initializers/on_fork_setup.hpp> +#include <boost/process/posix/initializers/on_fork_success.hpp> +#include <boost/process/posix/initializers/run_exe.hpp> +#include <boost/process/posix/initializers/set_args.hpp> +#include <boost/process/posix/initializers/set_cmd_line.hpp> +#include <boost/process/posix/initializers/set_env.hpp> +#include <boost/process/posix/initializers/set_on_error.hpp> +#include <boost/process/posix/initializers/start_in_dir.hpp> +#include <boost/process/posix/initializers/throw_on_error.hpp> + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_fd.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_fd.hpp new file mode 100644 index 0000000000..851b7ef3e4 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_fd.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_BIND_FD_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_BIND_FD_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class FileDescriptor> +class bind_fd_ : public initializer_base +{ +public: + bind_fd_(int id, const FileDescriptor &fd) : id_(id), fd_(fd) {} + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + ::dup2(fd_.handle(), id_); + } + +private: + int id_; + FileDescriptor fd_; +}; + +template <class FileDescriptor> +bind_fd_<FileDescriptor> bind_fd(int id, const FileDescriptor &fd) +{ + return bind_fd_<FileDescriptor>(id, fd); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_stderr.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_stderr.hpp new file mode 100644 index 0000000000..be767bf2fe --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_stderr.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_BIND_STDERR_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_BIND_STDERR_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class bind_stderr : public initializer_base +{ +public: + explicit bind_stderr(const boost::iostreams::file_descriptor_sink &sink) + : sink_(sink) {} + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + ::dup2(sink_.handle(), STDERR_FILENO); + } + +private: + boost::iostreams::file_descriptor_sink sink_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_stdin.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_stdin.hpp new file mode 100644 index 0000000000..b592d6f8b3 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_stdin.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_BIND_STDIN_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_BIND_STDIN_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class bind_stdin : public initializer_base +{ +public: + explicit bind_stdin(const boost::iostreams::file_descriptor_source &source) + : source_(source) {} + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + ::dup2(source_.handle(), STDIN_FILENO); + } + +private: + boost::iostreams::file_descriptor_source source_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_stdout.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_stdout.hpp new file mode 100644 index 0000000000..a2c316d997 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/bind_stdout.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_BIND_STDOUT_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_BIND_STDOUT_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class bind_stdout : public initializer_base +{ +public: + explicit bind_stdout(const boost::iostreams::file_descriptor_sink &sink) + : sink_(sink) {} + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + ::dup2(sink_.handle(), STDOUT_FILENO); + } + +private: + boost::iostreams::file_descriptor_sink sink_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/close_fd.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_fd.hpp new file mode 100644 index 0000000000..fd516e4100 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_fd.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_FD_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_FD_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class close_fd : public initializer_base +{ +public: + explicit close_fd(int fd) : fd_(fd) {} + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + ::close(fd_); + } + +private: + int fd_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/close_fds.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_fds.hpp new file mode 100644 index 0000000000..2fa338501e --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_fds.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_FDS_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_FDS_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/range/algorithm/for_each.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class Range> +class close_fds_ : public initializer_base +{ +public: + explicit close_fds_(const Range &fds) : fds_(fds) {} + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + boost::for_each(fds_, ::close); + } + +private: + Range fds_; +}; + +template <class Range> +close_fds_<Range> close_fds(const Range &fds) +{ + return close_fds_<Range>(fds); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/close_fds_if.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_fds_if.hpp new file mode 100644 index 0000000000..fb3a651d62 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_fds_if.hpp @@ -0,0 +1,80 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_FDS_IF_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_FDS_IF_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/iterator/counting_iterator.hpp> +#include <boost/range/counting_range.hpp> +#include <boost/range/adaptor/filtered.hpp> +#include <boost/range/algorithm/for_each.hpp> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#ifndef BOOST_PROCESS_POSIX_MAX_FD +# define BOOST_PROCESS_POSIX_MAX_FD 32 +#endif + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class Predicate> +class close_fds_if_ : public initializer_base +{ +private: + static void close(int fd) + { + ::fcntl(fd, F_SETFD, FD_CLOEXEC); + } + +public: + explicit close_fds_if_(const Predicate &pred) : pred_(pred) {} + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + boost::for_each( + boost::adaptors::filter( + boost::counting_range(0, upper_bound()), + pred_ + ), + close + ); + } + +private: + static int upper_bound() + { + int up; +#if defined(F_MAXFD) + do + { + up = ::fcntl(0, F_MAXFD); + } while (up == -1 && errno == EINTR); + if (up == -1) +#endif + up = ::sysconf(_SC_OPEN_MAX); + if (up == -1) + up = BOOST_PROCESS_POSIX_MAX_FD; + return up; + } + + Predicate pred_; +}; + +template <class Predicate> +close_fds_if_<Predicate> close_fds_if(const Predicate &pred) +{ + return close_fds_if_<Predicate>(pred); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/close_stderr.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_stderr.hpp new file mode 100644 index 0000000000..1a4c2ad00d --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_stderr.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_STDERR_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_STDERR_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class close_stderr : public initializer_base +{ +public: + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + ::close(STDERR_FILENO); + } +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/close_stdin.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_stdin.hpp new file mode 100644 index 0000000000..021c3ec54d --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_stdin.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_STDIN_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_STDIN_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class close_stdin : public initializer_base +{ +public: + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + ::close(STDIN_FILENO); + } +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/close_stdout.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_stdout.hpp new file mode 100644 index 0000000000..cfab7d1d62 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/close_stdout.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_STDOUT_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_CLOSE_STDOUT_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class close_stdout : public initializer_base +{ +public: + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + ::close(STDOUT_FILENO); + } +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/hide_console.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/hide_console.hpp new file mode 100644 index 0000000000..20d527b457 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/hide_console.hpp @@ -0,0 +1,24 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_HIDE_CONSOLE_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_HIDE_CONSOLE_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class hide_console : public initializer_base +{ +public: +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/inherit_env.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/inherit_env.hpp new file mode 100644 index 0000000000..bc73c8571f --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/inherit_env.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_INHERIT_ENV_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_INHERIT_ENV_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +// From <https://svn.boost.org/trac/boost/changeset/67768> +#if defined(__APPLE__) && defined(__DYNAMIC__) +extern "C" { extern char ***_NSGetEnviron(void); } +# define environ (*_NSGetEnviron()) +#else +# include <unistd.h> +#endif + +namespace boost { namespace process { namespace posix { namespace initializers { + +class inherit_env : public initializer_base +{ +public: + template <class PosixExecutor> + void on_fork_setup(PosixExecutor &e) const + { + e.env = environ; + } +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/initializer_base.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/initializer_base.hpp new file mode 100644 index 0000000000..775f00e48c --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/initializer_base.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_INITIALIZER_BASE_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_INITIALIZER_BASE_HPP + +namespace boost { namespace process { namespace posix { namespace initializers { + +struct initializer_base +{ + template <class PosixExecutor> + void on_fork_setup(PosixExecutor&) const {} + + template <class PosixExecutor> + void on_fork_error(PosixExecutor&) const {} + + template <class PosixExecutor> + void on_fork_success(PosixExecutor&) const {} + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const {} + + template <class PosixExecutor> + void on_exec_error(PosixExecutor&) const {} +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/notify_io_service.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/notify_io_service.hpp new file mode 100644 index 0000000000..d94f674c81 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/notify_io_service.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_NOTIFY_IO_SERVICE_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_NOTIFY_IO_SERVICE_HPP + +#include <boost/process/config.hpp> +#include <boost/process/posix/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class IOService> +class notify_io_service_ : public initializer_base +{ +public: + explicit notify_io_service_(IOService &io_service) : + io_service_(io_service) {} + + template <class PosixExecutor> + void on_fork_setup(PosixExecutor&) const + { + io_service_.notify_fork(IOService::fork_prepare); + } + + template <class PosixExecutor> + void on_fork_success(PosixExecutor&) const + { + io_service_.notify_fork(IOService::fork_parent); + } + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + io_service_.notify_fork(IOService::fork_child); + } + +private: + IOService &io_service_; +}; + +template <class IOService> +notify_io_service_<IOService> notify_io_service(IOService &io_service) +{ + return notify_io_service_<IOService>(io_service); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/on_exec_error.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/on_exec_error.hpp new file mode 100644 index 0000000000..63b56def4f --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/on_exec_error.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_ON_EXEC_ERROR_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_ON_EXEC_ERROR_HPP + +#include <boost/process/config.hpp> +#include <boost/process/posix/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class Handler> +class on_exec_error_ : public initializer_base +{ +public: + explicit on_exec_error_(Handler handler) : handler_(handler) {} + + template <class PosixExecutor> + void on_exec_error(PosixExecutor &e) const + { + handler_(e); + } + +private: + Handler handler_; +}; + +template <class Handler> +on_exec_error_<Handler> on_exec_error(Handler handler) +{ + return on_exec_error_<Handler>(handler); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/on_exec_setup.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/on_exec_setup.hpp new file mode 100644 index 0000000000..50f5f3736b --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/on_exec_setup.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_ON_EXEC_SETUP_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_ON_EXEC_SETUP_HPP + +#include <boost/process/config.hpp> +#include <boost/process/posix/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class Handler> +class on_exec_setup_ : public initializer_base +{ +public: + explicit on_exec_setup_(Handler handler) : handler_(handler) {} + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor &e) const + { + handler_(e); + } + +private: + Handler handler_; +}; + +template <class Handler> +on_exec_setup_<Handler> on_exec_setup(Handler handler) +{ + return on_exec_setup_<Handler>(handler); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/on_fork_error.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/on_fork_error.hpp new file mode 100644 index 0000000000..42ecf1aac9 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/on_fork_error.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_ON_FORK_ERROR_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_ON_FORK_ERROR_HPP + +#include <boost/process/config.hpp> +#include <boost/process/posix/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class Handler> +class on_fork_error_ : public initializer_base +{ +public: + explicit on_fork_error_(Handler handler) : handler_(handler) {} + + template <class PosixExecutor> + void on_fork_error(PosixExecutor &e) const + { + handler_(e); + } + +private: + Handler handler_; +}; + +template <class Handler> +on_fork_error_<Handler> on_fork_error(Handler handler) +{ + return on_fork_error_<Handler>(handler); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/on_fork_setup.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/on_fork_setup.hpp new file mode 100644 index 0000000000..c0c5b0682f --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/on_fork_setup.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_ON_FORK_SETUP_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_ON_FORK_SETUP_HPP + +#include <boost/process/config.hpp> +#include <boost/process/posix/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class Handler> +class on_fork_setup_ : public initializer_base +{ +public: + explicit on_fork_setup_(Handler handler) : handler_(handler) {} + + template <class PosixExecutor> + void on_fork_setup(PosixExecutor &e) const + { + handler_(e); + } + +private: + Handler handler_; +}; + +template <class Handler> +on_fork_setup_<Handler> on_fork_setup(Handler handler) +{ + return on_fork_setup_<Handler>(handler); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/on_fork_success.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/on_fork_success.hpp new file mode 100644 index 0000000000..01c9b12db0 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/on_fork_success.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_ON_FORK_SUCCESS_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_ON_FORK_SUCCESS_HPP + +#include <boost/process/config.hpp> +#include <boost/process/posix/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class Handler> +class on_fork_success_ : public initializer_base +{ +public: + explicit on_fork_success_(Handler handler) : handler_(handler) {} + + template <class PosixExecutor> + void on_fork_success(PosixExecutor &e) const + { + handler_(e); + } + +private: + Handler handler_; +}; + +template <class Handler> +on_fork_success_<Handler> on_fork_success(Handler handler) +{ + return on_fork_success_<Handler>(handler); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/run_exe.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/run_exe.hpp new file mode 100644 index 0000000000..6cceeea8c1 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/run_exe.hpp @@ -0,0 +1,59 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_RUN_EXE_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_RUN_EXE_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/filesystem.hpp> +#include <boost/shared_array.hpp> +#include <string> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class run_exe_ : public initializer_base +{ +public: + explicit run_exe_(const std::string &s) : s_(s), cmd_line_(new char*[2]) + { + cmd_line_[0] = const_cast<char*>(s_.c_str()); + cmd_line_[1] = 0; + } + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor &e) const + { + e.exe = s_.c_str(); + if (!e.cmd_line) + e.cmd_line = cmd_line_.get(); + } + +private: + std::string s_; + boost::shared_array<char*> cmd_line_; +}; + +inline run_exe_ run_exe(const char *s) +{ + return run_exe_(s); +} + +inline run_exe_ run_exe(const std::string &s) +{ + return run_exe_(s); +} + +inline run_exe_ run_exe(const boost::filesystem::path &p) +{ + return run_exe_(p.string()); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/set_args.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/set_args.hpp new file mode 100644 index 0000000000..294926dc22 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/set_args.hpp @@ -0,0 +1,57 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_SET_ARGS_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_SET_ARGS_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/range/algorithm/transform.hpp> +#include <boost/shared_array.hpp> +#include <string> + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class Range> +class set_args_ : public initializer_base +{ +private: + static char *c_str(const std::string &s) + { + return const_cast<char*>(s.c_str()); + } + +public: + explicit set_args_(const Range &args) + { + args_.reset(new char*[args.size() + 1]); + boost::transform(args, args_.get(), c_str); + args_[args.size()] = 0; + } + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor &e) const + { + e.cmd_line = args_.get(); + if (!e.exe && *args_[0]) + e.exe = args_[0]; + } + +private: + boost::shared_array<char*> args_; +}; + +template <class Range> +set_args_<Range> set_args(const Range &range) +{ + return set_args_<Range>(range); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/set_cmd_line.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/set_cmd_line.hpp new file mode 100644 index 0000000000..0f59d25359 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/set_cmd_line.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_SET_CMD_LINE_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_SET_CMD_LINE_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/tokenizer.hpp> +#include <boost/shared_array.hpp> +#include <string> +#include <vector> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class set_cmd_line : public initializer_base +{ +private: + static char *c_str(const std::string &s) + { + return const_cast<char*>(s.c_str()); + } + +public: + explicit set_cmd_line(const std::string &s) + { + typedef boost::tokenizer<boost::escaped_list_separator<char> > tokenizer; + boost::escaped_list_separator<char> sep('\\', ' ', '\"'); + tokenizer tok(s, sep); + args_.assign(tok.begin(), tok.end()); + cmd_line_.reset(new char*[args_.size() + 1]); + boost::transform(args_, cmd_line_.get(), c_str); + cmd_line_[args_.size()] = 0; + } + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor &e) const + { + e.cmd_line = cmd_line_.get(); + } + +private: + std::vector<std::string> args_; + boost::shared_array<char*> cmd_line_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/set_env.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/set_env.hpp new file mode 100644 index 0000000000..76649184f3 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/set_env.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_SET_ENV_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_SET_ENV_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/range/algorithm/transform.hpp> +#include <boost/shared_array.hpp> +#include <string> + +namespace boost { namespace process { namespace posix { namespace initializers { + +template <class Range> +class set_env_ : public initializer_base +{ +private: + static char *get_ptr(const std::string &s) + { + return const_cast<char*>(s.c_str()); + } + +public: + explicit set_env_(const Range &envs) : env_(new char*[envs.size() + 1]) + { + boost::transform(envs, env_.get(), get_ptr); + env_[envs.size()] = 0; + } + + template <class PosixExecutor> + void on_fork_setup(PosixExecutor &e) const + { + e.env = env_.get(); + } + +private: + boost::shared_array<char*> env_; +}; + +template <class Range> +set_env_<Range> set_env(const Range &envs) +{ + return set_env_<Range>(envs); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/set_on_error.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/set_on_error.hpp new file mode 100644 index 0000000000..c01a816e60 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/set_on_error.hpp @@ -0,0 +1,95 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_SET_ON_ERROR_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_SET_ON_ERROR_HPP + +#include <boost/process/config.hpp> +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/system/error_code.hpp> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class set_on_error : public initializer_base +{ +public: + explicit set_on_error(boost::system::error_code &ec) : ec_(ec) {} + + template <class PosixExecutor> + void on_fork_setup(PosixExecutor&) const + { + if (::pipe(fds_) == -1) + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec_); + if (::fcntl(fds_[1], F_SETFD, FD_CLOEXEC) == -1) + { + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec_); + ::close(fds_[0]); + ::close(fds_[1]); + } + } + + template <class PosixExecutor> + void on_fork_error(PosixExecutor&) const + { + if (!ec_) + { + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec_); + ::close(fds_[0]); + ::close(fds_[1]); + } + } + + template <class PosixExecutor> + void on_fork_success(PosixExecutor&) const + { + if (!ec_) + { + ::close(fds_[1]); + int code; + if (::read(fds_[0], &code, sizeof(int)) > 0) + { + ec_ = boost::system::error_code(code, + boost::system::system_category()); + } + ::close(fds_[0]); + } + } + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + if (!ec_) + { + ::close(fds_[0]); + } + } + + template <class PosixExecutor> + void on_exec_error(PosixExecutor&) const + { + if (!ec_) + { + int e = errno; + while (::write(fds_[1], &e, sizeof(int)) == -1 && errno == EINTR) + ; + ::close(fds_[1]); + } + } + +private: + boost::system::error_code &ec_; + mutable int fds_[2]; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/start_in_dir.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/start_in_dir.hpp new file mode 100644 index 0000000000..187b5a31f4 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/start_in_dir.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_START_IN_DIR_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_START_IN_DIR_HPP + +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <string> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class start_in_dir : public initializer_base +{ +public: + explicit start_in_dir(const std::string &s) : s_(s) {} + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + ::chdir(s_.c_str()); + } + +private: + std::string s_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/initializers/throw_on_error.hpp b/plugins/New_GPG/src/include/boost/process/posix/initializers/throw_on_error.hpp new file mode 100644 index 0000000000..7734c19e30 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/initializers/throw_on_error.hpp @@ -0,0 +1,90 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_INITIALIZERS_THROW_ON_ERROR_HPP +#define BOOST_PROCESS_POSIX_INITIALIZERS_THROW_ON_ERROR_HPP + +#include <boost/process/config.hpp> +#include <boost/process/posix/initializers/initializer_base.hpp> +#include <boost/system/error_code.hpp> +#include <boost/system/system_error.hpp> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +namespace boost { namespace process { namespace posix { namespace initializers { + +class throw_on_error : public initializer_base +{ +public: + template <class PosixExecutor> + void on_fork_setup(PosixExecutor&) const + { + if (::pipe(fds_) == -1) + BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pipe(2) failed"); + if (::fcntl(fds_[1], F_SETFD, FD_CLOEXEC) == -1) + { + int e = errno; + ::close(fds_[0]); + ::close(fds_[1]); + BOOST_PROCESS_THROW(boost::system::system_error( + boost::system::error_code(e, boost::system::system_category()), + BOOST_PROCESS_SOURCE_LOCATION "fcntl(2) failed")); + } + } + + template <class PosixExecutor> + void on_fork_error(PosixExecutor&) const + { + int e = errno; + ::close(fds_[0]); + ::close(fds_[1]); + BOOST_PROCESS_THROW(boost::system::system_error( + boost::system::error_code(e, boost::system::system_category()), + BOOST_PROCESS_SOURCE_LOCATION "fork(2) failed")); + } + + template <class PosixExecutor> + void on_fork_success(PosixExecutor&) const + { + ::close(fds_[1]); + int code; + if (::read(fds_[0], &code, sizeof(int)) > 0) + { + ::close(fds_[0]); + BOOST_PROCESS_THROW(boost::system::system_error( + boost::system::error_code(code, + boost::system::system_category()), + BOOST_PROCESS_SOURCE_LOCATION "execve(2) failed")); + } + ::close(fds_[0]); + } + + template <class PosixExecutor> + void on_exec_setup(PosixExecutor&) const + { + ::close(fds_[0]); + } + + template <class PosixExecutor> + void on_exec_error(PosixExecutor&) const + { + int e = errno; + while (::write(fds_[1], &e, sizeof(int)) == -1 && errno == EINTR) + ; + ::close(fds_[1]); + } + +private: + mutable int fds_[2]; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/pipe.hpp b/plugins/New_GPG/src/include/boost/process/posix/pipe.hpp new file mode 100644 index 0000000000..ca5b29447a --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/pipe.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_PIPE_HPP +#define BOOST_PROCESS_POSIX_PIPE_HPP + +namespace boost { namespace process { namespace posix { + +struct pipe +{ + int source; + int sink; + + pipe(int source, int sink) : source(source), sink(sink) {} +}; + +inline pipe make_pipe(int source, int sink) +{ + return pipe(source, sink); +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/search_path.hpp b/plugins/New_GPG/src/include/boost/process/posix/search_path.hpp new file mode 100644 index 0000000000..6dc2bea063 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/search_path.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_SEARCH_PATH_HPP +#define BOOST_PROCESS_POSIX_SEARCH_PATH_HPP + +#include <boost/process/config.hpp> +#include <boost/filesystem.hpp> +#include <boost/tokenizer.hpp> +#include <string> +#include <stdexcept> +#include <stdlib.h> +#include <unistd.h> + +namespace boost { namespace process { namespace posix { + +inline std::string search_path(const std::string &filename, + std::string path = "") +{ + if (path.empty()) + { + path = ::getenv("PATH"); + if (path.empty()) + BOOST_PROCESS_THROW(std::runtime_error( + "Environment variable PATH not found")); + } + + std::string result; + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep(":"); + tokenizer tok(path, sep); + for (tokenizer::iterator it = tok.begin(); it != tok.end(); ++it) + { + boost::filesystem::path p = *it; + p /= filename; + if (!::access(p.c_str(), X_OK)) + { + result = p.string(); + break; + } + } + return result; +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/shell_path.hpp b/plugins/New_GPG/src/include/boost/process/posix/shell_path.hpp new file mode 100644 index 0000000000..3e21e75759 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/shell_path.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_SHELL_PATH_HPP +#define BOOST_PROCESS_POSIX_SHELL_PATH_HPP + +#include <boost/process/config.hpp> +#include <boost/system/error_code.hpp> +#include <boost/filesystem/path.hpp> + +namespace boost { namespace process { namespace posix { + +inline boost::filesystem::path shell_path() +{ + return "/bin/sh"; +} + +inline boost::filesystem::path shell_path(boost::system::error_code &ec) +{ + ec.clear(); + return "/bin/sh"; +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/terminate.hpp b/plugins/New_GPG/src/include/boost/process/posix/terminate.hpp new file mode 100644 index 0000000000..9be087df25 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/terminate.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_TERMINATE_HPP +#define BOOST_PROCESS_POSIX_TERMINATE_HPP + +#include <boost/process/config.hpp> +#include <boost/system/error_code.hpp> +#include <signal.h> + +namespace boost { namespace process { namespace posix { + +template <class Process> +void terminate(const Process &p) +{ + if (::kill(p.pid, SIGKILL) == -1) + BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("kill(2) failed"); +} + +template <class Process> +void terminate(const Process &p, boost::system::error_code &ec) +{ + if (::kill(p.pid, SIGKILL) == -1) + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec); + else + ec.clear(); +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/posix/wait_for_exit.hpp b/plugins/New_GPG/src/include/boost/process/posix/wait_for_exit.hpp new file mode 100644 index 0000000000..d2b946c262 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/posix/wait_for_exit.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_WAIT_FOR_EXIT_HPP +#define BOOST_PROCESS_POSIX_WAIT_FOR_EXIT_HPP + +#include <boost/process/config.hpp> +#include <boost/system/error_code.hpp> +#include <sys/types.h> +#include <sys/wait.h> + +namespace boost { namespace process { namespace posix { + +template <class Process> +inline int wait_for_exit(const Process &p) +{ + pid_t ret; + int status; + do + { + ret = ::waitpid(p.pid, &status, 0); + } while ((ret == -1 && errno == EINTR) || (ret != -1 && !WIFEXITED(status))); + if (ret == -1) + BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("waitpid(2) failed"); + return status; +} + +template <class Process> +inline int wait_for_exit(const Process &p, boost::system::error_code &ec) +{ + pid_t ret; + int status; + do + { + ret = ::waitpid(p.pid, &status, 0); + } while ((ret == -1 && errno == EINTR) || (ret != -1 && !WIFEXITED(status))); + if (ret == -1) + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec); + else + ec.clear(); + return status; +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/search_path.hpp b/plugins/New_GPG/src/include/boost/process/search_path.hpp new file mode 100644 index 0000000000..20bff060b6 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/search_path.hpp @@ -0,0 +1,51 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/search_path.hpp + * + * Defines a function to search for an executable in path. + */ + +#ifndef BOOST_PROCESS_SEARCH_PATH_HPP +#define BOOST_PROCESS_SEARCH_PATH_HPP + +#include <boost/process/config.hpp> + +#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(search_path) +BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(search_path) + +#if defined(BOOST_PROCESS_DOXYGEN) +namespace boost { namespace process { + +/** + * Searches for an executable in path. + * + * filename must be a basename including the file extension. + * It must not include any directory separators (like a slash). + * On Windows the file extension may be omitted. The function + * will then try the various file extensions for executables on + * Windows to find filename. + * + * path must be a set of directories. Directories must be + * separated by colons on POSIX and by semicolons on Windows. + * If path is empty, the environment variable PATH is used. + * + * \returns the absolute path to the executable filename or an + * empty string if filename isn't found + * + * \throws std::runtime_error if path is empty and no environment + * variable PATH exists + */ +string_type search_path(const string_type &filename, string_type path = ""); + +}} +#endif + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/shell_path.hpp b/plugins/New_GPG/src/include/boost/process/shell_path.hpp new file mode 100644 index 0000000000..92e9f0814b --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/shell_path.hpp @@ -0,0 +1,46 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/shell_path.hpp + * + * Defines a function to return the absolute path to a shell executable. + */ + +#ifndef BOOST_PROCESS_SHELL_PATH_HPP +#define BOOST_PROCESS_SHELL_PATH_HPP + +#include <boost/process/config.hpp> + +#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(shell_path) +BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(shell_path) + +#if defined(BOOST_PROCESS_DOXYGEN) +namespace boost { namespace process { + +/** + * Returns the absolute path to a shell executable. + * + * \returns the path to cmd.exe on Windows and /bin/sh on POSIX. + * + * \throws boost::system::system_error in case of an error + */ +boost::filesystem::path shell_path(); + +/** + * Returns the absolute path to a shell executable. + * + * \returns the path to cmd.exe on Windows and /bin/sh on POSIX. + */ +boost::filesystem::path shell_path(boost::system::error_code &ec); + +}} +#endif + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/terminate.hpp b/plugins/New_GPG/src/include/boost/process/terminate.hpp new file mode 100644 index 0000000000..140eba7e8d --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/terminate.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/terminate.hpp + * + * Defines a function to terminate a process. + */ + +#ifndef BOOST_PROCESS_TERMINATE_HPP +#define BOOST_PROCESS_TERMINATE_HPP + +#include <boost/process/config.hpp> + +#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(terminate) +BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(terminate) + +#if defined(BOOST_PROCESS_DOXYGEN) +namespace boost { namespace process { + +/** + * Terminates a process. + * + * \warning Call this function only as a last resort. The process + * is terminated immediately and forcefully and has no + * chance to close or clean up resources properly. + * + * \throws boost::system::system_error in case of an error + */ +template <class Process> +void terminate(const Process &p); + +/** + * Terminates a process. + * + * \warning Call this function only as a last resort. The process + * is terminated immediately and forcefully and has no + * chance to close or clean up resources properly. + */ +template <class Process> +void terminate(const Process &p, boost::system::error_code &ec); + +}} +#endif + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/wait_for_exit.hpp b/plugins/New_GPG/src/include/boost/process/wait_for_exit.hpp new file mode 100644 index 0000000000..d9b118695d --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/wait_for_exit.hpp @@ -0,0 +1,58 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/wait_for_exit.hpp + * + * Defines a function to wait for a process to exit. + */ + +#ifndef BOOST_PROCESS_WAIT_FOR_EXIT_HPP +#define BOOST_PROCESS_WAIT_FOR_EXIT_HPP + +#include <boost/process/config.hpp> + +#include BOOST_PROCESS_PLATFORM_PROMOTE_PATH(wait_for_exit) +BOOST_PROCESS_PLATFORM_PROMOTE_NAMESPACE(wait_for_exit) + +#if defined(BOOST_PROCESS_DOXYGEN) +namespace boost { namespace process { + +/** + * Waits for a process to exit. + * + * On Window boost::process::wait_for_exit returns the exit code + * of the process. On POSIX the exit status is returned. You must + * use the macro \c WEXITSTATUS (defined in sys/wait.h) to fetch + * the exit code from the exit status. + * + * \note This is a blocking function. + * + * \throws boost::system::system_error in case of an error + */ +template <class Process> +int_type wait_for_exit(const Process &p); + +/** + * Waits for a process to exit. + * + * On Window boost::process::wait_for_exit returns the exit code + * of the process. On POSIX the exit status is returned. You must + * use the macro \c WEXITSTATUS (defined in sys/wait.h) to fetch + * the exit code from the exit status. + * + * \note This is a blocking function. + */ +template <class Process> +int_type wait_for_exit(const Process &p, boost::system::error_code &ec); + +}} +#endif + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/child.hpp b/plugins/New_GPG/src/include/boost/process/windows/child.hpp new file mode 100644 index 0000000000..083cd29da0 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/child.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_CHILD_HPP +#define BOOST_PROCESS_WINDOWS_CHILD_HPP + +#include <boost/move/move.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { + +class child +{ +public: + PROCESS_INFORMATION proc_info; + + explicit child(const PROCESS_INFORMATION &pi) : proc_info(pi) {} + + ~child() + { + ::CloseHandle(proc_info.hProcess); + ::CloseHandle(proc_info.hThread); + } + + child(BOOST_RV_REF(child) c) : proc_info(c.proc_info) + { + c.proc_info.hProcess = INVALID_HANDLE_VALUE; + c.proc_info.hThread = INVALID_HANDLE_VALUE; + } + + child &operator=(BOOST_RV_REF(child) c) + { + ::CloseHandle(proc_info.hProcess); + ::CloseHandle(proc_info.hThread); + proc_info = c.proc_info; + c.proc_info.hProcess = INVALID_HANDLE_VALUE; + c.proc_info.hThread = INVALID_HANDLE_VALUE; + return *this; + } + + HANDLE process_handle() const { return proc_info.hProcess; } + +private: + BOOST_MOVABLE_BUT_NOT_COPYABLE(child); +}; + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/create_pipe.hpp b/plugins/New_GPG/src/include/boost/process/windows/create_pipe.hpp new file mode 100644 index 0000000000..fe1e49751d --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/create_pipe.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_CREATE_PIPE_HPP +#define BOOST_PROCESS_WINDOWS_CREATE_PIPE_HPP + +#include <boost/process/config.hpp> +#include <boost/process/windows/pipe.hpp> +#include <boost/system/error_code.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { + +inline pipe create_pipe() +{ + HANDLE handles[2]; + if (!::CreatePipe(&handles[0], &handles[1], NULL, 0)) + BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed"); + return make_pipe(handles[0], handles[1]); +} + +inline pipe create_pipe(boost::system::error_code &ec) +{ + HANDLE handles[2]; + if (!::CreatePipe(&handles[0], &handles[1], NULL, 0)) + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec); + else + ec.clear(); + return make_pipe(handles[0], handles[1]); +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/execute.hpp b/plugins/New_GPG/src/include/boost/process/windows/execute.hpp new file mode 100644 index 0000000000..43067521ea --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/execute.hpp @@ -0,0 +1,82 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_EXECUTE_HPP +#define BOOST_PROCESS_WINDOWS_EXECUTE_HPP + +#include <boost/process/windows/executor.hpp> +#include <boost/process/windows/child.hpp> +#include <boost/fusion/tuple/make_tuple.hpp> +#include <boost/ref.hpp> + +namespace boost { namespace process { namespace windows { + +template <class I0> +child execute(const I0 &i0) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0))); +} + +template <class I0, class I1> +child execute(const I0 &i0, const I1 &i1) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1))); +} + +template <class I0, class I1, class I2> +child execute(const I0 &i0, const I1 &i1, const I2 &i2) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2))); +} + +template <class I0, class I1, class I2, class I3> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3))); +} + +template <class I0, class I1, class I2, class I3, class I4> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4))); +} + +template <class I0, class I1, class I2, class I3, class I4, class I5> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5))); +} + +template <class I0, class I1, class I2, class I3, class I4, class I5, class I6> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6))); +} + +template <class I0, class I1, class I2, class I3, class I4, class I5, class I6, class I7> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6, const I7 &i7) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6), boost::cref(i7))); +} + +template <class I0, class I1, class I2, class I3, class I4, class I5, class I6, class I7, class I8> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6, const I7 &i7, const I8 &i8) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6), boost::cref(i7), boost::cref(i8))); +} + +template <class I0, class I1, class I2, class I3, class I4, class I5, class I6, class I7, class I8, class I9> +child execute(const I0 &i0, const I1 &i1, const I2 &i2, const I3 &i3, const I4 &i4, const I5 &i5, const I6 &i6, const I7 &i7, const I8 &i8, const I9 &i9) +{ + return executor()(boost::fusion::make_tuple(boost::cref(i0), boost::cref(i1), boost::cref(i2), boost::cref(i3), boost::cref(i4), boost::cref(i5), boost::cref(i6), boost::cref(i7), boost::cref(i8), boost::cref(i9))); +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/executor.hpp b/plugins/New_GPG/src/include/boost/process/windows/executor.hpp new file mode 100644 index 0000000000..1560f30793 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/executor.hpp @@ -0,0 +1,130 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_EXECUTOR_HPP +#define BOOST_PROCESS_WINDOWS_EXECUTOR_HPP + +#include <boost/process/windows/child.hpp> +#include <boost/fusion/algorithm/iteration/for_each.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { + +struct executor +{ + executor() : exe(0), cmd_line(0), proc_attrs(0), thread_attrs(0), + inherit_handles(FALSE), +#if (_WIN32_WINNT >= 0x0600) + creation_flags(EXTENDED_STARTUPINFO_PRESENT), +#else + creation_flags(0), +#endif + env(0), work_dir(0) +#if (_WIN32_WINNT >= 0x0600) + ,startup_info(startup_info_ex.StartupInfo) +#endif + { +#if (_WIN32_WINNT >= 0x0600) + ZeroMemory(&startup_info_ex, sizeof(STARTUPINFOEX)); + startup_info.cb = sizeof(STARTUPINFOEX); +#else + ZeroMemory(&startup_info, sizeof(STARTUPINFO)); + startup_info.cb = sizeof(STARTUPINFO); +#endif + startup_info.hStdInput = INVALID_HANDLE_VALUE; + startup_info.hStdOutput = INVALID_HANDLE_VALUE; + startup_info.hStdError = INVALID_HANDLE_VALUE; + } + + struct call_on_CreateProcess_setup + { + executor &e_; + + call_on_CreateProcess_setup(executor &e) : e_(e) {} + + template <class Arg> + void operator()(Arg &arg) const + { + arg.on_CreateProcess_setup(e_); + } + }; + + struct call_on_CreateProcess_error + { + executor &e_; + + call_on_CreateProcess_error(executor &e) : e_(e) {} + + template <class Arg> + void operator()(Arg &arg) const + { + arg.on_CreateProcess_error(e_); + } + }; + + struct call_on_CreateProcess_success + { + executor &e_; + + call_on_CreateProcess_success(executor &e) : e_(e) {} + + template <class Arg> + void operator()(Arg &arg) const + { + arg.on_CreateProcess_success(e_); + } + }; + + template <class InitializerSequence> + child operator()(const InitializerSequence &seq) + { + boost::fusion::for_each(seq, call_on_CreateProcess_setup(*this)); + + if (!::CreateProcess( + exe, + cmd_line, + proc_attrs, + thread_attrs, + inherit_handles, + creation_flags, + env, + work_dir, + &startup_info, + &proc_info)) + { + boost::fusion::for_each(seq, call_on_CreateProcess_error(*this)); + } + else + { + boost::fusion::for_each(seq, call_on_CreateProcess_success(*this)); + } + + return child(proc_info); + } + + LPCTSTR exe; + LPTSTR cmd_line; + LPSECURITY_ATTRIBUTES proc_attrs; + LPSECURITY_ATTRIBUTES thread_attrs; + BOOL inherit_handles; + DWORD creation_flags; + LPVOID env; + LPCTSTR work_dir; +#if (_WIN32_WINNT >= 0x0600) + STARTUPINFOEX startup_info_ex; + STARTUPINFO &startup_info; +#else + STARTUPINFO startup_info; +#endif + PROCESS_INFORMATION proc_info; +}; + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers.hpp new file mode 100644 index 0000000000..2d7098c034 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_HPP + +#include <boost/process/windows/initializers/bind_stderr.hpp> +#include <boost/process/windows/initializers/bind_stdin.hpp> +#include <boost/process/windows/initializers/bind_stdout.hpp> +#include <boost/process/windows/initializers/close_stderr.hpp> +#include <boost/process/windows/initializers/close_stdin.hpp> +#include <boost/process/windows/initializers/close_stdout.hpp> +#include <boost/process/windows/initializers/hide_console.hpp> +#include <boost/process/windows/initializers/inherit_env.hpp> +#include <boost/process/windows/initializers/on_CreateProcess_error.hpp> +#include <boost/process/windows/initializers/on_CreateProcess_setup.hpp> +#include <boost/process/windows/initializers/on_CreateProcess_success.hpp> +#include <boost/process/windows/initializers/run_exe.hpp> +#include <boost/process/windows/initializers/set_args.hpp> +#include <boost/process/windows/initializers/set_cmd_line.hpp> +#include <boost/process/windows/initializers/set_env.hpp> +#include <boost/process/windows/initializers/set_on_error.hpp> +#include <boost/process/windows/initializers/show_window.hpp> +#include <boost/process/windows/initializers/start_in_dir.hpp> +#include <boost/process/windows/initializers/throw_on_error.hpp> + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stderr.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stderr.hpp new file mode 100644 index 0000000000..de3ee30dc5 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stderr.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDERR_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDERR_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class bind_stderr : public initializer_base +{ +public: + explicit bind_stderr(const boost::iostreams::file_descriptor_sink &sink) : sink_(sink) {} + + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + ::SetHandleInformation(sink_.handle(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); + e.startup_info.hStdError = sink_.handle(); + e.startup_info.dwFlags |= STARTF_USESTDHANDLES; + e.inherit_handles = true; + } + +private: + boost::iostreams::file_descriptor_sink sink_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdin.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdin.hpp new file mode 100644 index 0000000000..54c942ab63 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdin.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDIN_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDIN_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class bind_stdin : public initializer_base +{ +public: + explicit bind_stdin(const boost::iostreams::file_descriptor_source &source) : source_(source) {} + + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + ::SetHandleInformation(source_.handle(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); + e.startup_info.hStdInput = source_.handle(); + e.startup_info.dwFlags |= STARTF_USESTDHANDLES; + e.inherit_handles = true; + } + +private: + boost::iostreams::file_descriptor_source source_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdout.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdout.hpp new file mode 100644 index 0000000000..c72c05f1bf --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/bind_stdout.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDOUT_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_BIND_STDOUT_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class bind_stdout : public initializer_base +{ +public: + explicit bind_stdout(const boost::iostreams::file_descriptor_sink &sink) : sink_(sink) {} + + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + ::SetHandleInformation(sink_.handle(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); + e.startup_info.hStdOutput = sink_.handle(); + e.startup_info.dwFlags |= STARTF_USESTDHANDLES; + e.inherit_handles = true; + } + +private: + boost::iostreams::file_descriptor_sink sink_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stderr.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stderr.hpp new file mode 100644 index 0000000000..373c097f3a --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stderr.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDERR_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDERR_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class close_stderr : public initializer_base +{ +public: + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + e.startup_info.hStdError = INVALID_HANDLE_VALUE; + e.startup_info.dwFlags |= STARTF_USESTDHANDLES; + } +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdin.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdin.hpp new file mode 100644 index 0000000000..036b0bb4ce --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdin.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDIN_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDIN_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class close_stdin : public initializer_base +{ +public: + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + e.startup_info.hStdInput = INVALID_HANDLE_VALUE; + e.startup_info.dwFlags |= STARTF_USESTDHANDLES; + } +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdout.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdout.hpp new file mode 100644 index 0000000000..b58a6000f9 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/close_stdout.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDOUT_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_STDOUT_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class close_stdout : public initializer_base +{ +public: + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + e.startup_info.hStdOutput = INVALID_HANDLE_VALUE; + e.startup_info.dwFlags |= STARTF_USESTDHANDLES; + } +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/hide_console.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/hide_console.hpp new file mode 100644 index 0000000000..b01aa026f0 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/hide_console.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_HIDE_CONSOLE_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_HIDE_CONSOLE_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class hide_console : public initializer_base +{ +public: + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + e.startup_info.dwFlags |= STARTF_USESHOWWINDOW; + e.startup_info.wShowWindow |= SW_HIDE; + } +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/inherit_env.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/inherit_env.hpp new file mode 100644 index 0000000000..a2b2eda00a --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/inherit_env.hpp @@ -0,0 +1,24 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_INHERIT_ENV_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_INHERIT_ENV_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class inherit_env : public initializer_base +{ +public: +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/initializer_base.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/initializer_base.hpp new file mode 100644 index 0000000000..b98da7b21b --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/initializer_base.hpp @@ -0,0 +1,29 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_INITIALIZER_BASE_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_INITIALIZER_BASE_HPP + +namespace boost { namespace process { namespace windows { namespace initializers { + +struct initializer_base +{ + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor&) const {} + + template <class WindowsExecutor> + void on_CreateProcess_error(WindowsExecutor&) const {} + + template <class WindowsExecutor> + void on_CreateProcess_success(WindowsExecutor&) const {} +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_error.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_error.hpp new file mode 100644 index 0000000000..71eeada072 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_error.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_ERROR_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_ERROR_HPP + +#include <boost/process/config.hpp> +#include <boost/process/windows/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace windows { namespace initializers { + +template <class Handler> +class on_CreateProcess_error_ : public initializer_base +{ +public: + explicit on_CreateProcess_error_(Handler handler) : handler_(handler) {} + + template <class WindowsExecutor> + void on_CreateProcess_error(WindowsExecutor &e) const + { + handler_(e); + } + +private: + Handler handler_; +}; + +template <class Handler> +on_CreateProcess_error_<Handler> on_CreateProcess_error(Handler handler) +{ + return on_CreateProcess_error_<Handler>(handler); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_setup.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_setup.hpp new file mode 100644 index 0000000000..671fc9ac5c --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_setup.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_SETUP_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_SETUP_HPP + +#include <boost/process/config.hpp> +#include <boost/process/windows/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace windows { namespace initializers { + +template <class Handler> +class on_CreateProcess_setup_ : public initializer_base +{ +public: + explicit on_CreateProcess_setup_(Handler handler) : handler_(handler) {} + + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + handler_(e); + } + +private: + Handler handler_; +}; + +template <class Handler> +on_CreateProcess_setup_<Handler> on_CreateProcess_setup(Handler handler) +{ + return on_CreateProcess_setup_<Handler>(handler); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_success.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_success.hpp new file mode 100644 index 0000000000..67b3b2bdcf --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/on_CreateProcess_success.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_SUCCESS_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ON_CREATEPROCESS_SUCCESS_HPP + +#include <boost/process/config.hpp> +#include <boost/process/windows/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace windows { namespace initializers { + +template <class Handler> +class on_CreateProcess_success_ : public initializer_base +{ +public: + explicit on_CreateProcess_success_(Handler handler) : handler_(handler) {} + + template <class WindowsExecutor> + void on_CreateProcess_sucess(WindowsExecutor &e) const + { + handler_(e); + } + +private: + Handler handler_; +}; + +template <class Handler> +on_CreateProcess_success_<Handler> on_CreateProcess_success(Handler handler) +{ + return on_CreateProcess_success_<Handler>(handler); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/run_exe.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/run_exe.hpp new file mode 100644 index 0000000000..bfa2b790b1 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/run_exe.hpp @@ -0,0 +1,69 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_RUN_EXE_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_RUN_EXE_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <boost/filesystem.hpp> +#include <string> + +namespace boost { namespace process { namespace windows { namespace initializers { + +template <class String> +class run_exe_ : public initializer_base +{ +public: + explicit run_exe_(const String &s) : s_(s) {} + + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + e.exe = s_.c_str(); + } + +private: + String s_; +}; + +#if defined(_UNICODE) || defined(UNICODE) +inline run_exe_<std::wstring> run_exe(const wchar_t *ws) +{ + return run_exe_<std::wstring>(ws); +} + +inline run_exe_<std::wstring> run_exe(const std::wstring &ws) +{ + return run_exe_<std::wstring>(ws); +} + +inline run_exe_<std::wstring> run_exe(const boost::filesystem::path &p) +{ + return run_exe_<std::wstring>(p.wstring()); +} +#else +inline run_exe_<std::string> run_exe(const char *s) +{ + return run_exe_<std::string>(s); +} + +inline run_exe_<std::string> run_exe(const std::string &s) +{ + return run_exe_<std::string>(s); +} + +inline run_exe_<std::string> run_exe(const boost::filesystem::path &p) +{ + return run_exe_<std::string>(p.string()); +} +#endif + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/set_args.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_args.hpp new file mode 100644 index 0000000000..4b3c5b6249 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_args.hpp @@ -0,0 +1,87 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ARGS_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ARGS_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/algorithm/copy.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/shared_array.hpp> +#include <sstream> + +namespace boost { namespace process { namespace windows { namespace initializers { + +template <class Range> +class set_args_ : public initializer_base +{ +private: + typedef typename Range::const_iterator ConstIterator; + typedef typename Range::value_type String; + typedef typename String::value_type Char; + typedef std::basic_ostringstream<Char> OStringStream; + +public: + explicit set_args_(const Range &args) + { + ConstIterator it = boost::const_begin(args); + ConstIterator end = boost::const_end(args); + if (it != end) + { + exe_ = *it; + OStringStream os; + for (; it != end; ++it) + { + if (boost::algorithm::contains(*it, + String(1, static_cast<Char>(' ')))) + { + os << static_cast<Char>('"') << *it << + static_cast<Char>('"'); + } + else + { + os << *it; + } + os << static_cast<Char>(' '); + } + String s = os.str(); + cmd_line_.reset(new Char[s.size() + 1]); + boost::copy(s, cmd_line_.get()); + cmd_line_[s.size()] = 0; + } + else + { + cmd_line_.reset(new Char[1]()); + } + } + + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + e.cmd_line = cmd_line_.get(); + if (!e.exe && !exe_.empty()) + e.exe = exe_.c_str(); + } + +private: + boost::shared_array<Char> cmd_line_; + String exe_; +}; + +template <class Range> +set_args_<Range> set_args(const Range &range) +{ + return set_args_<Range>(range); +} + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/set_cmd_line.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_cmd_line.hpp new file mode 100644 index 0000000000..a3d9f6f761 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_cmd_line.hpp @@ -0,0 +1,68 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_CMD_LINE_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_CMD_LINE_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <boost/range/algorithm/copy.hpp> +#include <boost/shared_array.hpp> +#include <memory> + +namespace boost { namespace process { namespace windows { namespace initializers { + +template <class String> +class set_cmd_line_ : public initializer_base +{ +private: + typedef typename String::value_type Char; + +public: + explicit set_cmd_line_(const String &s) + : cmd_line_(new Char[s.size() + 1]) + { + boost::copy(s, cmd_line_.get()); + cmd_line_[s.size()] = 0; + } + + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + e.cmd_line = cmd_line_.get(); + } + +private: + boost::shared_array<Char> cmd_line_; +}; + +#if defined(_UNICODE) || defined(UNICODE) +inline set_cmd_line_<std::wstring> set_cmd_line(const wchar_t *ws) +{ + return set_cmd_line_<std::wstring>(ws); +} + +inline set_cmd_line_<std::wstring> set_cmd_line(const std::wstring &ws) +{ + return set_cmd_line_<std::wstring>(ws); +} +#else +inline set_cmd_line_<std::string> set_cmd_line(const char *s) +{ + return set_cmd_line_<std::string>(s); +} + +inline set_cmd_line_<std::string> set_cmd_line(const std::string &s) +{ + return set_cmd_line_<std::string>(s); +} +#endif + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/set_env.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_env.hpp new file mode 100644 index 0000000000..6dfdfc58a4 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_env.hpp @@ -0,0 +1,88 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ENV_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ENV_HPP + +#include <Windows.h> +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <boost/range/numeric.hpp> +#include <boost/range/algorithm/copy.hpp> +#include <boost/range/algorithm/for_each.hpp> +#include <boost/shared_array.hpp> +#include <iterator> +#include <cstddef> + +namespace boost { namespace process { namespace windows { namespace initializers { + +template <class Range, bool Unicode> +class set_env_ : public initializer_base +{ +private: + typedef typename Range::value_type String; + typedef typename String::value_type Char; + + static std::size_t add_size(std::size_t size, const String &s) + { + return size + s.size() + 1u; + } + + struct copy + { + Char *it_; + + copy(Char *it) : it_(it) {} + + void operator()(const String &s) + { + it_ = boost::copy(s, it_); + *it_ = 0; + ++it_; + } + }; + +public: + set_env_(const Range &envs) + : size_(boost::accumulate(envs, 0, add_size) + 1), + env_(new Char[size_]) + { + boost::for_each(envs, copy(env_.get())); + env_[size_ - 1] = 0; + } + + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + e.env = env_.get(); + if (Unicode) + e.creation_flags |= CREATE_UNICODE_ENVIRONMENT; + } + +private: + std::size_t size_; + boost::shared_array<Char> env_; +}; + +#if defined(_UNICODE) || defined(UNICODE) +template <class Range> +set_env_<Range, true> set_env(const Range &envs) +{ + return set_env_<Range, true>(envs); +} +#else +template <class Range> +set_env_<Range, false> set_env(const Range &envs) +{ + return set_env_<Range, false>(envs); +} +#endif + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/set_on_error.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_on_error.hpp new file mode 100644 index 0000000000..695ea5904d --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/set_on_error.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ON_ERROR_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SET_ON_ERROR_HPP + +#include <boost/process/config.hpp> +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <boost/system/error_code.hpp> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class set_on_error : public initializer_base +{ +public: + explicit set_on_error(boost::system::error_code &ec) : ec_(ec) {} + + template <class WindowsExecutor> + void on_CreateProcess_error(WindowsExecutor&) const + { + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec_); + } + +private: + boost::system::error_code &ec_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/show_window.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/show_window.hpp new file mode 100644 index 0000000000..3046179205 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/show_window.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_SHOW_WINDOW_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_SHOW_WINDOW_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class show_window : public initializer_base +{ +public: + explicit show_window(WORD flags) : flags_(flags) {} + + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + e.startup_info.dwFlags |= STARTF_USESHOWWINDOW; + e.startup_info.wShowWindow |= flags_; + } + +private: + WORD flags_; +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/start_in_dir.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/start_in_dir.hpp new file mode 100644 index 0000000000..8dc952abcc --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/start_in_dir.hpp @@ -0,0 +1,69 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_START_IN_DIR_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_START_IN_DIR_HPP + +#include <boost/process/windows/initializers/initializer_base.hpp> +#include <boost/filesystem/path.hpp> +#include <string> + +namespace boost { namespace process { namespace windows { namespace initializers { + +template <class String> +class start_in_dir_ : public initializer_base +{ +public: + explicit start_in_dir_(const String &s) : s_(s) {} + + template <class WindowsExecutor> + void on_CreateProcess_setup(WindowsExecutor &e) const + { + e.work_dir = s_.c_str(); + } + +private: + String s_; +}; + +#if defined(_UNICODE) || defined(UNICODE) +inline start_in_dir_<std::wstring> start_in_dir(const wchar_t *ws) +{ + return start_in_dir_<std::wstring>(ws); +} + +inline start_in_dir_<std::wstring> start_in_dir(const std::wstring &ws) +{ + return start_in_dir_<std::wstring>(ws); +} + +inline start_in_dir_<std::wstring> start_in_dir(const boost::filesystem::path &p) +{ + return start_in_dir_<std::wstring>(p.wstring()); +} +#else +inline start_in_dir_<std::string> start_in_dir(const char *s) +{ + return start_in_dir_<std::string>(s); +} + +inline start_in_dir_<std::string> start_in_dir(const std::string &s) +{ + return start_in_dir_<std::string>(s); +} + +inline start_in_dir_<std::string> start_in_dir(const boost::filesystem::path &p) +{ + return start_in_dir_<std::string>(p.string()); +} +#endif + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/initializers/throw_on_error.hpp b/plugins/New_GPG/src/include/boost/process/windows/initializers/throw_on_error.hpp new file mode 100644 index 0000000000..044fa00417 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/initializers/throw_on_error.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_THROW_ON_ERROR_HPP +#define BOOST_PROCESS_WINDOWS_INITIALIZERS_THROW_ON_ERROR_HPP + +#include <boost/process/config.hpp> +#include <boost/process/windows/initializers/initializer_base.hpp> + +namespace boost { namespace process { namespace windows { namespace initializers { + +class throw_on_error : public initializer_base +{ +public: + template <class WindowsExecutor> + void on_CreateProcess_error(WindowsExecutor&) const + { + BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed"); + } +}; + +}}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/pipe.hpp b/plugins/New_GPG/src/include/boost/process/windows/pipe.hpp new file mode 100644 index 0000000000..fd912afcc9 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/pipe.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_PIPE_HPP +#define BOOST_PROCESS_WINDOWS_PIPE_HPP + +#include <Windows.h> + +namespace boost { namespace process { namespace windows { + +struct pipe +{ + HANDLE source; + HANDLE sink; + + pipe(HANDLE source, HANDLE sink) : source(source), sink(sink) {} +}; + +inline pipe make_pipe(HANDLE source, HANDLE sink) +{ + return pipe(source, sink); +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/search_path.hpp b/plugins/New_GPG/src/include/boost/process/windows/search_path.hpp new file mode 100644 index 0000000000..62bb5f2745 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/search_path.hpp @@ -0,0 +1,104 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_SEARCH_PATH_HPP +#define BOOST_PROCESS_WINDOWS_SEARCH_PATH_HPP + +#include <boost/process/config.hpp> +#include <boost/filesystem.hpp> +#include <boost/tokenizer.hpp> +#include <boost/array.hpp> +#include <boost/system/error_code.hpp> +#include <string> +#include <stdexcept> +#include <stdlib.h> +#include <Shellapi.h> + +namespace boost { namespace process { namespace windows { + +#if defined(_UNICODE) || defined(UNICODE) +inline std::wstring search_path(const std::wstring &filename, + std::wstring path = L"") +{ + if (path.empty()) + { + path = ::_wgetenv(L"PATH"); + if (path.empty()) + BOOST_PROCESS_THROW(std::runtime_error( + "Environment variable PATH not found")); + } + + typedef boost::tokenizer<boost::char_separator<wchar_t>, + std::wstring::const_iterator, std::wstring> tokenizer; + boost::char_separator<wchar_t> sep(L";"); + tokenizer tok(path, sep); + for (tokenizer::iterator it = tok.begin(); it != tok.end(); ++it) + { + boost::filesystem::path p = *it; + p /= filename; + boost::array<std::wstring, 4> extensions = + { L"", L".exe", L".com", L".bat" }; + for (boost::array<std::wstring, 4>::iterator it2 = extensions.begin(); + it2 != extensions.end(); ++it2) + { + boost::filesystem::path p2 = p; + p2 += *it2; + boost::system::error_code ec; + bool file = boost::filesystem::is_regular_file(p2, ec); + if (!ec && file && + SHGetFileInfoW(p2.c_str(), 0, 0, 0, SHGFI_EXETYPE)) + { + return p2.wstring(); + } + } + } + return L""; +} +#else +inline std::string search_path(const std::string &filename, + std::string path = "") +{ + if (path.empty()) + { + path = ::getenv("PATH"); + if (path.empty()) + BOOST_PROCESS_THROW(std::runtime_error( + "Environment variable PATH not found")); + } + + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep(";"); + tokenizer tok(path, sep); + for (tokenizer::iterator it = tok.begin(); it != tok.end(); ++it) + { + boost::filesystem::path p = *it; + p /= filename; + boost::array<std::string, 4> extensions = + { "", ".exe", ".com", ".bat" }; + for (boost::array<std::string, 4>::iterator it2 = extensions.begin(); + it2 != extensions.end(); ++it2) + { + boost::filesystem::path p2 = p; + p2 += *it2; + boost::system::error_code ec; + bool file = boost::filesystem::is_regular_file(p2, ec); + if (!ec && file && + SHGetFileInfoA(p2.string().c_str(), 0, 0, 0, SHGFI_EXETYPE)) + { + return p2.string(); + } + } + } + return ""; +} +#endif + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/shell_path.hpp b/plugins/New_GPG/src/include/boost/process/windows/shell_path.hpp new file mode 100644 index 0000000000..ace15b96e1 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/shell_path.hpp @@ -0,0 +1,50 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_SHELL_PATH_HPP +#define BOOST_PROCESS_WINDOWS_SHELL_PATH_HPP + +#include <boost/process/config.hpp> +#include <boost/system/error_code.hpp> +#include <boost/filesystem/path.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { + +inline boost::filesystem::path shell_path() +{ + TCHAR sysdir[MAX_PATH]; + UINT size = ::GetSystemDirectory(sysdir, sizeof(sysdir)); + if (!size) + BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetSystemDirectory() failed"); + boost::filesystem::path p = sysdir; + return p / "cmd.exe"; +} + +inline boost::filesystem::path shell_path(boost::system::error_code &ec) +{ + TCHAR sysdir[MAX_PATH]; + UINT size = ::GetSystemDirectory(sysdir, sizeof(sysdir)); + boost::filesystem::path p; + if (!size) + { + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec); + } + else + { + ec.clear(); + p = sysdir; + p /= "cmd.exe"; + } + return p; +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/terminate.hpp b/plugins/New_GPG/src/include/boost/process/windows/terminate.hpp new file mode 100644 index 0000000000..43afe250a6 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/terminate.hpp @@ -0,0 +1,38 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_TERMINATE_HPP +#define BOOST_PROCESS_WINDOWS_TERMINATE_HPP + +#include <boost/process/config.hpp> +#include <boost/system/error_code.hpp> +#include <cstdlib> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { + +template <class Process> +void terminate(const Process &p) +{ + if (!::TerminateProcess(p.process_handle(), EXIT_FAILURE)) + BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("TerminateProcess() failed"); +} + +template <class Process> +void terminate(const Process &p, boost::system::error_code &ec) +{ + if (!::TerminateProcess(p.process_handle(), EXIT_FAILURE)) + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec); + else + ec.clear(); +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/boost/process/windows/wait_for_exit.hpp b/plugins/New_GPG/src/include/boost/process/windows/wait_for_exit.hpp new file mode 100644 index 0000000000..23a8b9a9f1 --- /dev/null +++ b/plugins/New_GPG/src/include/boost/process/windows/wait_for_exit.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_WINDOWS_WAIT_FOR_EXIT_HPP +#define BOOST_PROCESS_WINDOWS_WAIT_FOR_EXIT_HPP + +#include <boost/process/config.hpp> +#include <boost/system/error_code.hpp> +#include <Windows.h> + +namespace boost { namespace process { namespace windows { + +template <class Process> +inline DWORD wait_for_exit(const Process &p) +{ + if (::WaitForSingleObject(p.process_handle(), INFINITE) == WAIT_FAILED) + BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("WaitForSingleObject() failed"); + + DWORD exit_code; + if (!::GetExitCodeProcess(p.process_handle(), &exit_code)) + BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetExitCodeProcess() failed"); + + return exit_code; +} + +template <class Process> +inline DWORD wait_for_exit(const Process &p, boost::system::error_code &ec) +{ + DWORD exit_code = 1; + + if (::WaitForSingleObject(p.process_handle(), INFINITE) == WAIT_FAILED) + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec); + else if (!::GetExitCodeProcess(p.process_handle(), &exit_code)) + BOOST_PROCESS_RETURN_LAST_SYSTEM_ERROR(ec); + else + ec.clear(); + + return exit_code; +} + +}}} + +#endif diff --git a/plugins/New_GPG/src/include/libs/process/doc/Jamfile.jam b/plugins/New_GPG/src/include/libs/process/doc/Jamfile.jam new file mode 100644 index 0000000000..84dccbc466 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/doc/Jamfile.jam @@ -0,0 +1,31 @@ +# Copyright (c) 2006, 2007 Julio M. Merino Vidal +# Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +# Copyright (c) 2009 Boris Schaeling +# Copyright (c) 2010 Felipe Tanus, Boris Schaeling +# Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +using boostbook ; +using quickbook ; +using doxygen ; + +doxygen autodoc +: + ../../../boost/process.hpp + [ glob ../../../boost/process/*.hpp : ../../../boost/process/all.hpp ] +: + <doxygen:param>PREDEFINED=BOOST_PROCESS_DOXYGEN + <doxygen:param>HIDE_UNDOC_CLASSES=YES + <doxygen:param>HIDE_UNDOC_MEMBERS=YES +; + +boostbook standalone +: + process.qbk +: + <dependency>autodoc + <xsl:param>boost.root=../../../.. + <xml:param>html.stylesheet=../../../../doc/src/boostbook.css +; diff --git a/plugins/New_GPG/src/include/libs/process/doc/acknowledgements.qbk b/plugins/New_GPG/src/include/libs/process/doc/acknowledgements.qbk new file mode 100644 index 0000000000..136726050e --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/doc/acknowledgements.qbk @@ -0,0 +1,9 @@ +[section Acknowledgements] + +The first Boost.Process draft was created in 2006. A lof of people have worked on various drafts since then. Especially Merino Vidal, Ilya Sokolov and Felipe Tanus spent a lot of time working on early drafts. They influenced Boost.Process over the years and wrote code which, to various extents, is still around in the library today. + +The design of earlier versions of Boost.Process was not always satisfying. In 2011 Jeff Flinn proposed the executor and initializer concepts Boost.Process is based on today. Without Jeff's idea the overall design of Boost.Process would not look like it does today. + +A special thank you goes to [@http://www.intra2net.com/ Intra2net AG] (especially Thomas Jarosch) who sponsored a project to support the development of Boost.Process. It was this sponsorship which made it possible to create a new Boost.Process version in 2012. + +[endsect] diff --git a/plugins/New_GPG/src/include/libs/process/doc/faq.qbk b/plugins/New_GPG/src/include/libs/process/doc/faq.qbk new file mode 100644 index 0000000000..52f379290f --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/doc/faq.qbk @@ -0,0 +1,124 @@ +[section FAQ] + +[section Why does the parent process hang if a pipe is used to redirect a child's output stream?] + +The following program doesn't work as expected - the parent process never exits: + + #include <boost/process.hpp> + #include <boost/iostreams/device/file_descriptor.hpp> + #include <boost/iostreams/stream.hpp> + #include <iostream> + + using namespace boost::process; + using namespace boost::process::initializers; + using namespace boost::iostreams; + + int main() + { + boost::process::pipe p = create_pipe(); + file_descriptor_sink sink(p.sink, close_handle); + execute( + run_exe("/bin/echo"), + set_cmd_line("echo hello"), + bind_stdout(sink) + ); + file_descriptor_source source(p.source, close_handle); + stream<file_descriptor_source> is(source); + std::string s; + while (is >> s) + std::cout << s << std::endl; + } + +The program gets stuck in the `while`-loop as the write-end of the pipe is never closed. It is closed by the child process when it exits. But it is never closed in the parent process. *sink* has been initialized with *close_handle*. But as the destructor isn't called before the `while`-loop, the handle hasn't been closed yet. + +The program can be fixed by introducing another scope: + + #include <boost/process.hpp> + #include <boost/iostreams/device/file_descriptor.hpp> + #include <boost/iostreams/stream.hpp> + #include <iostream> + + using namespace boost::process; + using namespace boost::process::initializers; + using namespace boost::iostreams; + + int main() + { + boost::process::pipe p = create_pipe(); + { + file_descriptor_sink sink(p.sink, close_handle); + execute( + run_exe("/bin/echo"), + set_cmd_line("echo hello"), + bind_stdout(sink) + ); + } + file_descriptor_source source(p.source, close_handle); + stream<file_descriptor_source> is(source); + std::string s; + while (is >> s) + std::cout << s << std::endl; + } + +The destructor of *sink* will now be called before the `while`-loop. As there is no other write-end open anymore when the child process exits, the `while`-loop sees an end-of-file and can finish. + +[endsect] + +[section Why can executing /bin/ls make a parent process seem to hang?] + +If you run the following program on Linux, it sometimes doesn't seem to exit: + + #include <boost/process.hpp> + + using namespace boost::process; + using namespace boost::process::initializers; + + int main() + { + execute(run_exe("/bin/ls")); + } + +Don't let yourself get fooled! When */bin/ls* is executed, it runs in a different process. It's unknown whether your program or */bin/ls* exits first. If */bin/ls* exits first, you see this: + +[pre +boris@linux:\/> .\/test +afile anotherfile +boris@linux:\/> _ +] + +If your program exits first, you see this though: + +[pre +boris@linux:\/> .\/test +boris@linux:\/> afile anotherfile +_ +] + +It seems as if the program hangs as there is no prompt. And when you press `ENTER`, a new line with a prompt appears. But your program did exit. It's just that */bin/ls* printed the filenames after the prompt when your program had already exited. And that's what pushes your input cursor to the next line where a prompt seems to be missing. + +You could "fix" the program by waiting for the child process to exit: + + #include <boost/process.hpp> + + using namespace boost::process; + using namespace boost::process::initializers; + + int main() + { + child c = execute(run_exe("/bin/ls")); + wait_for_exit(c); + } + +Now it's guaranteed that */bin/ls* prints the filenames before your program exits and before you see the prompt again. + +[endsect] + +[section Is Boost.Process thread-safe?] + +No, Boost.Process is not thread-safe. + +Please note that even if you don't share Boost.Process objects between threads, you can run into problems. For example, file descriptors on POSIX and handles on Windows are global per process. If `boost::process::execute` is called in multiple threads, it is possible that file descriptors or handles are inherited by a child process which shouldn't inherit them. If these are ends of a pipe and another process expects that these ends are closed but a process accidently inherited them and doesn't even know he got the ends which should be closed, another process might wait forever for an end-of-file. While on POSIX an initializer like `boost::process::initializers::close_fds` could be used to close file descriptors, accidental "leaking" can't be prevented on Windows. This scenario can be avoided if for example always only one thread calls `boost::process::execute`. + +[endsect] + +[endsect] diff --git a/plugins/New_GPG/src/include/libs/process/doc/introduction.qbk b/plugins/New_GPG/src/include/libs/process/doc/introduction.qbk new file mode 100644 index 0000000000..bdf69980e5 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/doc/introduction.qbk @@ -0,0 +1,18 @@ +[section:introduction Introduction] + +Boost.Process is a library to manage system processes. It can be used to: + +* create child processes +* setup streams for child processes +* communicate with child processes through streams (synchronously or asynchronously) +* wait for processes to exit (synchronously or asynchronously) +* terminate processes + +Here's a simple example of how to start a program with Boost.Process: + +[import ../example/intro.cpp] +[intro] + +[caution This is not yet an official Boost C++ library. It wasn't reviewed and can't be downloaded from [@http://www.boost.org/ www.boost.org]. It is however the latest version of an ongoing effort to create a process management library for Boost. For now the library can be downloaded from [@http://www.highscore.de/boost/process0.5/process.zip http://www.highscore.de/boost/process0.5/process.zip].] + +[endsect] diff --git a/plugins/New_GPG/src/include/libs/process/doc/posix.qbk b/plugins/New_GPG/src/include/libs/process/doc/posix.qbk new file mode 100644 index 0000000000..768025b75d --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/doc/posix.qbk @@ -0,0 +1,40 @@ +[section POSIX specifics] + +[section Binding file descriptors] + +Use [classref boost::process::initializers::bind_fd bind_fd] to bind any file descriptor (not only a standard stream): + +[import ../example/posix.cpp] +[bind_fd] + +[endsect] + +[section Closing file descriptors] + +Use [classref boost::process::initializers::close_fd close_fd] to close a single file descriptor: + +[close_fd] + +Use [classref boost::process::initializers::close_fds close_fds] to close multiple file descriptors: + +[close_fds] + +Use [classref boost::process::initializers::close_fds_if close_fds_if] to close all file descriptors a predicate returns `true` for: + +[close_fds_if] + +[endsect] + +[section Arbitrary extensions] + +On POSIX [classref boost::process::executor executor] calls [@http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html `fork`] and [@http://pubs.opengroup.org/onlinepubs/009604499/functions/exec.html `execve`] to start a program. Boost.Process provides five generic initializers to run any code before `fork` is called, afterwards if `fork` failed or succeeded, before `execve` is called and afterwards if `execve` failed: [funcref boost::process::initializers::on_fork_setup on_fork_setup], [funcref boost::process::initializers::on_fork_error on_fork_error], [funcref boost::process::initializers::on_fork_success on_fork_success], [funcref boost::process::initializers::on_exec_setup on_exec_setup] and [funcref boost::process::initializers::on_exec_error on_exec_error]. These initializers can be used to arbitrarily extend Boost.Process: + +[fork_execve] + +The example sets the environment variable `LANG` to *de*. If `fork` fails, the system error is written to the standard error stream. If `fork` doesn't fail, `chroot` is called. This happens in the newly created (forked) process before `execve` is called. If `execve` fails, the system error is written to a file. + +[note Boost.Process guarantees to call initializers in the order they are passed to `execute`. The order is important if several initializers try to set the same member variables in the `executor`. The initializers provided by Boost.Process have been designed to work correctly no matter which order they are used in. You only have to be careful if you use the generic initializers [funcref boost::process::initializers::on_fork_setup on_fork_setup], [funcref boost::process::initializers::on_fork_error on_fork_error], [funcref boost::process::initializers::on_fork_success on_fork_success], [funcref boost::process::initializers::on_exec_setup on_exec_setup] and [funcref boost::process::initializers::on_exec_error on_exec_error].] + +[endsect] + +[endsect] diff --git a/plugins/New_GPG/src/include/libs/process/doc/process.qbk b/plugins/New_GPG/src/include/libs/process/doc/process.qbk new file mode 100644 index 0000000000..86d8bf7eaf --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/doc/process.qbk @@ -0,0 +1,20 @@ +[library Boost.Process + [quickbook 1.5] + [authors [Schaeling, Boris]] + [copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012 Julio M. Merino Vidal, Ilya Sokolov, Felipe Tanus, Jeff Flinn, Boris Schaeling] + [id process] + [dirname process] + [license + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) + ] +] + +[include introduction.qbk] +[include tutorial.qbk] +[include windows.qbk] +[include posix.qbk] +[include faq.qbk] +[xinclude autodoc.xml] +[include acknowledgements.qbk] diff --git a/plugins/New_GPG/src/include/libs/process/doc/tutorial.qbk b/plugins/New_GPG/src/include/libs/process/doc/tutorial.qbk new file mode 100644 index 0000000000..b4e213363c --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/doc/tutorial.qbk @@ -0,0 +1,219 @@ +[section Tutorial] + +[section Header files] + +Boost.Process is a header-only library. It comes with a convenience header file which is the only one you need to include to make use of all library features: + + #include <boost/process.hpp> + +All examples in this tutorial assume this header file is included. + +[note The header file [headerref boost/process/mitigate.hpp] is not included by [headerref boost/process.hpp]. It contains helpers to mitigate platform differences. As these helpers can have subtle side effects, [headerref boost/process/mitigate.hpp] must be included explicitly.] + +[endsect] + +[section Namespaces] + +Most definitions can be found in one namespace: + + boost::process + +For example, the most important function [funcref boost::process::execute execute] to start a program is defined in `boost::process`. + +There is a second namespace used by Boost.Process: + + boost::process::initializers + +This namespace is used for initializers. Initializers are the parameters passed to [funcref boost::process::execute execute]. As you commonly use initializers provided by Boost.Process, you need to use this namespace, too. + +[endsect] + +[section Starting a program] + +The function Boost.Process provides to start a program is [funcref boost::process::execute execute]. You need to pass at least one initializer as a parameter. Think of initializers as named parameters. With the initializer [classref boost::process::initializers::run_exe run_exe] you refer to the program you want to start: + +[import ../example/execute.cpp] +[execute] + +[classref boost::process::initializers::run_exe run_exe] expects an exact filename. For instance, you can't leave out the file extension. [classref boost::process::initializers::run_exe run_exe] does not automatically search for a program either. In the example above Boost.Process expects to find *test.exe* in the current work directory. + +You can refer to programs in other directories with an absolute or relative path. It is also possible to use [classref boost::filesystem::path]: + +[execute_path] + +Boost.Process provides two utility functions to lookup executables: Call [funcref boost::process::search_path search_path] if you want to find an executable in the directories of the environment variable PATH. Or call [funcref boost::process::shell_path shell_path] for the system's shell. + +[endsect] + +[section Cleaning up resources] + +If you have a long-running program starting other programs with [funcref boost::process::execute execute], you want to be careful cleaning up resources. Resources are for example entries in the system's process table on POSIX and handlers to child processes on Windows. + +The only reliable cross-platform solution to clean up resources is to call [funcref boost::process::wait_for_exit wait_for_exit]: + +[import ../example/cleanup.cpp] +[cleanup] + +[funcref boost::process::wait_for_exit wait_for_exit] is a blocking function. The function returns when the child process exits. Calling [funcref boost::process::wait_for_exit wait_for_exit] guarantees that all resources are cleaned up. + +There are other platform-specific solutions to clean up resources. Boost.Process provides the macros [macroref BOOST_POSIX_API] and [macroref BOOST_WINDOWS_API] if you need to distinguish between platforms. On POSIX you can call [@http://pubs.opengroup.org/onlinepubs/009604599/functions/signal.html `signal`] for example to ignore SIGCHLD: + +[cleanup_posix] + +If SIGCHLD is ignored, a child process isn't added to the system's process table. There is no need then to call [funcref boost::process::wait_for_exit wait_for_exit]. It is important to ignore SIGCHLD before the child process exits though. For instance, call `signal` before you call [funcref boost::process::execute execute] as in the example above. + +[cleanup_windows] + +On Windows [classref boost::process::child child] is a movable but non-copyable type. The destructor closes handles to the child process when the instance of [classref boost::process::child child] goes out of scope. On Windows it's not strictly required to call [funcref boost::process::wait_for_exit wait_for_exit] to clean up resources. + +[endsect] + +[section Handling errors] + +Boost.Process provides two initializers to detect errors. Use [classref boost::process::initializers::set_on_error set_on_error] if you want [funcref boost::process::execute execute] to return an error: + +[import ../example/error_handling.cpp] +[set_on_error] + +Use [classref boost::process::initializers::throw_on_error throw_on_error] if you want [funcref boost::process::execute execute] to throw an exception: + +[throw_on_error] + +The type of the exception thrown by [classref boost::process::initializers::throw_on_error throw_on_error] is [classref boost::system::system_error]. + +[note On POSIX [classref boost::process::initializers::set_on_error set_on_error] and [classref boost::process::initializers::throw_on_error throw_on_error] detect a failed call to [@http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html `fork`] and [@http://pubs.opengroup.org/onlinepubs/009604499/functions/exec.html `execve`]. If `execve` fails the initializers send *errno* through a pipe from the child to the parent process. The pipe is automatically closed no matter whether `execve` succeeds or fails.] + +[endsect] + +[section Setting command line arguments] + +Use the initializer [classref boost::process::initializers::set_args set_args] to set command line arguments: + +[import ../example/args.cpp] +[args] + +If [classref boost::process::initializers::set_args set_args] is used, [classref boost::process::initializers::run_exe run_exe] may be omitted. The first command line argument must then refer to the program to start. + +Alternatively use the initializer [classref boost::process::initializers::set_cmd_line set_cmd_line] to set the command line: + +[import ../example/cmd_line.cpp] +[cmd_line] + +You can use [classref boost::process::initializers::set_cmd_line set_cmd_line] to set a command line like you would if you started the program in the shell. Just like in the shell you must start the command line with the name of the program. + +You must not omit [classref boost::process::initializers::run_exe run_exe] if you use [classref boost::process::initializers::set_cmd_line set_cmd_line]. + +[note If you don't use [classref boost::process::initializers::set_args set_args] or [classref boost::process::initializers::set_cmd_line set_cmd_line] the path you pass to [classref boost::process::initializers::run_exe run_exe] is forwarded as the only argument to a program. That is the argument which is accessible through `argv[0]` (assuming `argv` is the name of the parameter in `main`).] + +[endsect] + +[section Starting in a specific work directory] + +Use the initializer [classref boost::process::initializers::start_in_dir start_in_dir] to set the work directory: + +[import ../example/work_dir.cpp] +[work_dir] + +[classref boost::process::initializers::start_in_dir start_in_dir] also supports [classref boost::filesystem::path]. + +For portability reasons you want to use an absolute path with [classref boost::process::initializers::run_exe run_exe] if you set the work directory with [classref boost::process::initializers::start_in_dir start_in_dir]: + +[work_dir_abs] + +On Windows a relative path is relative to the work directory of the parent process. On POSIX a relative path is relative to the work directory set with [classref boost::process::initializers::start_in_dir start_in_dir] as the directory is changed before the program starts. + +[tip Use an absolute path with [classref boost::process::initializers::run_exe run_exe] if you set the work directory with [classref boost::process::initializers::start_in_dir start_in_dir] to avoid portability problems.] + +[endsect] + +[section Inheriting environment variables] + +Boost.Process provides the initializer [classref boost::process::initializers::inherit_env inherit_env] to inherit environment variables: + +[import ../example/env.cpp] +[inherit_env] + +While [classref boost::process::initializers::inherit_env inherit_env] is required on POSIX, environment variables are also inherited without this initializer on Windows as on Windows environment variables are inherited by default. + +If you want to set environment variables for the child process explicitly, use the initializer [classref boost::process::initializers::set_env set_env]. + +[endsect] + +[section Setting up standard streams] + +Boost.Process provides the initializers [classref boost::process::initializers::bind_stdin bind_stdin], [classref boost::process::initializers::bind_stdout bind_stdout] and [classref boost::process::initializers::bind_stderr bind_stderr] to setup standard streams. They are based on the classes [classref boost::iostreams::file_descriptor_source] and [classref boost::iostreams::file_descriptor_sink] from Boost.Iostreams: + +[import ../example/streams.cpp] +[stdout] + +In the example above the standard output stream of the child process is bound to a file. All data written by the child process to the standard output stream is written to *stdout.txt*. Have a look at the [@boost:/libs/iostreams/index.html Boost.Iostreams documentation] to find out what other devices you can use with [classref boost::iostreams::file_descriptor_source] and [classref boost::iostreams::file_descriptor_sink]. + +[note If you don't bind a stream with one of the initializers it depends on the platform where the streams are bound to. On Windows the streams are bound to the console by default. On POSIX the streams are inherited from the parent process and are bound to whatever they are bound to in the parent process.] + +If you want to close streams for a child process, use [classref boost::process::initializers::close_stdin close_stdin], [classref boost::process::initializers::close_stdout close_stdout] and [classref boost::process::initializers::close_stderr close_stderr]: + +[close_in_err] + +For POSIX Boost.Process also provides [classref boost::process::initializers::close_fd close_fd] to close a single file descriptor, [classref boost::process::initializers::close_fds close_fds] to close multiple file descriptors and [classref boost::process::initializers::close_fds_if close_fds_if] to close all file descriptors a predicate returns `true` for. + +[endsect] + +[section Synchronous I/O] + +Boost.Process provides the function [funcref boost::process::create_pipe create_pipe] to create an anonymous pipe. A parent and child process can use the pipe to send and receive data: + +[import ../example/sync_io.cpp] +[sync_io] + +In the example above the standard output stream of the child process is bound to the write-end of the pipe. The read-end is used by the parent process to receive data. The class [classref boost::iostreams::stream] is another class provided by Boost.Iostreams to wrap file descriptor sources or sinks. + +[note There is a [@https://svn.boost.org/trac/boost/ticket/6576 Boost.Iostreams bug] on Windows in all versions up to 1.50.0. If you read from a [classref boost::iostreams::file_descriptor_source] which has been initialized with the read-end of a pipe, and the write-end of the pipe has been closed, an exception is thrown.] + +[endsect] + +[section Asynchronous I/O] + +With the help of [@boost:/libs/asio/index.html Boost.Asio] it's possible to send and receive data between parent and child processes asynchronously. On Windows a named pipe must be used though as Windows doesn't support asynchronous I/O with anonymous pipes. That's why [funcref boost::process::create_pipe create_pipe] can't be used for asynchronous I/O - at least not on Windows. The following example expects that a function called `create_async_pipe` has been defined which returns a pipe on all platforms supporting asynchronous I/O: + +[import ../example/async_io.cpp] +[async_io] + +For asynchronous I/O Boost.Asio must be used. Boost.Asio provides the I/O objects [classref boost::asio::windows::stream_handle] on Windows and [classref boost::asio::posix::stream_descriptor] on POSIX which can be initialized with a read- or write-end of a pipe. Once the I/O objects have been created it's possible to use the asynchronous operations Boost.Asio provides. + +[note [headerref boost/process/mitigate.hpp] provides a typedef [classref boost::process::pipe_end] for the two Boost.Asio types.] + +[note There is a [@https://svn.boost.org/trac/boost/ticket/6576 Boost.Iostreams bug] on Windows in all versions up to 1.50.0. If you read from a [classref boost::iostreams::file_descriptor_source] which has been initialized with the read-end of a pipe, and the write-end of the pipe has been closed, an exception is thrown.] + +[note Please note that `create_async_pipe` is not provided by Boost.Process. First, the concept of an asynchronous pipe is artificial and only introduced for Boost.Process. Platforms distinguish between anonymous and named pipes. Secondly, there are too many options to define a named pipe - that's the only pipe supporting asynchronous I/O on Windows - that it's not an easy exercise to create a platform-independent `create_named_pipe` function.] + +[endsect] + +[section Waiting for a program to exit] + +Call [funcref boost::process::wait_for_exit wait_for_exit] to wait for a program to exit: + +[import ../example/wait.cpp] +[sync] + +On Windows [funcref boost::process::wait_for_exit wait_for_exit] returns the exit code of the program as a `DWORD`. On POSIX the function returns the status of the program as an `int`. `DWORD` is defined as `unsigned long`. While both are numeric integer types, you must use the macro [@http://pubs.opengroup.org/onlinepubs/009695399/functions/wait.html `WEXITSTATUS`] to get the exit code on POSIX. + +[note [headerref boost/process/mitigate.hpp] defines a macro [macroref BOOST_PROCESS_EXITSTATUS] which works like `WEXITSTATUS` on POSIX and casts to `int` on Windows. You can use this macro to get the exit code as an `int` on all platforms.] + +[funcref boost::process::wait_for_exit wait_for_exit] is a blocking function. If you want to wait asynchronously, use Boost.Process together with [@boost:/libs/asio/index.html Boost.Asio]: + +[async] + +[endsect] + +[section Terminating a program] + +Call [funcref boost::process::terminate terminate] to close a program: + +[import ../example/terminate.cpp] +[terminate] + +[funcref boost::process::terminate terminate] closes a program immediately and forcefully. It is a last resort function as it doesn't give the program to be closed any chance to clean up resources. For instance, if the program is in the middle of writing data to a file, [funcref boost::process::terminate terminate] can leave that data in an undefined state. + +[endsect] + +[endsect] diff --git a/plugins/New_GPG/src/include/libs/process/doc/windows.qbk b/plugins/New_GPG/src/include/libs/process/doc/windows.qbk new file mode 100644 index 0000000000..0f74d9ccea --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/doc/windows.qbk @@ -0,0 +1,33 @@ +[section Windows specifics] + +[section Setting wShowWindow] + +Use the initializer [classref boost::process::initializers::show_window show_window] to set the member variable `wShowWindow` in [@http://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx `STARTUPINFO`]: + +[import ../example/windows.cpp] +[show_window] + +[endsect] + +[section Unicode] + +Boost.Process supports Unicode on Windows. If the macro [macroref UNICODE] or `_UNICODE` is defined, the Unicode version of [@http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx `CreateProcess`] is used: + +[import ../example/windows_unicode.cpp] +[unicode] + +[endsect] + +[section Arbitrary extensions] + +On Windows [classref boost::process::executor executor] calls [@http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx `CreateProcess`] to start a program. Boost.Process provides three generic initializers to run any code before `CreateProcess` is called, afterwards if `CreateProcess` failed and afterwards if `CreateProcess` succeeded: [funcref boost::process::initializers::on_CreateProcess_setup on_CreateProcess_setup], [funcref boost::process::initializers::on_CreateProcess_error on_CreateProcess_error] and [funcref boost::process::initializers::on_CreateProcess_success on_CreateProcess_success]. These initializers can be used to arbitrarily extend Boost.Process: + +[create_process] + +The example sets the member variable `dwFlags` in `STARTUPINFO` to *STARTF_RUNFULLSCREEN*. If `CreateProcess` fails, the system error is written to the standard error stream. + +[note Boost.Process guarantees to call initializers in the order they are passed to `execute`. The order is important if several initializers try to set the same member variables in the `executor`. The initializers provided by Boost.Process have been designed to work correctly no matter which order they are used in. You only have to be careful if you use the generic initializers [funcref boost::process::initializers::on_CreateProcess_setup on_CreateProcess_setup], [funcref boost::process::initializers::on_CreateProcess_error on_CreateProcess_error] and [funcref boost::process::initializers::on_CreateProcess_success on_CreateProcess_success].] + +[endsect] + +[endsect] diff --git a/plugins/New_GPG/src/include/libs/process/example/Jamfile.jam b/plugins/New_GPG/src/include/libs/process/example/Jamfile.jam new file mode 100644 index 0000000000..69b75bc527 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/Jamfile.jam @@ -0,0 +1,33 @@ +# Copyright (c) 2006, 2007 Julio M. Merino Vidal +# Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +# Copyright (c) 2009 Boris Schaeling +# Copyright (c) 2010 Felipe Tanus, Boris Schaeling +# Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +project : requirements + <include>../../.. + <source>/boost//headers + <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS + <target-os>windows:<define>WIN32_LEAN_AND_MEAN +; + +import testing ; + +compile args.cpp ; +compile async_io.cpp ; +compile cleanup.cpp ; +compile cmd_line.cpp ; +compile env.cpp ; +compile error_handling.cpp ; +compile execute.cpp ; +compile intro.cpp ; +compile posix.cpp : <build>no <target-os>linux:<build>yes ; +compile streams.cpp ; +compile sync_io.cpp ; +compile terminate.cpp ; +compile wait.cpp ; +compile windows.cpp : <build>no <target-os>windows:<build>yes ; +compile work_dir.cpp ; diff --git a/plugins/New_GPG/src/include/libs/process/example/args.cpp b/plugins/New_GPG/src/include/libs/process/example/args.cpp new file mode 100644 index 0000000000..1d83cbf4c1 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/args.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#include <vector> +#include <string> + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ +//[args + std::vector<std::string> args; + args.push_back("test.exe"); + args.push_back("--foo"); + args.push_back("/bar"); + + execute(set_args(args)); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/async_io.cpp b/plugins/New_GPG/src/include/libs/process/example/async_io.cpp new file mode 100644 index 0000000000..5253886918 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/async_io.cpp @@ -0,0 +1,65 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/asio.hpp> +#include <boost/array.hpp> +#include <string> +#if defined(BOOST_WINDOWS_API) +# include <Windows.h> +#endif + +using namespace boost::process; +using namespace boost::process::initializers; +using namespace boost::iostreams; + +boost::process::pipe create_async_pipe() +{ +#if defined(BOOST_WINDOWS_API) + std::string name = "\\\\.\\pipe\\boost_process_async_io"; + HANDLE handle1 = ::CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND | + FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, NULL); + HANDLE handle2 = ::CreateFileA(name.c_str(), GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + return make_pipe(handle1, handle2); +#elif defined(BOOST_POSIX_API) + return create_pipe(); +#endif +} + +int main() +{ +//[async_io + boost::process::pipe p = create_async_pipe(); + + file_descriptor_sink sink(p.sink, close_handle); + execute( + run_exe("test.exe"), + bind_stdout(sink) + ); + + file_descriptor_source source(p.source, close_handle); + +#if defined(BOOST_WINDOWS_API) + typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) + typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + + boost::asio::io_service io_service; + pipe_end pend(io_service, p.source); + + boost::array<char, 4096> buffer; + boost::asio::async_read(pend, boost::asio::buffer(buffer), + [](const boost::system::error_code&, std::size_t){}); + + io_service.run(); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/cleanup.cpp b/plugins/New_GPG/src/include/libs/process/example/cleanup.cpp new file mode 100644 index 0000000000..6d40eee032 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/cleanup.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#if defined(BOOST_POSIX_API) +# include <signal.h> +#endif + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ +//[cleanup + child c = execute(run_exe("test.exe")); + wait_for_exit(c); +//] + +//[cleanup_posix +#if defined(BOOST_POSIX_API) + signal(SIGCHLD, SIG_IGN); +#endif + execute(run_exe("test.exe")); +//] + +//[cleanup_windows + { + child c = execute(run_exe("test.exe")); + } +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/cmd_line.cpp b/plugins/New_GPG/src/include/libs/process/example/cmd_line.cpp new file mode 100644 index 0000000000..99b581ab7c --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/cmd_line.cpp @@ -0,0 +1,23 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ +//[cmd_line + execute( + run_exe("test.exe"), + set_cmd_line("test --foo /bar") + ); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/env.cpp b/plugins/New_GPG/src/include/libs/process/example/env.cpp new file mode 100644 index 0000000000..d890af98fb --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/env.cpp @@ -0,0 +1,23 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ +//[inherit_env + execute( + run_exe("test.exe"), + inherit_env() + ); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/error_handling.cpp b/plugins/New_GPG/src/include/libs/process/example/error_handling.cpp new file mode 100644 index 0000000000..4f7a261c33 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/error_handling.cpp @@ -0,0 +1,32 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ +//[set_on_error + boost::system::error_code ec; + execute( + run_exe("test.exe"), + set_on_error(ec) + ); +//] + +//[throw_on_error + execute( + run_exe("test.exe"), + throw_on_error() + ); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/execute.cpp b/plugins/New_GPG/src/include/libs/process/example/execute.cpp new file mode 100644 index 0000000000..e8bd5947cc --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/execute.cpp @@ -0,0 +1,25 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ +//[execute + execute(run_exe("test.exe")); +//] + +//[execute_path + boost::filesystem::path exe = "../test.exe"; + execute(run_exe(exe)); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/intro.cpp b/plugins/New_GPG/src/include/libs/process/example/intro.cpp new file mode 100644 index 0000000000..ce9b1a41da --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/intro.cpp @@ -0,0 +1,20 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +//[intro +#include <boost/process.hpp> + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ + execute(run_exe("test.exe")); +} +//] diff --git a/plugins/New_GPG/src/include/libs/process/example/posix.cpp b/plugins/New_GPG/src/include/libs/process/example/posix.cpp new file mode 100644 index 0000000000..21da84f4a9 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/posix.cpp @@ -0,0 +1,68 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/assign/list_of.hpp> +#include <iostream> +#include <fstream> +#include <unistd.h> +#include <errno.h> + +using namespace boost::process; +using namespace boost::process::initializers; +using namespace boost::iostreams; + +int main() +{ +//[bind_fd + file_descriptor_sink sink("output.txt"); + execute( + run_exe("test"), + bind_fd(4, sink) + ); +//] + +//[close_fd + execute( + run_exe("test"), + close_fd(STDIN_FILENO) + ); +//] + +//[close_fds + execute( + run_exe("test"), + close_fds(boost::assign::list_of(STDIN_FILENO)(4)) + ); +//] + +//[close_fds_if + execute( + run_exe("test"), + close_fds_if([](int fd){ return fd == STDIN_FILENO; }) + ); +//] + +//[fork_execve + const char *env[2] = { 0 }; + env[0] = "LANG=de"; + execute( + run_exe("test"), + on_fork_setup([env](executor &e) + { e.env = const_cast<char**>(env); }), + on_fork_error([](executor&) + { std::cerr << errno << std::endl; }), + on_exec_setup([](executor&) + { chroot("/new/root/directory/"); }), + on_exec_error([](executor&) + { std::ofstream ofs("log.txt"); if (ofs) ofs << errno; }) + ); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/streams.cpp b/plugins/New_GPG/src/include/libs/process/example/streams.cpp new file mode 100644 index 0000000000..3319820055 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/streams.cpp @@ -0,0 +1,36 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/assign/list_of.hpp> + +using namespace boost::process; +using namespace boost::process::initializers; +using namespace boost::iostreams; + +int main() +{ +//[stdout + file_descriptor_sink sink("stdout.txt"); + execute( + run_exe("test.exe"), + bind_stdout(sink) + ); +//] + +//[close_in_err + execute( + run_exe("test.exe"), + bind_stdout(sink), + close_stdin(), + close_stderr() + ); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/sync_io.cpp b/plugins/New_GPG/src/include/libs/process/example/sync_io.cpp new file mode 100644 index 0000000000..cc36c40d14 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/sync_io.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <string> + +using namespace boost::process; +using namespace boost::process::initializers; +using namespace boost::iostreams; + +int main() +{ +//[sync_io + boost::process::pipe p = create_pipe(); + + file_descriptor_sink sink(p.sink, close_handle); + execute( + run_exe("test.exe"), + bind_stdout(sink) + ); + + file_descriptor_source source(p.source, close_handle); + stream<file_descriptor_source> is(source); + std::string s; + std::getline(is, s); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/terminate.cpp b/plugins/New_GPG/src/include/libs/process/example/terminate.cpp new file mode 100644 index 0000000000..7518e5cb80 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/terminate.cpp @@ -0,0 +1,21 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ +//[terminate + child c = execute(run_exe("test.exe")); + terminate(c); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/wait.cpp b/plugins/New_GPG/src/include/libs/process/example/wait.cpp new file mode 100644 index 0000000000..c47edac0e3 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/wait.cpp @@ -0,0 +1,62 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#include <boost/asio.hpp> +#if defined(BOOST_WINDOWS_API) +# include <Windows.h> +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <errno.h> +#endif + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ + { +//[sync + child c = execute(run_exe("test.exe")); + auto exit_code = wait_for_exit(c); +//] + } + + { +//[async + boost::asio::io_service io_service; + +#if defined(BOOST_POSIX_API) + int status; + boost::asio::signal_set set(io_service, SIGCHLD); + set.async_wait( + [&status](const boost::system::error_code&, int) { ::wait(&status); } + ); +#endif + + child c = execute( + run_exe("test.exe") +#if defined(BOOST_POSIX_API) + , notify_io_service(io_service) +#endif + ); + +#if defined(BOOST_WINDOWS_API) + DWORD exit_code; + boost::asio::windows::object_handle handle(io_service, c.process_handle()); + handle.async_wait( + [&handle, &exit_code](const boost::system::error_code&) + { ::GetExitCodeProcess(handle.native(), &exit_code); } + ); +#endif + + io_service.run(); +//] + } +} diff --git a/plugins/New_GPG/src/include/libs/process/example/windows.cpp b/plugins/New_GPG/src/include/libs/process/example/windows.cpp new file mode 100644 index 0000000000..e2b2955b1e --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/windows.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#include <iostream> +#include <Windows.h> + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ +//[show_window + execute( + run_exe("test.exe"), + show_window(SW_HIDE) + ); +//] + +//[create_process + execute( + run_exe("test.exe"), + on_CreateProcess_setup([](executor &e) + { e.startup_info.dwFlags = STARTF_RUNFULLSCREEN; }), + on_CreateProcess_error([](executor&) + { std::cerr << GetLastError() << std::endl; }) + ); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/example/windows_unicode.cpp b/plugins/New_GPG/src/include/libs/process/example/windows_unicode.cpp new file mode 100644 index 0000000000..1585cb2870 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/windows_unicode.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +//[unicode +#define UNICODE +#include <boost/process.hpp> +#include <boost/filesystem.hpp> + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ + boost::filesystem::path p = L"C:\\"; + execute( + run_exe(L"test.exe"), + set_cmd_line(L"test --help"), + start_in_dir(p) + ); +} +//] diff --git a/plugins/New_GPG/src/include/libs/process/example/work_dir.cpp b/plugins/New_GPG/src/include/libs/process/example/work_dir.cpp new file mode 100644 index 0000000000..cb17fd8d17 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/example/work_dir.cpp @@ -0,0 +1,32 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/process.hpp> +#include <boost/filesystem.hpp> + +using namespace boost::process; +using namespace boost::process::initializers; + +int main() +{ +//[work_dir + execute( + run_exe("test.exe"), + start_in_dir("../foo") + ); +//] + +//[work_dir_abs + boost::filesystem::path exe = "test.exe"; + execute( + run_exe(boost::filesystem::absolute(exe)), + start_in_dir("../foo") + ); +//] +} diff --git a/plugins/New_GPG/src/include/libs/process/test/Jamfile.jam b/plugins/New_GPG/src/include/libs/process/test/Jamfile.jam new file mode 100644 index 0000000000..ff0829c1bd --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/Jamfile.jam @@ -0,0 +1,57 @@ +# Copyright (c) 2006, 2007 Julio M. Merino Vidal +# Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +# Copyright (c) 2009 Boris Schaeling +# Copyright (c) 2010 Felipe Tanus, Boris Schaeling +# Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +project : requirements + <include>../../.. + <source>/boost//headers + <source>/boost//system + <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS + <target-os>windows:<define>WIN32_LEAN_AND_MEAN + <target-os>linux:<linkflags>-lpthread +; + +searched-lib shell32 ; + +import testing ; + +exe sparring_partner : sparring_partner.cpp /boost//program_options /boost//filesystem /boost//iostreams ; + +run bind_stderr.cpp /boost//iostreams : : sparring_partner ; +run bind_stdin.cpp /boost//iostreams : : sparring_partner ; +run bind_stdin_stdout.cpp /boost//iostreams : : sparring_partner ; +run bind_stdout.cpp /boost//iostreams : : sparring_partner ; +run bind_stdout_stderr.cpp /boost//iostreams : : sparring_partner ; +run close_stderr.cpp /boost//iostreams : : sparring_partner ; +run close_stdin.cpp /boost//iostreams : : sparring_partner ; +run close_stdout.cpp /boost//iostreams : : sparring_partner ; +run exit_code.cpp /boost//iostreams /boost//program_options : : sparring_partner ; +run extensions.cpp : : sparring_partner ; +run inherit_env.cpp /boost//iostreams /boost//program_options : : sparring_partner ; +run posix_specific.cpp /boost//iostreams : : sparring_partner : <build>no <target-os>linux:<build>yes ; +run run_exe.cpp : : sparring_partner ; +run run_exe_path.cpp /boost//filesystem : : sparring_partner ; +run run_exe_wstring.cpp /boost//filesystem : : sparring_partner : <build>no <target-os>windows:<build>yes ; +run search_path.cpp /boost//filesystem : : : <target-os>windows:<source>shell32 ; +run search_path_wstring.cpp /boost//filesystem shell32 : : : <build>no <target-os>windows:<build>yes ; +run set_args.cpp /boost//iostreams : : sparring_partner ; +run set_args_wstring.cpp /boost//iostreams /boost//filesystem : : sparring_partner : <build>no <target-os>windows:<build>yes ; +run set_cmd_line.cpp /boost//iostreams : : sparring_partner ; +run set_cmd_line_wstring.cpp /boost//iostreams /boost//filesystem : : sparring_partner : <build>no <target-os>windows:<build>yes ; +run set_env.cpp /boost//iostreams : : sparring_partner ; +run set_env_wstring.cpp /boost//iostreams /boost//filesystem : : sparring_partner : <build>no <target-os>windows:<build>yes ; +run set_on_error.cpp : : sparring_partner ; +run shell_path.cpp /boost//filesystem ; +run shell_path_wstring.cpp /boost//filesystem : : : <build>no <target-os>windows:<build>yes ; +run show_window.cpp /boost//iostreams : : sparring_partner : <build>no <target-os>windows:<build>yes ; +run start_in_dir.cpp /boost//iostreams /boost//filesystem : : sparring_partner ; +run start_in_dir_wstring.cpp /boost//iostreams /boost//filesystem : : sparring_partner : <build>no <target-os>windows:<build>yes ; +run terminate.cpp : : sparring_partner ; +run throw_on_error.cpp : : sparring_partner ; +run wait.cpp : : sparring_partner ; +run windows_specific.cpp /boost//iostreams : : sparring_partner : <build>no <target-os>windows:<build>yes ; diff --git a/plugins/New_GPG/src/include/libs/process/test/bind_stderr.cpp b/plugins/New_GPG/src/include/libs/process/test/bind_stderr.cpp new file mode 100644 index 0000000000..2a60a47171 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/bind_stderr.cpp @@ -0,0 +1,144 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <string> +#include <istream> +#include <cstdlib> +#if defined(BOOST_WINDOWS_API) +# include <Windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <unistd.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; +namespace bio = boost::iostreams; + +BOOST_AUTO_TEST_CASE(sync_io) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p = bp::create_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --echo-stderr hello"), + bpi::bind_stderr(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is(source); + + std::string s; + is >> s; + BOOST_CHECK_EQUAL(s, "hello"); +} + +bp::pipe create_async_pipe() +{ +#if defined(BOOST_WINDOWS_API) + std::string name = "\\\\.\\pipe\\boost_process_test_bind_stderr"; + HANDLE handle1 = CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND | + FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, NULL); + HANDLE handle2 = CreateFileA(name.c_str(), GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + return bp::make_pipe(handle1, handle2); +#elif defined(BOOST_POSIX_API) + return bp::create_pipe(); +#endif +} + +struct read_handler +{ + boost::asio::streambuf &buffer_; + + read_handler(boost::asio::streambuf &buffer) : buffer_(buffer) {} + + void operator()(const boost::system::error_code &ec, std::size_t size) + { + BOOST_REQUIRE(!ec); + std::istream is(&buffer_); + std::string line; + std::getline(is, line); + BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); + } +}; + +BOOST_AUTO_TEST_CASE(async_io) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p = create_async_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --echo-stderr abc"), + bpi::bind_stderr(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + boost::asio::io_service io_service; + pipe_end pend(io_service, p.source); + + boost::asio::streambuf buffer; + boost::asio::async_read_until(pend, buffer, '\n', + read_handler(buffer)); + + io_service.run(); +} + +BOOST_AUTO_TEST_CASE(nul) +{ + using boost::unit_test::framework::master_test_suite; + +#if defined(BOOST_WINDOWS_API) + bio::file_descriptor_sink sink("NUL"); +#elif defined(BOOST_POSIX_API) + bio::file_descriptor_sink sink("/dev/null"); +#endif + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --is-nul-stderr"), + bpi::bind_stderr(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + int exit_code = bp::wait_for_exit(c); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, WEXITSTATUS(exit_code)); +#endif +} diff --git a/plugins/New_GPG/src/include/libs/process/test/bind_stdin.cpp b/plugins/New_GPG/src/include/libs/process/test/bind_stdin.cpp new file mode 100644 index 0000000000..83f547dda9 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/bind_stdin.cpp @@ -0,0 +1,165 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/asio.hpp> +#include <string> +#include <cstdlib> +#if defined(BOOST_WINDOWS_API) +# include <Windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <unistd.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; +namespace bio = boost::iostreams; + +BOOST_AUTO_TEST_CASE(sync_io) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p1 = bp::create_pipe(); + bp::pipe p2 = bp::create_pipe(); + + { + bio::file_descriptor_source source1(p1.source, bio::close_handle); + bio::file_descriptor_sink sink2(p2.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --prefix abc"), + bpi::bind_stdin(source1), + bpi::bind_stdout(sink2), +#if defined(BOOST_POSIX_API) + bpi::close_fd(p1.sink), +#endif + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_sink sink1(p1.sink, bio::close_handle); + bio::stream<bio::file_descriptor_sink> os(sink1); + + os << "hello" << std::endl; + + bio::file_descriptor_source source2(p2.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is(source2); + + std::string s; + is >> s; + BOOST_CHECK_EQUAL(s, "abchello"); + os << 123 << std::endl; + is >> s; + BOOST_CHECK_EQUAL(s, "abc123"); + os << 3.1415 << std::endl; + is >> s; + BOOST_CHECK_EQUAL(s, "abc3.1415"); +} + +bp::pipe create_async_pipe() +{ +#if defined(BOOST_WINDOWS_API) + std::string name = "\\\\.\\pipe\\boost_process_test_bind_stdin"; + HANDLE handle1 = CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND, + 0, 1, 8192, 8192, 0, NULL); + HANDLE handle2 = CreateFileA(name.c_str(), GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + return bp::make_pipe(handle1, handle2); +#elif defined(BOOST_POSIX_API) + return bp::create_pipe(); +#endif +} + +struct write_handler +{ + bio::stream<bio::file_descriptor_source> &is_; + + write_handler(bio::stream<bio::file_descriptor_source> &is) : is_(is) {} + + void operator()(const boost::system::error_code &ec, std::size_t size) + { + BOOST_REQUIRE(!ec); + BOOST_REQUIRE_EQUAL(6u, size); + std::string s; + is_ >> s; + BOOST_CHECK_EQUAL(s, "abchello"); + } +}; + +BOOST_AUTO_TEST_CASE(async_io) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p1 = create_async_pipe(); + bp::pipe p2 = bp::create_pipe(); + + { + bio::file_descriptor_source source1(p1.source, bio::close_handle); + bio::file_descriptor_sink sink2(p2.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --prefix-once abc"), + bpi::bind_stdin(source1), + bpi::bind_stdout(sink2), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source2(p2.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is(source2); + + boost::asio::io_service io_service; + pipe_end pend(io_service, p1.sink); + + std::string s = "hello\n"; + boost::asio::async_write(pend, boost::asio::buffer(s), + write_handler(is)); + + io_service.run(); +} + +BOOST_AUTO_TEST_CASE(nul) +{ + using boost::unit_test::framework::master_test_suite; + +#if defined(BOOST_WINDOWS_API) + bio::file_descriptor_source source("NUL"); +#elif defined(BOOST_POSIX_API) + bio::file_descriptor_source source("/dev/null"); +#endif + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --is-nul-stdin"), + bpi::bind_stdin(source), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + int exit_code = bp::wait_for_exit(c); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, WEXITSTATUS(exit_code)); +#endif +} diff --git a/plugins/New_GPG/src/include/libs/process/test/bind_stdin_stdout.cpp b/plugins/New_GPG/src/include/libs/process/test/bind_stdin_stdout.cpp new file mode 100644 index 0000000000..adb83eef22 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/bind_stdin_stdout.cpp @@ -0,0 +1,62 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <string> +#include <iostream> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; +namespace bio = boost::iostreams; + +BOOST_AUTO_TEST_CASE(sync_io) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p1 = bp::create_pipe(); + bp::pipe p2 = bp::create_pipe(); + + { + bio::file_descriptor_source source(p1.source, bio::close_handle); + bio::file_descriptor_sink sink(p2.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --stdin-to-stdout"), + bpi::bind_stdin(source), + bpi::bind_stdout(sink), +#if defined(BOOST_POSIX_API) + bpi::close_fd(p1.sink), +#endif + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_sink sink(p1.sink, bio::close_handle); + bio::stream<bio::file_descriptor_sink> os(sink); + + bio::file_descriptor_source source(p2.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is(source); + + std::string s = "abcdefghi j"; + for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) + { + os << *it << std::flush; + char c; + is >> std::noskipws >> c; + BOOST_CHECK_EQUAL(*it, c); + } +} diff --git a/plugins/New_GPG/src/include/libs/process/test/bind_stdout.cpp b/plugins/New_GPG/src/include/libs/process/test/bind_stdout.cpp new file mode 100644 index 0000000000..9b06107ff9 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/bind_stdout.cpp @@ -0,0 +1,144 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <string> +#include <istream> +#include <cstdlib> +#if defined(BOOST_WINDOWS_API) +# include <Windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <unistd.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; +namespace bio = boost::iostreams; + +BOOST_AUTO_TEST_CASE(sync_io) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p = bp::create_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --echo-stdout hello"), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is(source); + + std::string s; + is >> s; + BOOST_CHECK_EQUAL(s, "hello"); +} + +bp::pipe create_async_pipe() +{ +#if defined(BOOST_WINDOWS_API) + std::string name = "\\\\.\\pipe\\boost_process_test_bind_stdout"; + HANDLE handle1 = CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND | + FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, NULL); + HANDLE handle2 = CreateFileA(name.c_str(), GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + return bp::make_pipe(handle1, handle2); +#elif defined(BOOST_POSIX_API) + return bp::create_pipe(); +#endif +} + +struct read_handler +{ + boost::asio::streambuf &buffer_; + + read_handler(boost::asio::streambuf &buffer) : buffer_(buffer) {} + + void operator()(const boost::system::error_code &ec, std::size_t size) + { + BOOST_REQUIRE(!ec); + std::istream is(&buffer_); + std::string line; + std::getline(is, line); + BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); + } +}; + +BOOST_AUTO_TEST_CASE(async_io) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p = create_async_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --echo-stdout abc"), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + boost::asio::io_service io_service; + pipe_end pend(io_service, p.source); + + boost::asio::streambuf buffer; + boost::asio::async_read_until(pend, buffer, '\n', + read_handler(buffer)); + + io_service.run(); +} + +BOOST_AUTO_TEST_CASE(nul) +{ + using boost::unit_test::framework::master_test_suite; + +#if defined(BOOST_WINDOWS_API) + bio::file_descriptor_sink sink("NUL"); +#elif defined(BOOST_POSIX_API) + bio::file_descriptor_sink sink("/dev/null"); +#endif + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --is-nul-stdout"), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + int exit_code = bp::wait_for_exit(c); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, WEXITSTATUS(exit_code)); +#endif +} diff --git a/plugins/New_GPG/src/include/libs/process/test/bind_stdout_stderr.cpp b/plugins/New_GPG/src/include/libs/process/test/bind_stdout_stderr.cpp new file mode 100644 index 0000000000..90f90da858 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/bind_stdout_stderr.cpp @@ -0,0 +1,131 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/asio.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <string> +#include <istream> +#if defined(BOOST_WINDOWS_API) +# include <Windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; +namespace bio = boost::iostreams; + +BOOST_AUTO_TEST_CASE(sync_io) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p1 = bp::create_pipe(); + bp::pipe p2 = bp::create_pipe(); + + { + bio::file_descriptor_sink sink1(p1.sink, bio::close_handle); + bio::file_descriptor_sink sink2(p2.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --echo-stdout-stderr hello"), + bpi::bind_stdout(sink1), + bpi::bind_stderr(sink2), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source1(p1.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is1(source1); + + std::string s; + is1 >> s; + BOOST_CHECK_EQUAL(s, "hello"); + + bio::file_descriptor_source source2(p2.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is2(source2); + + is2 >> s; + BOOST_CHECK_EQUAL(s, "hello"); +} + +bp::pipe create_async_pipe(const std::string &s) +{ +#if defined(BOOST_WINDOWS_API) + std::string name = "\\\\.\\pipe\\boost_process_test_bind_stdout_stderr" + s; + HANDLE handle1 = CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND | + FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, NULL); + HANDLE handle2 = CreateFileA(name.c_str(), GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + return bp::make_pipe(handle1, handle2); +#elif defined(BOOST_POSIX_API) + return bp::create_pipe(); +#endif +} + +struct read_handler +{ + boost::asio::streambuf &buffer_; + + read_handler(boost::asio::streambuf &buffer) : buffer_(buffer) {} + + void operator()(const boost::system::error_code &ec, std::size_t size) + { + BOOST_REQUIRE(!ec); + std::istream is(&buffer_); + std::string line; + std::getline(is, line); + BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); + } +}; + +BOOST_AUTO_TEST_CASE(async_io) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p1 = create_async_pipe("1"); + bp::pipe p2 = create_async_pipe("2"); + + { + bio::file_descriptor_sink sink1(p1.sink, bio::close_handle); + bio::file_descriptor_sink sink2(p2.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --echo-stdout-stderr abc"), + bpi::bind_stdout(sink1), + bpi::bind_stderr(sink2), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + boost::asio::io_service io_service; + pipe_end pend1(io_service, p1.source); + pipe_end pend2(io_service, p2.source); + + boost::asio::streambuf buffer1; + boost::asio::async_read_until(pend1, buffer1, '\n', + read_handler(buffer1)); + + boost::asio::streambuf buffer2; + boost::asio::async_read_until(pend2, buffer2, '\n', + read_handler(buffer2)); + + io_service.run(); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/close_stderr.cpp b/plugins/New_GPG/src/include/libs/process/test/close_stderr.cpp new file mode 100644 index 0000000000..e82f9df82c --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/close_stderr.cpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <cstdlib> +#if defined(BOOST_POSIX_API) +# include <sys/wait.h> +#endif + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(closed) +{ + using boost::unit_test::framework::master_test_suite; + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --is-closed-stderr"), + bpi::close_stderr(), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + int exit_code = bp::wait_for_exit(c); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, WEXITSTATUS(exit_code)); +#endif +} diff --git a/plugins/New_GPG/src/include/libs/process/test/close_stdin.cpp b/plugins/New_GPG/src/include/libs/process/test/close_stdin.cpp new file mode 100644 index 0000000000..2290652ae8 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/close_stdin.cpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <cstdlib> +#if defined(BOOST_POSIX_API) +# include <sys/wait.h> +#endif + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(closed) +{ + using boost::unit_test::framework::master_test_suite; + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --is-closed-stdin"), + bpi::close_stdin(), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + int exit_code = bp::wait_for_exit(c); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, WEXITSTATUS(exit_code)); +#endif +} diff --git a/plugins/New_GPG/src/include/libs/process/test/close_stdout.cpp b/plugins/New_GPG/src/include/libs/process/test/close_stdout.cpp new file mode 100644 index 0000000000..4338a8f1ed --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/close_stdout.cpp @@ -0,0 +1,42 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <cstdlib> +#if defined(BOOST_POSIX_API) +# include <sys/wait.h> +#endif + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(closed) +{ + using boost::unit_test::framework::master_test_suite; + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --is-closed-stdout"), + bpi::close_stdout(), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + int exit_code = bp::wait_for_exit(c); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(EXIT_SUCCESS, WEXITSTATUS(exit_code)); +#endif +} diff --git a/plugins/New_GPG/src/include/libs/process/test/exit_code.cpp b/plugins/New_GPG/src/include/libs/process/test/exit_code.cpp new file mode 100644 index 0000000000..4fb946dcae --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/exit_code.cpp @@ -0,0 +1,106 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/asio.hpp> +#if defined(BOOST_WINDOWS_API) +# include <Windows.h> +typedef boost::asio::windows::stream_handle pipe_end; +#elif defined(BOOST_POSIX_API) +# include <sys/wait.h> +# include <signal.h> +typedef boost::asio::posix::stream_descriptor pipe_end; +#endif + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(sync_wait) +{ + using boost::unit_test::framework::master_test_suite; + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --exit-code 123"), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + int exit_code = bp::wait_for_exit(c); +#if defined(BOOST_WINDOWS_API) + BOOST_CHECK_EQUAL(123, exit_code); +#elif defined(BOOST_POSIX_API) + BOOST_CHECK_EQUAL(123, WEXITSTATUS(exit_code)); +#endif +} + +#if defined(BOOST_WINDOWS_API) +struct wait_handler +{ + HANDLE handle_; + + wait_handler(HANDLE handle) : handle_(handle) {} + + void operator()(const boost::system::error_code &ec) + { + BOOST_REQUIRE(!ec); + DWORD exit_code; + BOOST_REQUIRE(GetExitCodeProcess(handle_, &exit_code)); + BOOST_CHECK_EQUAL(123, exit_code); + } +}; +#elif defined(BOOST_POSIX_API) +struct wait_handler +{ + void operator()(const boost::system::error_code &ec, int signal) + { + BOOST_REQUIRE(!ec); + BOOST_REQUIRE_EQUAL(SIGCHLD, signal); + int status; + wait(&status); + BOOST_CHECK_EQUAL(123, WEXITSTATUS(status)); + } +}; +#endif + +BOOST_AUTO_TEST_CASE(async_wait) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::asio::io_service io_service; + +#if defined(BOOST_POSIX_API) + signal_set set(io_service, SIGCHLD); + set.async_wait(wait_handler()); +#endif + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --exit-code 123"), + bpi::set_on_error(ec) +#if defined(BOOST_POSIX_API) + , bpi::notify_io_service(io_service) +#endif + ); + BOOST_REQUIRE(!ec); + +#if defined(BOOST_WINDOWS_API) + windows::object_handle handle(io_service, c.process_handle()); + handle.async_wait(wait_handler(handle.native())); +#endif + + io_service.run(); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/extensions.cpp b/plugins/New_GPG/src/include/libs/process/test/extensions.cpp new file mode 100644 index 0000000000..6e53352eda --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/extensions.cpp @@ -0,0 +1,65 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/bind.hpp> +#include <boost/ref.hpp> +#if defined(BOOST_WINDOWS_API) +# include <Windows.h> +#elif defined(BOOST_POSIX_API) +# include <errno.h> +#endif + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; +namespace bio = boost::iostreams; + +void run_exe(const std::string &exe, bp::executor &e) +{ + e.exe = exe.c_str(); +} + +void set_on_error(boost::system::error_code &ec, bp::executor&) +{ + using namespace boost::system; +#if defined(BOOST_WINDOWS_API) + ec = error_code(::GetLastError(), system_category()); +#elif defined(BOOST_POSIX_API) + ec = error_code(errno, system_category()); +#endif +} + +BOOST_AUTO_TEST_CASE(extensions) +{ + using boost::unit_test::framework::master_test_suite; + + std::string exe = master_test_suite().argv[1]; + + boost::system::error_code ec; + bp::execute( +#if defined(BOOST_WINDOWS_API) + bpi::on_CreateProcess_setup( + boost::bind(run_exe, exe, _1)), + bpi::set_cmd_line("test"), + bpi::on_CreateProcess_error( + boost::bind(set_on_error, boost::ref(ec), _1)) +#elif defined(BOOST_POSIX_API) + bpi::on_exec_setup( + boost::bind(run_exe, exe, _1)), + bpi::set_cmd_line("test"), + bpi::on_exec_error( + boost::bind(set_on_error, boost::ref(ec), _1)) +#endif + ); + BOOST_CHECK(!ec); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/inherit_env.cpp b/plugins/New_GPG/src/include/libs/process/test/inherit_env.cpp new file mode 100644 index 0000000000..591948d0e8 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/inherit_env.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/filter/newline.hpp> +#include <boost/program_options/environment_iterator.hpp> +#include <string> +#include <stdlib.h> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(inherit_env) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + + boost::environment_iterator it(environ); + BOOST_REQUIRE(it != boost::environment_iterator()); + + bp::pipe p = bp::create_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --query " + it->first), + bpi::inherit_env(), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::filtering_istream is; + is.push(bio::newline_filter(bio::newline::posix)); + is.push(source); + + std::string s; + std::getline(is, s); + BOOST_CHECK_EQUAL(s, "defined"); + std::getline(is, s); + BOOST_CHECK_EQUAL(s, it->second); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/posix_specific.cpp b/plugins/New_GPG/src/include/libs/process/test/posix_specific.cpp new file mode 100644 index 0000000000..6c4ce6378c --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/posix_specific.cpp @@ -0,0 +1,113 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/system/system_error.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <string> +#include <sys/wait.h> +#include <errno.h> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; +namespace bio = boost::iostreams; + +BOOST_AUTO_TEST_CASE(bind_fd) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p = bp::create_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --posix-echo-one 3 hello"), + bpi::bind_fd(3, sink), + bpi::set_on_error(ec) + ); + BOOST_CHECK(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is(source); + + std::string s; + is >> s; + BOOST_CHECK_EQUAL(s, "hello"); +} + +BOOST_AUTO_TEST_CASE(bind_fds) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p1 = bp::create_pipe(); + bp::pipe p2 = bp::create_pipe(); + + { + bio::file_descriptor_sink sink1(p1.sink, bio::close_handle); + bio::file_descriptor_sink sink2(p2.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --posix-echo-two 3 hello 99 bye"), + bpi::bind_fd(3, sink1), + bpi::bind_fd(99, sink2), + bpi::set_on_error(ec) + ); + BOOST_CHECK(!ec); + } + + bio::file_descriptor_source source1(p1.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is1(source1); + + std::string s1; + is1 >> s1; + BOOST_CHECK_EQUAL(s1, "hello"); + + bio::file_descriptor_source source2(p2.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is2(source2); + + std::string s2; + is2 >> s2; + BOOST_CHECK_EQUAL(s2, "bye"); +} + +BOOST_AUTO_TEST_CASE(execve_set_on_error) +{ + boost::system::error_code ec; + bp::execute( + bpi::run_exe("doesnt-exist"), + bpi::set_on_error(ec) + ); + BOOST_CHECK(ec); + BOOST_CHECK_EQUAL(ec.value(), ENOENT); +} + +BOOST_AUTO_TEST_CASE(execve_throw_on_error) +{ + try + { + bp::execute( + bpi::run_exe("doesnt-exist"), + bpi::throw_on_error() + ); + } + catch (boost::system::system_error &e) + { + BOOST_CHECK(e.code()); + BOOST_CHECK_EQUAL(e.code().value(), ENOENT); + } +} diff --git a/plugins/New_GPG/src/include/libs/process/test/run_exe.cpp b/plugins/New_GPG/src/include/libs/process/test/run_exe.cpp new file mode 100644 index 0000000000..7c6e6b2511 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/run_exe.cpp @@ -0,0 +1,39 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(run_exe_success) +{ + using boost::unit_test::framework::master_test_suite; + + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_on_error(ec) + ); + BOOST_CHECK(!ec); +} + +BOOST_AUTO_TEST_CASE(run_exe_error) +{ + boost::system::error_code ec; + bp::execute( + bpi::run_exe("doesnt-exist"), + bpi::set_on_error(ec) + ); + BOOST_CHECK(ec); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/run_exe_path.cpp b/plugins/New_GPG/src/include/libs/process/test/run_exe_path.cpp new file mode 100644 index 0000000000..f514935259 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/run_exe_path.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/filesystem.hpp> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(run_exe_success) +{ + using boost::unit_test::framework::master_test_suite; + + boost::filesystem::path exe = master_test_suite().argv[1]; + + boost::system::error_code ec; + bp::execute( + bpi::run_exe(exe), + bpi::set_on_error(ec) + ); + BOOST_CHECK(!ec); +} + +#if defined(BOOST_WINDOWS_API) +BOOST_AUTO_TEST_CASE(run_exe_error) +{ + boost::filesystem::path exe = "doesnt-exist"; + + boost::system::error_code ec; + bp::execute( + bpi::run_exe(exe), + bpi::set_on_error(ec) + ); + BOOST_CHECK(ec); +} +#endif diff --git a/plugins/New_GPG/src/include/libs/process/test/run_exe_wstring.cpp b/plugins/New_GPG/src/include/libs/process/test/run_exe_wstring.cpp new file mode 100644 index 0000000000..cc11bd00a5 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/run_exe_wstring.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define _UNICODE +#define UNICODE +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/filesystem.hpp> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(run_exe_success) +{ + using boost::unit_test::framework::master_test_suite; + + boost::filesystem::path p = master_test_suite().argv[1]; + + boost::system::error_code ec; + bp::execute( + bpi::run_exe(p.wstring()), + bpi::set_on_error(ec) + ); + BOOST_CHECK(!ec); +} + +#if defined(BOOST_WINDOWS_API) +BOOST_AUTO_TEST_CASE(run_exe_error) +{ + boost::system::error_code ec; + bp::execute( + bpi::run_exe(L"doesnt-exist"), + bpi::set_on_error(ec) + ); + BOOST_CHECK(ec); +} +#endif diff --git a/plugins/New_GPG/src/include/libs/process/test/search_path.cpp b/plugins/New_GPG/src/include/libs/process/test/search_path.cpp new file mode 100644 index 0000000000..2a155d8095 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/search_path.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <string> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(search) +{ +#if defined(BOOST_WINDOWS_API) + std::string filename = "cmd"; +#elif defined(BOOST_POSIX_API) + std::string filename = "ls"; +#endif + + BOOST_CHECK(!bp::search_path(filename).empty()); + +#if defined(BOOST_WINDOWS_API) + std::string path = "C:\\Windows;C:\\Windows\\System32"; +#elif defined(BOOST_POSIX_API) + std::string path = "/usr/local/bin:/usr/bin:/bin"; +#endif + + BOOST_CHECK(!bp::search_path(filename, path).empty()); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/search_path_wstring.cpp b/plugins/New_GPG/src/include/libs/process/test/search_path_wstring.cpp new file mode 100644 index 0000000000..3ba9c33279 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/search_path_wstring.cpp @@ -0,0 +1,25 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define _UNICODE +#define UNICODE +#define BOOST_TEST_MAIN +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <string> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(search) +{ + std::wstring filename = L"cmd"; + BOOST_CHECK(!bp::search_path(filename).empty()); + std::wstring path = L"C:\\Windows;C:\\Windows\\System32"; + BOOST_CHECK(!bp::search_path(filename, path).empty()); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/set_args.cpp b/plugins/New_GPG/src/include/libs/process/test/set_args.cpp new file mode 100644 index 0000000000..c3a453291d --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/set_args.cpp @@ -0,0 +1,83 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/filter/newline.hpp> +#include <boost/assign/list_of.hpp> +#include <string> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(set_args) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + namespace ba = boost::assign; + + bp::pipe p = bp::create_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_args(ba::list_of<std::string>("test") + ("--echo-argv")("a b")), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::filtering_istream is; + is.push(bio::newline_filter(bio::newline::posix)); + is.push(source); + + std::string s; + std::getline(is, s); + BOOST_CHECK_EQUAL(s, "\"test\" \"--echo-argv\" \"a b\""); +} + +BOOST_AUTO_TEST_CASE(set_args_without_run_exe) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + namespace ba = boost::assign; + + std::string exe = master_test_suite().argv[1]; + bp::pipe p = bp::create_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::set_args(ba::list_of<std::string>(exe)("--echo-argv")), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::filtering_istream is; + is.push(bio::newline_filter(bio::newline::posix)); + is.push(source); + + std::string s; + std::getline(is, s); + BOOST_CHECK_EQUAL(s, "\"" + exe + "\" \"--echo-argv\""); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/set_args_wstring.cpp b/plugins/New_GPG/src/include/libs/process/test/set_args_wstring.cpp new file mode 100644 index 0000000000..685b57f440 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/set_args_wstring.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define _UNICODE +#define UNICODE +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/filter/newline.hpp> +#include <boost/assign/list_of.hpp> +#include <string> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(set_args) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + namespace ba = boost::assign; + + bp::pipe p = bp::create_pipe(); + + { + boost::filesystem::path exe = master_test_suite().argv[1]; + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(exe), + bpi::set_args(ba::list_of<std::wstring>(L"test") + (L"--echo-argv")(L"a b")), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::filtering_istream is; + is.push(bio::newline_filter(bio::newline::posix)); + is.push(source); + + std::string s; + std::getline(is, s); + BOOST_CHECK_EQUAL(s, "\"test\" \"--echo-argv\" \"a b\""); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/set_cmd_line.cpp b/plugins/New_GPG/src/include/libs/process/test/set_cmd_line.cpp new file mode 100644 index 0000000000..128634a094 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/set_cmd_line.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/filter/newline.hpp> +#include <string> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(set_cmd_line) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + + bp::pipe p = bp::create_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --echo-argv \"a b\""), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::filtering_istream is; + is.push(bio::newline_filter(bio::newline::posix)); + is.push(source); + + std::string s; + std::getline(is, s); + BOOST_CHECK_EQUAL(s, "\"test\" \"--echo-argv\" \"a b\""); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/set_cmd_line_wstring.cpp b/plugins/New_GPG/src/include/libs/process/test/set_cmd_line_wstring.cpp new file mode 100644 index 0000000000..629f7e3bb8 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/set_cmd_line_wstring.cpp @@ -0,0 +1,54 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define _UNICODE +#define UNICODE +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/filesystem.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filter/newline.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <string> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(set_cmd_line) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + + bp::pipe p = bp::create_pipe(); + + { + boost::filesystem::path exe = master_test_suite().argv[1]; + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(exe), + bpi::set_cmd_line(L"test --echo-argv \"a b\""), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::filtering_istream is; + is.push(bio::newline_filter(bio::newline::posix)); + is.push(source); + + std::string s; + std::getline(is, s); + BOOST_CHECK_EQUAL(s, "\"test\" \"--echo-argv\" \"a b\""); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/set_env.cpp b/plugins/New_GPG/src/include/libs/process/test/set_env.cpp new file mode 100644 index 0000000000..d0eaf54e70 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/set_env.cpp @@ -0,0 +1,57 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/filter/newline.hpp> +#include <set> +#include <string> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(set_env) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + + std::set<std::string> env; + env.insert("FOO=BAR"); + + bp::pipe p = bp::create_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --query FOO"), + bpi::set_env(env), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::filtering_istream is; + is.push(bio::newline_filter(bio::newline::posix)); + is.push(source); + + std::string s; + std::getline(is, s); + BOOST_CHECK_EQUAL(s, "defined"); + std::getline(is, s); + BOOST_CHECK_EQUAL(s, "BAR"); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/set_env_wstring.cpp b/plugins/New_GPG/src/include/libs/process/test/set_env_wstring.cpp new file mode 100644 index 0000000000..bd884d33fe --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/set_env_wstring.cpp @@ -0,0 +1,61 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define _UNICODE +#define UNICODE +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/filesystem.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/filter/newline.hpp> +#include <set> +#include <string> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(set_env) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + + std::set<std::wstring> env; + env.insert(L"FOO=BAR"); + + bp::pipe p = bp::create_pipe(); + + { + boost::filesystem::path exe = master_test_suite().argv[1]; + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(exe), + bpi::set_cmd_line(L"test --query FOO"), + bpi::set_env(env), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::filtering_istream is; + is.push(bio::newline_filter(bio::newline::posix)); + is.push(source); + + std::string s; + std::getline(is, s); + BOOST_CHECK_EQUAL(s, "defined"); + std::getline(is, s); + BOOST_CHECK_EQUAL(s, "BAR"); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/set_on_error.cpp b/plugins/New_GPG/src/include/libs/process/test/set_on_error.cpp new file mode 100644 index 0000000000..3680dee364 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/set_on_error.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(set_on_error_test) +{ + boost::system::error_code ec; + bp::execute( + bpi::run_exe("doesnt-exist"), + bpi::set_on_error(ec) + ); + BOOST_CHECK(ec); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/shell_path.cpp b/plugins/New_GPG/src/include/libs/process/test/shell_path.cpp new file mode 100644 index 0000000000..31418b8116 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/shell_path.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/filesystem.hpp> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(shell_set_on_error) +{ + boost::system::error_code ec; + boost::filesystem::path p = bp::shell_path(ec); + BOOST_CHECK(!ec); + BOOST_CHECK(boost::filesystem::exists(p)); +} + +BOOST_AUTO_TEST_CASE(shell_throw_on_error) +{ + BOOST_CHECK_NO_THROW(bp::shell_path()); + BOOST_CHECK(boost::filesystem::exists(bp::shell_path())); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/shell_path_wstring.cpp b/plugins/New_GPG/src/include/libs/process/test/shell_path_wstring.cpp new file mode 100644 index 0000000000..72424b1404 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/shell_path_wstring.cpp @@ -0,0 +1,31 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define _UNICODE +#define UNICODE +#define BOOST_TEST_MAIN +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/filesystem.hpp> + +namespace bp = boost::process; + +BOOST_AUTO_TEST_CASE(shell_set_on_error) +{ + boost::system::error_code ec; + boost::filesystem::path p = bp::shell_path(ec); + BOOST_CHECK(!ec); + BOOST_CHECK(boost::filesystem::exists(p)); +} + +BOOST_AUTO_TEST_CASE(shell_throw_on_error) +{ + BOOST_CHECK_NO_THROW(bp::shell_path()); + BOOST_CHECK(boost::filesystem::exists(bp::shell_path())); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/show_window.cpp b/plugins/New_GPG/src/include/libs/process/test/show_window.cpp new file mode 100644 index 0000000000..3bba69995e --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/show_window.cpp @@ -0,0 +1,49 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <string> +#include <Windows.h> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(show_window) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + + bp::pipe p = bp::create_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --windows-print-showwindow"), + bpi::show_window(SW_SHOWNORMAL), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is(source); + + int i; + is >> i; + BOOST_CHECK_EQUAL(i, SW_SHOWNORMAL); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/sparring_partner.cpp b/plugins/New_GPG/src/include/libs/process/test/sparring_partner.cpp new file mode 100644 index 0000000000..abfaf128f3 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/sparring_partner.cpp @@ -0,0 +1,232 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/program_options.hpp> +#include <boost/filesystem.hpp> +#include <boost/algorithm/string/join.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/range/algorithm/transform.hpp> +#include <boost/range/algorithm_ext/push_back.hpp> +#include <boost/lambda/lambda.hpp> +#include <vector> +#include <string> +#include <iterator> +#include <iostream> +#include <cstdlib> +#if defined(BOOST_POSIX_API) +# include <boost/lexical_cast.hpp> +# include <boost/iostreams/device/file_descriptor.hpp> +# include <boost/iostreams/stream.hpp> +# include <unistd.h> +#elif defined(BOOST_WINDOWS_API) +# include <Windows.h> +#endif + +using namespace boost::program_options; + +int main(int argc, char *argv[]) +{ + options_description desc; + desc.add_options() + ("echo-stdout", value<std::string>()) + ("echo-stderr", value<std::string>()) + ("echo-stdout-stderr", value<std::string>()) + ("echo-argv", bool_switch()) + ("exit-code", value<int>()) + ("wait", value<int>()) + ("is-closed-stdin", bool_switch()) + ("is-closed-stdout", bool_switch()) + ("is-closed-stderr", bool_switch()) + ("is-nul-stdin", bool_switch()) + ("is-nul-stdout", bool_switch()) + ("is-nul-stderr", bool_switch()) + ("loop", bool_switch()) + ("prefix", value<std::string>()) + ("prefix-once", value<std::string>()) + ("pwd", bool_switch()) + ("query-env", value<std::string>()) + ("stdin-to-stdout", bool_switch()) +#if defined(BOOST_POSIX_API) + ("posix-echo-one", value<std::vector<std::string> >()->multitoken()) + ("posix-echo-two", value<std::vector<std::string> >()->multitoken()); +#elif defined(BOOST_WINDOWS_API) + ("windows-print-showwindow", bool_switch()) + ("windows-print-flags", bool_switch()); +#endif + + variables_map vm; + command_line_parser parser(argc, argv); + store(parser.options(desc).allow_unregistered().run(), vm); + notify(vm); + + if (vm.count("echo-stdout")) + { + std::cout << vm["echo-stdout"].as<std::string>() << std::endl; + } + else if (vm.count("echo-stderr")) + { + std::cerr << vm["echo-stderr"].as<std::string>() << std::endl; + } + else if (vm.count("echo-stdout-stderr")) + { + std::cout << vm["echo-stdout-stderr"].as<std::string>() << std::endl; + std::cerr << vm["echo-stdout-stderr"].as<std::string>() << std::endl; + } + else if (vm["echo-argv"].as<bool>()) + { + std::vector<std::string> v, v2; + boost::push_back(v, boost::make_iterator_range(argv, argv + argc)); + boost::transform(v, std::back_inserter(v2), + "\"" + boost::lambda::_1 + "\""); + std::cout << boost::algorithm::join(v2, " ") << std::endl; + } + else if (vm.count("exit-code")) + { + return vm["exit-code"].as<int>(); + } + else if (vm.count("wait")) + { + int sec = vm["wait"].as<int>(); +#if defined(BOOST_POSIX_API) + sleep(sec); +#elif defined(BOOST_WINDOWS_API) + Sleep(sec * 1000); +#endif + } + else if (vm["is-closed-stdin"].as<bool>()) + { + std::string s; + std::cin >> s; + return std::cin.eof() ? EXIT_SUCCESS : EXIT_FAILURE; + } + else if (vm["is-closed-stdout"].as<bool>()) + { + std::cout << "foo" << std::endl; + return std::cout.bad() ? EXIT_SUCCESS : EXIT_FAILURE; + } + else if (vm["is-closed-stderr"].as<bool>()) + { + std::cerr << "foo" << std::endl; + return std::cerr.bad() ? EXIT_SUCCESS : EXIT_FAILURE; + } + else if (vm["is-nul-stdin"].as<bool>()) + { +#if defined(BOOST_POSIX_API) + char buffer[1]; + int res = read(STDIN_FILENO, buffer, 1); + return res != -1 ? EXIT_SUCCESS : EXIT_FAILURE; +#elif defined(BOOST_WINDOWS_API) + HANDLE h = GetStdHandle(STD_INPUT_HANDLE); + if (h == INVALID_HANDLE_VALUE) + return EXIT_FAILURE; + char buffer[1]; + DWORD read; + BOOL res = ReadFile(h, buffer, 1, &read, NULL); + CloseHandle(h); + return res ? EXIT_SUCCESS : EXIT_FAILURE; +#endif + } + else if (vm["is-nul-stdout"].as<bool>()) + { + std::cout << "foo" << std::endl; + return std::cout.bad() ? EXIT_FAILURE : EXIT_SUCCESS; + } + else if (vm["is-nul-stderr"].as<bool>()) + { + std::cerr << "foo" << std::endl; + return std::cerr.bad() ? EXIT_FAILURE : EXIT_SUCCESS; + } + else if (vm["loop"].as<bool>()) + { + for (;;); + } + else if (vm.count("prefix")) + { + std::string line; + while (std::getline(std::cin, line)) + std::cout << vm["prefix"].as<std::string>() << line << std::endl; + } + else if (vm.count("prefix-once")) + { + std::string line; + std::getline(std::cin, line); + std::cout << vm["prefix-once"].as<std::string>() << line << std::endl; + } + else if (vm["pwd"].as<bool>()) + { + std::cout << boost::filesystem::current_path().string() << std::endl; + } + else if (vm.count("query-env")) + { +#if defined(BOOST_POSIX_API) + const char *value = getenv(vm["query-env"].as<std::string>().c_str()); + if (value == NULL) + std::cout << "undefined" << std::endl; + else + { + std::cout << "defined" << std::endl; + std::cout << value << std::endl; + } +#elif defined(BOOST_WINDOWS_API) + char buf[1024]; + DWORD res = GetEnvironmentVariableA(vm["query-env"].as<std::string>().c_str(), buf, sizeof(buf)); + if (res == 0) + std::cout << "undefined" << std::endl; + else + { + std::cout << "defined" << std::endl; + std::cout << buf << std::endl; + } +#endif + } + else if (vm["stdin-to-stdout"].as<bool>()) + { + char ch; + while (std::cin >> std::noskipws >> ch) + std::cout << ch << std::flush; + } +#if defined(BOOST_POSIX_API) + else if (vm.count("posix-echo-one")) + { + using namespace boost::iostreams; + std::vector<std::string> v = vm["posix-echo-one"].as<std::vector<std::string> >(); + int fd = boost::lexical_cast<int>(v[0]); + file_descriptor_sink sink(fd, close_handle); + stream<file_descriptor_sink> os(sink); + os << v[1] << std::endl; + } + else if (vm.count("posix-echo-two")) + { + using namespace boost::iostreams; + std::vector<std::string> v = vm["posix-echo-two"].as<std::vector<std::string> >(); + int fd1 = boost::lexical_cast<int>(v[0]); + file_descriptor_sink sink1(fd1, close_handle); + stream<file_descriptor_sink> os1(sink1); + os1 << v[1] << std::endl; + int fd2 = boost::lexical_cast<int>(v[2]); + file_descriptor_sink sink2(fd2, close_handle); + stream<file_descriptor_sink> os2(sink2); + os2 << v[3] << std::endl; + } +#elif defined(BOOST_WINDOWS_API) + else if (vm["windows-print-showwindow"].as<bool>()) + { + STARTUPINFO si; + GetStartupInfo(&si); + std::cout << si.wShowWindow << std::endl; + } + else if (vm["windows-print-flags"].as<bool>()) + { + STARTUPINFO si; + GetStartupInfo(&si); + std::cout << si.dwFlags << std::endl; + } +#endif + return EXIT_SUCCESS; +} diff --git a/plugins/New_GPG/src/include/libs/process/test/start_in_dir.cpp b/plugins/New_GPG/src/include/libs/process/test/start_in_dir.cpp new file mode 100644 index 0000000000..eb7c5737bb --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/start_in_dir.cpp @@ -0,0 +1,63 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filter/newline.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/filesystem.hpp> +#include <string> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +struct test_dir +{ + std::string s_; + test_dir(const std::string &s) : s_(s) + { BOOST_REQUIRE_NO_THROW(boost::filesystem::create_directory(s)); } + ~test_dir() { boost::filesystem::remove(s_); } +}; + +BOOST_AUTO_TEST_CASE(start_in_dir) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + + test_dir dir("start_in_dir_test"); + + bp::pipe p = bp::create_pipe(); + + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(boost::filesystem::absolute(master_test_suite().argv[1])), + bpi::set_cmd_line("test --pwd"), + bpi::start_in_dir(dir.s_), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + bio::close(sink); + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::filtering_istream is; + is.push(bio::newline_filter(bio::newline::posix)); + is.push(source); + + std::string s; + std::getline(is, s); + BOOST_CHECK_EQUAL(s, boost::filesystem::absolute(dir.s_)); + + BOOST_REQUIRE_NO_THROW(bp::wait_for_exit(c)); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/start_in_dir_wstring.cpp b/plugins/New_GPG/src/include/libs/process/test/start_in_dir_wstring.cpp new file mode 100644 index 0000000000..245a567583 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/start_in_dir_wstring.cpp @@ -0,0 +1,67 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define _UNICODE +#define UNICODE +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filter/newline.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/filesystem.hpp> +#include <string> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +struct test_dir +{ + std::wstring ws_; + test_dir(const std::wstring &ws) : ws_(ws) + { BOOST_REQUIRE_NO_THROW(boost::filesystem::create_directory(ws)); } + ~test_dir() { boost::filesystem::remove(ws_); } +}; + +BOOST_AUTO_TEST_CASE(start_in_dir) +{ + using boost::unit_test::framework::master_test_suite; + namespace bio = boost::iostreams; + + test_dir dir(L"start_in_dir_test"); + + boost::filesystem::path exe = master_test_suite().argv[1]; + + bp::pipe p = bp::create_pipe(); + + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(boost::filesystem::absolute(exe)), + bpi::set_cmd_line(L"test --pwd"), + bpi::start_in_dir(dir.ws_), + bpi::bind_stdout(sink), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + bio::close(sink); + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::filtering_istream is; + is.push(bio::newline_filter(bio::newline::posix)); + is.push(source); + + std::string s; + std::getline(is, s); + BOOST_CHECK_EQUAL(s, boost::filesystem::absolute(dir.ws_)); + + BOOST_REQUIRE_NO_THROW(bp::wait_for_exit(c)); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/terminate.cpp b/plugins/New_GPG/src/include/libs/process/test/terminate.cpp new file mode 100644 index 0000000000..1306492436 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/terminate.cpp @@ -0,0 +1,48 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(terminate_set_on_error) +{ + using boost::unit_test::framework::master_test_suite; + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --loop"), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + bp::terminate(c, ec); + BOOST_CHECK(!ec); +} + +BOOST_AUTO_TEST_CASE(terminate_throw_on_error) +{ + using boost::unit_test::framework::master_test_suite; + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --loop"), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + BOOST_CHECK_NO_THROW(bp::terminate(c)); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/throw_on_error.cpp b/plugins/New_GPG/src/include/libs/process/test/throw_on_error.cpp new file mode 100644 index 0000000000..47e5eafb41 --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/throw_on_error.cpp @@ -0,0 +1,28 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/system_error.hpp> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(throw_on_error_test) +{ + BOOST_CHECK_THROW( + bp::execute( + bpi::run_exe("doesnt-exist"), + bpi::throw_on_error() + ), + boost::system::system_error + ); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/wait.cpp b/plugins/New_GPG/src/include/libs/process/test/wait.cpp new file mode 100644 index 0000000000..7b60ce4e2e --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/wait.cpp @@ -0,0 +1,71 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/asio.hpp> +#if defined(BOOST_POSIX_API) +# include <signal.h> +#endif + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; + +BOOST_AUTO_TEST_CASE(sync_wait) +{ + using boost::unit_test::framework::master_test_suite; + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --wait 1"), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + bp::wait_for_exit(c); +} + +struct wait_handler +{ +#if defined(BOOST_WINDOWS_API) + void operator()(const boost::system::error_code&) {} +#elif defined(BOOST_POSIX_API) + void operator()(const boost::system::error_code&, int) {} +#endif +}; + +BOOST_AUTO_TEST_CASE(async_wait) +{ + using boost::unit_test::framework::master_test_suite; + using namespace boost::asio; + + boost::system::error_code ec; + bp::child c = bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --wait 1"), + bpi::set_on_error(ec) + ); + BOOST_REQUIRE(!ec); + + boost::asio::io_service io_service; + +#if defined(BOOST_WINDOWS_API) + windows::object_handle handle(io_service, c.process_handle()); + handle.async_wait(wait_handler()); +#elif defined(BOOST_POSIX_API) + signal_set set(io_service, SIGCHLD); + set.async_wait(wait_handler()); +#endif + + io_service.run(); +} diff --git a/plugins/New_GPG/src/include/libs/process/test/windows_specific.cpp b/plugins/New_GPG/src/include/libs/process/test/windows_specific.cpp new file mode 100644 index 0000000000..c0c69e085a --- /dev/null +++ b/plugins/New_GPG/src/include/libs/process/test/windows_specific.cpp @@ -0,0 +1,53 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MAIN +#define BOOST_TEST_IGNORE_SIGCHLD +#include <boost/test/included/unit_test.hpp> +#include <boost/process.hpp> +#include <boost/system/error_code.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <Windows.h> + +namespace bp = boost::process; +namespace bpi = boost::process::initializers; +namespace bio = boost::iostreams; + +void set_flags(bp::executor &e) +{ + e.startup_info.dwFlags |= STARTF_FORCEOFFFEEDBACK; +} + +BOOST_AUTO_TEST_CASE(flags) +{ + using boost::unit_test::framework::master_test_suite; + + bp::pipe p = bp::create_pipe(); + + { + bio::file_descriptor_sink sink(p.sink, bio::close_handle); + boost::system::error_code ec; + bp::execute( + bpi::run_exe(master_test_suite().argv[1]), + bpi::set_cmd_line("test --windows-print-flags"), + bpi::bind_stdout(sink), + bpi::on_CreateProcess_setup(set_flags), + bpi::set_on_error(ec) + ); + BOOST_CHECK(!ec); + } + + bio::file_descriptor_source source(p.source, bio::close_handle); + bio::stream<bio::file_descriptor_source> is(source); + + int i; + is >> i; + BOOST_CHECK_EQUAL(i, STARTF_USESTDHANDLES | STARTF_FORCEOFFFEEDBACK); +} diff --git a/plugins/New_GPG/src/include/pstream.h b/plugins/New_GPG/src/include/pstream.h new file mode 100644 index 0000000000..c0a1f964dd --- /dev/null +++ b/plugins/New_GPG/src/include/pstream.h @@ -0,0 +1,2095 @@ +/* $Id: pstream.h,v 1.112 2010/03/20 14:50:47 redi Exp $ +PStreams - POSIX Process I/O for C++ +Copyright (C) 2001,2002,2003,2004,2005,2006,2007,2008 Jonathan Wakely + +This file is part of PStreams. + +PStreams is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +PStreams is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * @file pstream.h + * @brief Declares all PStreams classes. + * @author Jonathan Wakely + * + * Defines classes redi::ipstream, redi::opstream, redi::pstream + * and redi::rpstream. + */ + +#ifndef REDI_PSTREAM_H_SEEN +#define REDI_PSTREAM_H_SEEN + +#include <ios> +#include <streambuf> +#include <istream> +#include <ostream> +#include <string> +#include <vector> +#include <algorithm> // for min() +#include <cerrno> // for errno +#include <cstddef> // for size_t +#include <cstdlib> // for exit() +#include <sys/types.h> // for pid_t +#include <sys/wait.h> // for waitpid() +#include <sys/ioctl.h> // for ioctl() and FIONREAD +#if defined(__sun) +# include <sys/filio.h> // for FIONREAD on Solaris 2.5 +#endif +#include <unistd.h> // for pipe() fork() exec() and filedes functions +#include <signal.h> // for kill() +#include <fcntl.h> // for fcntl() +#if REDI_EVISCERATE_PSTREAMS +# include <stdio.h> // for FILE, fdopen() +#endif + + +/// The library version. +#define PSTREAMS_VERSION 0x0070 // 0.7.0 + +/** + * @namespace redi + * @brief All PStreams classes are declared in namespace redi. + * + * Like the standard iostreams, PStreams is a set of class templates, + * taking a character type and traits type. As with the standard streams + * they are most likely to be used with @c char and the default + * traits type, so typedefs for this most common case are provided. + * + * The @c pstream_common class template is not intended to be used directly, + * it is used internally to provide the common functionality for the + * other stream classes. + */ +namespace redi +{ + /// Common base class providing constants and typenames. + struct pstreams + { + /// Type used to specify how to connect to the process. + typedef std::ios_base::openmode pmode; + + /// Type used to hold the arguments for a command. + typedef std::vector<std::string> argv_type; + + /// Type used for file descriptors. + typedef int fd_type; + + static const pmode pstdin = std::ios_base::out; ///< Write to stdin + static const pmode pstdout = std::ios_base::in; ///< Read from stdout + static const pmode pstderr = std::ios_base::app; ///< Read from stderr + + protected: + enum { bufsz = 32 }; ///< Size of pstreambuf buffers. + enum { pbsz = 2 }; ///< Number of putback characters kept. + }; + + /// Class template for stream buffer. + template <typename CharT, typename Traits = std::char_traits<CharT> > + class basic_pstreambuf + : public std::basic_streambuf<CharT, Traits> + , public pstreams + { + public: + // Type definitions for dependent types + typedef CharT char_type; + typedef Traits traits_type; + typedef typename traits_type::int_type int_type; + typedef typename traits_type::off_type off_type; + typedef typename traits_type::pos_type pos_type; + /** @deprecated use pstreams::fd_type instead. */ + typedef fd_type fd_t; + + /// Default constructor. + basic_pstreambuf(); + + /// Constructor that initialises the buffer with @a command. + basic_pstreambuf(const std::string& command, pmode mode); + + /// Constructor that initialises the buffer with @a file and @a argv. + basic_pstreambuf( const std::string& file, + const argv_type& argv, + pmode mode ); + + /// Destructor. + ~basic_pstreambuf(); + + /// Initialise the stream buffer with @a command. + basic_pstreambuf* + open(const std::string& command, pmode mode); + + /// Initialise the stream buffer with @a file and @a argv. + basic_pstreambuf* + open(const std::string& file, const argv_type& argv, pmode mode); + + /// Close the stream buffer and wait for the process to exit. + basic_pstreambuf* + close(); + + /// Send a signal to the process. + basic_pstreambuf* + kill(int signal = SIGTERM); + + /// Close the pipe connected to the process' stdin. + void + peof(); + + /// Change active input source. + bool + read_err(bool readerr = true); + + /// Report whether the stream buffer has been initialised. + bool + is_open() const; + + /// Report whether the process has exited. + bool + exited(); + +#if REDI_EVISCERATE_PSTREAMS + /// Obtain FILE pointers for each of the process' standard streams. + std::size_t + fopen(FILE*& in, FILE*& out, FILE*& err); +#endif + + /// Return the exit status of the process. + int + status() const; + + /// Return the error number (errno) for the most recent failed operation. + int + error() const; + + protected: + /// Transfer characters to the pipe when character buffer overflows. + int_type + overflow(int_type c); + + /// Transfer characters from the pipe when the character buffer is empty. + int_type + underflow(); + + /// Make a character available to be returned by the next extraction. + int_type + pbackfail(int_type c = traits_type::eof()); + + /// Write any buffered characters to the stream. + int + sync(); + + /// Insert multiple characters into the pipe. + std::streamsize + xsputn(const char_type* s, std::streamsize n); + + /// Insert a sequence of characters into the pipe. + std::streamsize + write(const char_type* s, std::streamsize n); + + /// Extract a sequence of characters from the pipe. + std::streamsize + read(char_type* s, std::streamsize n); + + /// Report how many characters can be read from active input without blocking. + std::streamsize + showmanyc(); + + protected: + /// Enumerated type to indicate whether stdout or stderr is to be read. + enum buf_read_src { rsrc_out = 0, rsrc_err = 1 }; + + /// Initialise pipes and fork process. + pid_t + fork(pmode mode); + + /// Wait for the child process to exit. + int + wait(bool nohang = false); + + /// Return the file descriptor for the output pipe. + fd_type& + wpipe(); + + /// Return the file descriptor for the active input pipe. + fd_type& + rpipe(); + + /// Return the file descriptor for the specified input pipe. + fd_type& + rpipe(buf_read_src which); + + void + create_buffers(pmode mode); + + void + destroy_buffers(pmode mode); + + /// Writes buffered characters to the process' stdin pipe. + bool + empty_buffer(); + + bool + fill_buffer(bool non_blocking = false); + + /// Return the active input buffer. + char_type* + rbuffer(); + + buf_read_src + switch_read_buffer(buf_read_src); + + private: + basic_pstreambuf(const basic_pstreambuf&); + basic_pstreambuf& operator=(const basic_pstreambuf&); + + void + init_rbuffers(); + + pid_t ppid_; // pid of process + fd_type wpipe_; // pipe used to write to process' stdin + fd_type rpipe_[2]; // two pipes to read from, stdout and stderr + char_type* wbuffer_; + char_type* rbuffer_[2]; + char_type* rbufstate_[3]; + /// Index into rpipe_[] to indicate active source for read operations. + buf_read_src rsrc_; + int status_; // hold exit status of child process + int error_; // hold errno if fork() or exec() fails + }; + + /// Class template for common base class. + template <typename CharT, typename Traits = std::char_traits<CharT> > + class pstream_common + : virtual public std::basic_ios<CharT, Traits> + , virtual public pstreams + { + protected: + typedef basic_pstreambuf<CharT, Traits> streambuf_type; + + typedef pstreams::pmode pmode; + typedef pstreams::argv_type argv_type; + + /// Default constructor. + pstream_common(); + + /// Constructor that initialises the stream by starting a process. + pstream_common(const std::string& command, pmode mode); + + /// Constructor that initialises the stream by starting a process. + pstream_common(const std::string& file, const argv_type& argv, pmode mode); + + /// Pure virtual destructor. + virtual + ~pstream_common() = 0; + + /// Start a process. + void + do_open(const std::string& command, pmode mode); + + /// Start a process. + void + do_open(const std::string& file, const argv_type& argv, pmode mode); + + public: + /// Close the pipe. + void + close(); + + /// Report whether the stream's buffer has been initialised. + bool + is_open() const; + + /// Return the command used to initialise the stream. + const std::string& + command() const; + + /// Return a pointer to the stream buffer. + streambuf_type* + rdbuf() const; + +#if REDI_EVISCERATE_PSTREAMS + /// Obtain FILE pointers for each of the process' standard streams. + std::size_t + fopen(FILE*& in, FILE*& out, FILE*& err); +#endif + + protected: + std::string command_; ///< The command used to start the process. + streambuf_type buf_; ///< The stream buffer. + }; + + + /** + * @class basic_ipstream + * @brief Class template for Input PStreams. + * + * Reading from an ipstream reads the command's standard output and/or + * standard error (depending on how the ipstream is opened) + * and the command's standard input is the same as that of the process + * that created the object, unless altered by the command itself. + */ + + template <typename CharT, typename Traits = std::char_traits<CharT> > + class basic_ipstream + : public std::basic_istream<CharT, Traits> + , public pstream_common<CharT, Traits> + , virtual public pstreams + { + typedef std::basic_istream<CharT, Traits> istream_type; + typedef pstream_common<CharT, Traits> pbase_type; + + using pbase_type::buf_; // declare name in this scope + + pmode readable(pmode mode) + { + if (!(mode & (pstdout|pstderr))) + mode |= pstdout; + return mode; + } + + public: + /// Type used to specify how to connect to the process. + typedef typename pbase_type::pmode pmode; + + /// Type used to hold the arguments for a command. + typedef typename pbase_type::argv_type argv_type; + + /// Default constructor, creates an uninitialised stream. + basic_ipstream() + : istream_type(NULL), pbase_type() + { } + + /** + * @brief Constructor that initialises the stream by starting a process. + * + * Initialises the stream buffer by calling do_open() with the supplied + * arguments. + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, pmode) + */ + basic_ipstream(const std::string& command, pmode mode = pstdout) + : istream_type(NULL), pbase_type(command, readable(mode)) + { } + + /** + * @brief Constructor that initialises the stream by starting a process. + * + * Initialises the stream buffer by calling do_open() with the supplied + * arguments. + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, const argv_type&, pmode) + */ + basic_ipstream( const std::string& file, + const argv_type& argv, + pmode mode = pstdout ) + : istream_type(NULL), pbase_type(file, argv, readable(mode)) + { } + + /** + * @brief Destructor. + * + * Closes the stream and waits for the child to exit. + */ + ~basic_ipstream() + { } + + /** + * @brief Start a process. + * + * Calls do_open( @a %command , @a mode|pstdout ). + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, pmode) + */ + void + open(const std::string& command, pmode mode = pstdout) + { + this->do_open(command, readable(mode)); + } + + /** + * @brief Start a process. + * + * Calls do_open( @a file , @a argv , @a mode|pstdout ). + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, const argv_type&, pmode) + */ + void + open( const std::string& file, + const argv_type& argv, + pmode mode = pstdout ) + { + this->do_open(file, argv, readable(mode)); + } + + /** + * @brief Set streambuf to read from process' @c stdout. + * @return @c *this + */ + basic_ipstream& + out() + { + this->buf_.read_err(false); + return *this; + } + + /** + * @brief Set streambuf to read from process' @c stderr. + * @return @c *this + */ + basic_ipstream& + err() + { + this->buf_.read_err(true); + return *this; + } + }; + + + /** + * @class basic_opstream + * @brief Class template for Output PStreams. + * + * Writing to an open opstream writes to the standard input of the command; + * the command's standard output is the same as that of the process that + * created the pstream object, unless altered by the command itself. + */ + + template <typename CharT, typename Traits = std::char_traits<CharT> > + class basic_opstream + : public std::basic_ostream<CharT, Traits> + , public pstream_common<CharT, Traits> + , virtual public pstreams + { + typedef std::basic_ostream<CharT, Traits> ostream_type; + typedef pstream_common<CharT, Traits> pbase_type; + + using pbase_type::buf_; // declare name in this scope + + public: + /// Type used to specify how to connect to the process. + typedef typename pbase_type::pmode pmode; + + /// Type used to hold the arguments for a command. + typedef typename pbase_type::argv_type argv_type; + + /// Default constructor, creates an uninitialised stream. + basic_opstream() + : ostream_type(NULL), pbase_type() + { } + + /** + * @brief Constructor that initialises the stream by starting a process. + * + * Initialises the stream buffer by calling do_open() with the supplied + * arguments. + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, pmode) + */ + basic_opstream(const std::string& command, pmode mode = pstdin) + : ostream_type(NULL), pbase_type(command, mode|pstdin) + { } + + /** + * @brief Constructor that initialises the stream by starting a process. + * + * Initialises the stream buffer by calling do_open() with the supplied + * arguments. + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, const argv_type&, pmode) + */ + basic_opstream( const std::string& file, + const argv_type& argv, + pmode mode = pstdin ) + : ostream_type(NULL), pbase_type(file, argv, mode|pstdin) + { } + + /** + * @brief Destructor + * + * Closes the stream and waits for the child to exit. + */ + ~basic_opstream() { } + + /** + * @brief Start a process. + * + * Calls do_open( @a %command , @a mode|pstdin ). + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, pmode) + */ + void + open(const std::string& command, pmode mode = pstdin) + { + this->do_open(command, mode|pstdin); + } + + /** + * @brief Start a process. + * + * Calls do_open( @a file , @a argv , @a mode|pstdin ). + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, const argv_type&, pmode) + */ + void + open( const std::string& file, + const argv_type& argv, + pmode mode = pstdin) + { + this->do_open(file, argv, mode|pstdin); + } + }; + + + /** + * @class basic_pstream + * @brief Class template for Bidirectional PStreams. + * + * Writing to a pstream opened with @c pmode @c pstdin writes to the + * standard input of the command. + * Reading from a pstream opened with @c pmode @c pstdout and/or @c pstderr + * reads the command's standard output and/or standard error. + * Any of the process' @c stdin, @c stdout or @c stderr that is not + * connected to the pstream (as specified by the @c pmode) + * will be the same as the process that created the pstream object, + * unless altered by the command itself. + */ + template <typename CharT, typename Traits = std::char_traits<CharT> > + class basic_pstream + : public std::basic_iostream<CharT, Traits> + , public pstream_common<CharT, Traits> + , virtual public pstreams + { + typedef std::basic_iostream<CharT, Traits> iostream_type; + typedef pstream_common<CharT, Traits> pbase_type; + + using pbase_type::buf_; // declare name in this scope + + public: + /// Type used to specify how to connect to the process. + typedef typename pbase_type::pmode pmode; + + /// Type used to hold the arguments for a command. + typedef typename pbase_type::argv_type argv_type; + + /// Default constructor, creates an uninitialised stream. + basic_pstream() + : iostream_type(NULL), pbase_type() + { } + + /** + * @brief Constructor that initialises the stream by starting a process. + * + * Initialises the stream buffer by calling do_open() with the supplied + * arguments. + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, pmode) + */ + basic_pstream(const std::string& command, pmode mode = pstdout|pstdin) + : iostream_type(NULL), pbase_type(command, mode) + { } + + /** + * @brief Constructor that initialises the stream by starting a process. + * + * Initialises the stream buffer by calling do_open() with the supplied + * arguments. + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, const argv_type&, pmode) + */ + basic_pstream( const std::string& file, + const argv_type& argv, + pmode mode = pstdout|pstdin ) + : iostream_type(NULL), pbase_type(file, argv, mode) + { } + + /** + * @brief Destructor + * + * Closes the stream and waits for the child to exit. + */ + ~basic_pstream() { } + + /** + * @brief Start a process. + * + * Calls do_open( @a %command , @a mode ). + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, pmode) + */ + void + open(const std::string& command, pmode mode = pstdout|pstdin) + { + this->do_open(command, mode); + } + + /** + * @brief Start a process. + * + * Calls do_open( @a file , @a argv , @a mode ). + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, const argv_type&, pmode) + */ + void + open( const std::string& file, + const argv_type& argv, + pmode mode = pstdout|pstdin ) + { + this->do_open(file, argv, mode); + } + + /** + * @brief Set streambuf to read from process' @c stdout. + * @return @c *this + */ + basic_pstream& + out() + { + this->buf_.read_err(false); + return *this; + } + + /** + * @brief Set streambuf to read from process' @c stderr. + * @return @c *this + */ + basic_pstream& + err() + { + this->buf_.read_err(true); + return *this; + } + }; + + + /** + * @class basic_rpstream + * @brief template for Restricted PStreams. + * + * Writing to an rpstream opened with @c pmode @c pstdin writes to the + * standard input of the command. + * It is not possible to read directly from an rpstream object, to use + * an rpstream as in istream you must call either basic_rpstream::out() + * or basic_rpstream::err(). This is to prevent accidental reads from + * the wrong input source. If the rpstream was not opened with @c pmode + * @c pstderr then the class cannot read the process' @c stderr, and + * basic_rpstream::err() will return an istream that reads from the + * process' @c stdout, and vice versa. + * Reading from an rpstream opened with @c pmode @c pstdout and/or + * @c pstderr reads the command's standard output and/or standard error. + * Any of the process' @c stdin, @c stdout or @c stderr that is not + * connected to the pstream (as specified by the @c pmode) + * will be the same as the process that created the pstream object, + * unless altered by the command itself. + */ + + template <typename CharT, typename Traits = std::char_traits<CharT> > + class basic_rpstream + : public std::basic_ostream<CharT, Traits> + , private std::basic_istream<CharT, Traits> + , private pstream_common<CharT, Traits> + , virtual public pstreams + { + typedef std::basic_ostream<CharT, Traits> ostream_type; + typedef std::basic_istream<CharT, Traits> istream_type; + typedef pstream_common<CharT, Traits> pbase_type; + + using pbase_type::buf_; // declare name in this scope + + public: + /// Type used to specify how to connect to the process. + typedef typename pbase_type::pmode pmode; + + /// Type used to hold the arguments for a command. + typedef typename pbase_type::argv_type argv_type; + + /// Default constructor, creates an uninitialised stream. + basic_rpstream() + : ostream_type(NULL), istream_type(NULL), pbase_type() + { } + + /** + * @brief Constructor that initialises the stream by starting a process. + * + * Initialises the stream buffer by calling do_open() with the supplied + * arguments. + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, pmode) + */ + basic_rpstream(const std::string& command, pmode mode = pstdout|pstdin) + : ostream_type(NULL) , istream_type(NULL) , pbase_type(command, mode) + { } + + /** + * @brief Constructor that initialises the stream by starting a process. + * + * Initialises the stream buffer by calling do_open() with the supplied + * arguments. + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, const argv_type&, pmode) + */ + basic_rpstream( const std::string& file, + const argv_type& argv, + pmode mode = pstdout|pstdin ) + : ostream_type(NULL), istream_type(NULL), pbase_type(file, argv, mode) + { } + + /// Destructor + ~basic_rpstream() { } + + /** + * @brief Start a process. + * + * Calls do_open( @a %command , @a mode ). + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, pmode) + */ + void + open(const std::string& command, pmode mode = pstdout|pstdin) + { + this->do_open(command, mode); + } + + /** + * @brief Start a process. + * + * Calls do_open( @a file , @a argv , @a mode ). + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, const argv_type&, pmode) + */ + void + open( const std::string& file, + const argv_type& argv, + pmode mode = pstdout|pstdin ) + { + this->do_open(file, argv, mode); + } + + /** + * @brief Obtain a reference to the istream that reads + * the process' @c stdout. + * @return @c *this + */ + istream_type& + out() + { + this->buf_.read_err(false); + return *this; + } + + /** + * @brief Obtain a reference to the istream that reads + * the process' @c stderr. + * @return @c *this + */ + istream_type& + err() + { + this->buf_.read_err(true); + return *this; + } + }; + + + /// Type definition for common template specialisation. + typedef basic_pstreambuf<char> pstreambuf; + /// Type definition for common template specialisation. + typedef basic_ipstream<char> ipstream; + /// Type definition for common template specialisation. + typedef basic_opstream<char> opstream; + /// Type definition for common template specialisation. + typedef basic_pstream<char> pstream; + /// Type definition for common template specialisation. + typedef basic_rpstream<char> rpstream; + + + /** + * When inserted into an output pstream the manipulator calls + * basic_pstreambuf<C,T>::peof() to close the output pipe, + * causing the child process to receive the end-of-file indicator + * on subsequent reads from its @c stdin stream. + * + * @brief Manipulator to close the pipe connected to the process' stdin. + * @param s An output PStream class. + * @return The stream object the manipulator was invoked on. + * @see basic_pstreambuf<C,T>::peof() + * @relates basic_opstream basic_pstream basic_rpstream + */ + template <typename C, typename T> + inline std::basic_ostream<C,T>& + peof(std::basic_ostream<C,T>& s) + { + typedef basic_pstreambuf<C,T> pstreambuf; + if (pstreambuf* p = dynamic_cast<pstreambuf*>(s.rdbuf())) + p->peof(); + return s; + } + + + /* + * member definitions for pstreambuf + */ + + + /** + * @class basic_pstreambuf + * Provides underlying streambuf functionality for the PStreams classes. + */ + + /** Creates an uninitialised stream buffer. */ + template <typename C, typename T> + inline + basic_pstreambuf<C,T>::basic_pstreambuf() + : ppid_(-1) // initialise to -1 to indicate no process run yet. + , wpipe_(-1) + , wbuffer_(NULL) + , rsrc_(rsrc_out) + , status_(-1) + , error_(0) + { + init_rbuffers(); + } + + /** + * Initialises the stream buffer by calling open() with the supplied + * arguments. + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see open() + */ + template <typename C, typename T> + inline + basic_pstreambuf<C,T>::basic_pstreambuf(const std::string& command, pmode mode) + : ppid_(-1) // initialise to -1 to indicate no process run yet. + , wpipe_(-1) + , wbuffer_(NULL) + , rsrc_(rsrc_out) + , status_(-1) + , error_(0) + { + init_rbuffers(); + open(command, mode); + } + + /** + * Initialises the stream buffer by calling open() with the supplied + * arguments. + * + * @param file a string containing the name of a program to execute. + * @param argv a vector of argument strings passsed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see open() + */ + template <typename C, typename T> + inline + basic_pstreambuf<C,T>::basic_pstreambuf( const std::string& file, + const argv_type& argv, + pmode mode ) + : ppid_(-1) // initialise to -1 to indicate no process run yet. + , wpipe_(-1) + , wbuffer_(NULL) + , rsrc_(rsrc_out) + , status_(-1) + , error_(0) + { + init_rbuffers(); + open(file, argv, mode); + } + + /** + * Closes the stream by calling close(). + * @see close() + */ + template <typename C, typename T> + inline + basic_pstreambuf<C,T>::~basic_pstreambuf() + { + close(); + } + + /** + * Starts a new process by passing @a command to the shell (/bin/sh) + * and opens pipes to the process with the specified @a mode. + * + * If @a mode contains @c pstdout the initial read source will be + * the child process' stdout, otherwise if @a mode contains @c pstderr + * the initial read source will be the child's stderr. + * + * Will duplicate the actions of the shell in searching for an + * executable file if the specified file name does not contain a slash (/) + * character. + * + * @warning + * There is no way to tell whether the shell command succeeded, this + * function will always succeed unless resource limits (such as + * memory usage, or number of processes or open files) are exceeded. + * This means is_open() will return true even if @a command cannot + * be executed. + * Use pstreambuf::open(const std::string&, const argv_type&, pmode) + * if you need to know whether the command failed to execute. + * + * @param command a string containing a shell command. + * @param mode a bitwise OR of one or more of @c out, @c in, @c err. + * @return NULL if the shell could not be started or the + * pipes could not be opened, @c this otherwise. + * @see <b>execl</b>(3) + */ + template <typename C, typename T> + basic_pstreambuf<C,T>* + basic_pstreambuf<C,T>::open(const std::string& command, pmode mode) + { + const char * shell_path = "/bin/sh"; +#if 0 + const std::string argv[] = { "sh", "-c", command }; + return this->open(shell_path, argv_type(argv, argv+3), mode); +#else + basic_pstreambuf<C,T>* ret = NULL; + + if (!is_open()) + { + switch(fork(mode)) + { + case 0 : + // this is the new process, exec command + ::execl(shell_path, "sh", "-c", command.c_str(), (char*)NULL); + + // can only reach this point if exec() failed + + // parent can get exit code from waitpid() + ::_exit(errno); + // using std::exit() would make static dtors run twice + + case -1 : + // couldn't fork, error already handled in pstreambuf::fork() + break; + + default : + // this is the parent process + // activate buffers + create_buffers(mode); + ret = this; + } + } + return ret; +#endif + } + + /** + * @brief Helper function to close a file descriptor. + * + * Inspects @a fd and calls <b>close</b>(3) if it has a non-negative value. + * + * @param fd a file descriptor. + * @relates basic_pstreambuf + */ + inline void + close_fd(pstreams::fd_type& fd) + { + if (fd >= 0 && ::close(fd) == 0) + fd = -1; + } + + /** + * @brief Helper function to close an array of file descriptors. + * + * Calls @c close_fd() on each member of the array. + * The length of the array is determined automatically by + * template argument deduction to avoid errors. + * + * @param fds an array of file descriptors. + * @relates basic_pstreambuf + */ + template <int N> + inline void + close_fd_array(pstreams::fd_type (&fds)[N]) + { + for (std::size_t i = 0; i < N; ++i) + close_fd(fds[i]); + } + + /** + * Starts a new process by executing @a file with the arguments in + * @a argv and opens pipes to the process with the specified @a mode. + * + * By convention @c argv[0] should be the file name of the file being + * executed. + * + * If @a mode contains @c pstdout the initial read source will be + * the child process' stdout, otherwise if @a mode contains @c pstderr + * the initial read source will be the child's stderr. + * + * Will duplicate the actions of the shell in searching for an + * executable file if the specified file name does not contain a slash (/) + * character. + * + * Iff @a file is successfully executed then is_open() will return true. + * Otherwise, pstreambuf::error() can be used to obtain the value of + * @c errno that was set by <b>execvp</b>(3) in the child process. + * + * The exit status of the new process will be returned by + * pstreambuf::status() after pstreambuf::exited() returns true. + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode a bitwise OR of one or more of @c out, @c in and @c err. + * @return NULL if a pipe could not be opened or if the program could + * not be executed, @c this otherwise. + * @see <b>execvp</b>(3) + */ + template <typename C, typename T> + basic_pstreambuf<C,T>* + basic_pstreambuf<C,T>::open( const std::string& file, + const argv_type& argv, + pmode mode ) + { + basic_pstreambuf<C,T>* ret = NULL; + + if (!is_open()) + { + // constants for read/write ends of pipe + enum { RD, WR }; + + // open another pipe and set close-on-exec + fd_type ck_exec[] = { -1, -1 }; + if (-1 == ::pipe(ck_exec) + || -1 == ::fcntl(ck_exec[RD], F_SETFD, FD_CLOEXEC) + || -1 == ::fcntl(ck_exec[WR], F_SETFD, FD_CLOEXEC)) + { + error_ = errno; + close_fd_array(ck_exec); + } + else + { + switch(fork(mode)) + { + case 0 : + // this is the new process, exec command + { + char** arg_v = new char*[argv.size()+1]; + for (std::size_t i = 0; i < argv.size(); ++i) + { + const std::string& src = argv[i]; + char*& dest = arg_v[i]; + dest = new char[src.size()+1]; + dest[ src.copy(dest, src.size()) ] = '\0'; + } + arg_v[argv.size()] = NULL; + + ::execvp(file.c_str(), arg_v); + + // can only reach this point if exec() failed + + // parent can get error code from ck_exec pipe + error_ = errno; + + ::write(ck_exec[WR], &error_, sizeof(error_)); + ::close(ck_exec[WR]); + ::close(ck_exec[RD]); + + ::_exit(error_); + // using std::exit() would make static dtors run twice + } + + case -1 : + // couldn't fork, error already handled in pstreambuf::fork() + close_fd_array(ck_exec); + break; + + default : + // this is the parent process + + // check child called exec() successfully + ::close(ck_exec[WR]); + switch (::read(ck_exec[RD], &error_, sizeof(error_))) + { + case 0: + // activate buffers + create_buffers(mode); + ret = this; + break; + case -1: + error_ = errno; + break; + default: + // error_ contains error code from child + // call wait() to clean up and set ppid_ to 0 + this->wait(); + break; + } + ::close(ck_exec[RD]); + } + } + } + return ret; + } + + /** + * Creates pipes as specified by @a mode and calls @c fork() to create + * a new process. If the fork is successful the parent process stores + * the child's PID and the opened pipes and the child process replaces + * its standard streams with the opened pipes. + * + * If an error occurs the error code will be set to one of the possible + * errors for @c pipe() or @c fork(). + * See your system's documentation for these error codes. + * + * @param mode an OR of pmodes specifying which of the child's + * standard streams to connect to. + * @return On success the PID of the child is returned in the parent's + * context and zero is returned in the child's context. + * On error -1 is returned and the error code is set appropriately. + */ + template <typename C, typename T> + pid_t + basic_pstreambuf<C,T>::fork(pmode mode) + { + pid_t pid = -1; + + // Three pairs of file descriptors, for pipes connected to the + // process' stdin, stdout and stderr + // (stored in a single array so close_fd_array() can close all at once) + fd_type fd[] = { -1, -1, -1, -1, -1, -1 }; + fd_type* const pin = fd; + fd_type* const pout = fd+2; + fd_type* const perr = fd+4; + + // constants for read/write ends of pipe + enum { RD, WR }; + + // N.B. + // For the pstreambuf pin is an output stream and + // pout and perr are input streams. + + if (!error_ && mode&pstdin && ::pipe(pin)) + error_ = errno; + + if (!error_ && mode&pstdout && ::pipe(pout)) + error_ = errno; + + if (!error_ && mode&pstderr && ::pipe(perr)) + error_ = errno; + + if (!error_) + { + pid = ::fork(); + switch (pid) + { + case 0 : + { + // this is the new process + + // for each open pipe close one end and redirect the + // respective standard stream to the other end + + if (*pin >= 0) + { + ::close(pin[WR]); + ::dup2(pin[RD], STDIN_FILENO); + ::close(pin[RD]); + } + if (*pout >= 0) + { + ::close(pout[RD]); + ::dup2(pout[WR], STDOUT_FILENO); + ::close(pout[WR]); + } + if (*perr >= 0) + { + ::close(perr[RD]); + ::dup2(perr[WR], STDERR_FILENO); + ::close(perr[WR]); + } + break; + } + case -1 : + { + // couldn't fork for some reason + error_ = errno; + // close any open pipes + close_fd_array(fd); + break; + } + default : + { + // this is the parent process, store process' pid + ppid_ = pid; + + // store one end of open pipes and close other end + if (*pin >= 0) + { + wpipe_ = pin[WR]; + ::close(pin[RD]); + } + if (*pout >= 0) + { + rpipe_[rsrc_out] = pout[RD]; + ::close(pout[WR]); + } + if (*perr >= 0) + { + rpipe_[rsrc_err] = perr[RD]; + ::close(perr[WR]); + } + } + } + } + else + { + // close any pipes we opened before failure + close_fd_array(fd); + } + return pid; + } + + /** + * Closes all pipes and calls wait() to wait for the process to finish. + * If an error occurs the error code will be set to one of the possible + * errors for @c waitpid(). + * See your system's documentation for these errors. + * + * @return @c this on successful close or @c NULL if there is no + * process to close or if an error occurs. + */ + template <typename C, typename T> + basic_pstreambuf<C,T>* + basic_pstreambuf<C,T>::close() + { + const bool running = is_open(); + + sync(); // this might call wait() and reap the child process + + // rather than trying to work out whether or not we need to clean up + // just do it anyway, all cleanup functions are safe to call twice. + + destroy_buffers(pstdin|pstdout|pstderr); + + // close pipes before wait() so child gets EOF/SIGPIPE + close_fd(wpipe_); + close_fd_array(rpipe_); + + do + { + error_ = 0; + } while (wait() == -1 && error() == EINTR); + + return running ? this : NULL; + } + + /** + * Called on construction to initialise the arrays used for reading. + */ + template <typename C, typename T> + inline void + basic_pstreambuf<C,T>::init_rbuffers() + { + rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1; + rbuffer_[rsrc_out] = rbuffer_[rsrc_err] = NULL; + rbufstate_[0] = rbufstate_[1] = rbufstate_[2] = NULL; + } + + template <typename C, typename T> + void + basic_pstreambuf<C,T>::create_buffers(pmode mode) + { + if (mode & pstdin) + { + delete[] wbuffer_; + wbuffer_ = new char_type[bufsz]; + this->setp(wbuffer_, wbuffer_ + bufsz); + } + if (mode & pstdout) + { + delete[] rbuffer_[rsrc_out]; + rbuffer_[rsrc_out] = new char_type[bufsz]; + rsrc_ = rsrc_out; + this->setg(rbuffer_[rsrc_out] + pbsz, rbuffer_[rsrc_out] + pbsz, + rbuffer_[rsrc_out] + pbsz); + } + if (mode & pstderr) + { + delete[] rbuffer_[rsrc_err]; + rbuffer_[rsrc_err] = new char_type[bufsz]; + if (!(mode & pstdout)) + { + rsrc_ = rsrc_err; + this->setg(rbuffer_[rsrc_err] + pbsz, rbuffer_[rsrc_err] + pbsz, + rbuffer_[rsrc_err] + pbsz); + } + } + } + + template <typename C, typename T> + void + basic_pstreambuf<C,T>::destroy_buffers(pmode mode) + { + if (mode & pstdin) + { + this->setp(NULL, NULL); + delete[] wbuffer_; + wbuffer_ = NULL; + } + if (mode & pstdout) + { + if (rsrc_ == rsrc_out) + this->setg(NULL, NULL, NULL); + delete[] rbuffer_[rsrc_out]; + rbuffer_[rsrc_out] = NULL; + } + if (mode & pstderr) + { + if (rsrc_ == rsrc_err) + this->setg(NULL, NULL, NULL); + delete[] rbuffer_[rsrc_err]; + rbuffer_[rsrc_err] = NULL; + } + } + + template <typename C, typename T> + typename basic_pstreambuf<C,T>::buf_read_src + basic_pstreambuf<C,T>::switch_read_buffer(buf_read_src src) + { + if (rsrc_ != src) + { + char_type* tmpbufstate[] = {this->eback(), this->gptr(), this->egptr()}; + this->setg(rbufstate_[0], rbufstate_[1], rbufstate_[2]); + for (std::size_t i = 0; i < 3; ++i) + rbufstate_[i] = tmpbufstate[i]; + rsrc_ = src; + } + return rsrc_; + } + + /** + * Suspends execution and waits for the associated process to exit, or + * until a signal is delivered whose action is to terminate the current + * process or to call a signal handling function. If the process has + * already exited (i.e. it is a "zombie" process) then wait() returns + * immediately. Waiting for the child process causes all its system + * resources to be freed. + * + * error() will return EINTR if wait() is interrupted by a signal. + * + * @param nohang true to return immediately if the process has not exited. + * @return 1 if the process has exited and wait() has not yet been called. + * 0 if @a nohang is true and the process has not exited yet. + * -1 if no process has been started or if an error occurs, + * in which case the error can be found using error(). + */ + template <typename C, typename T> + int + basic_pstreambuf<C,T>::wait(bool nohang) + { + int exited = -1; + if (is_open()) + { + int status; + switch(::waitpid(ppid_, &status, nohang ? WNOHANG : 0)) + { + case 0 : + // nohang was true and process has not exited + exited = 0; + break; + case -1 : + error_ = errno; + break; + default : + // process has exited + ppid_ = 0; + status_ = status; + exited = 1; + // Close wpipe, would get SIGPIPE if we used it. + destroy_buffers(pstdin); + close_fd(wpipe_); + // Must free read buffers and pipes on destruction + // or next call to open()/close() + break; + } + } + return exited; + } + + /** + * Sends the specified signal to the process. A signal can be used to + * terminate a child process that would not exit otherwise. + * + * If an error occurs the error code will be set to one of the possible + * errors for @c kill(). See your system's documentation for these errors. + * + * @param signal A signal to send to the child process. + * @return @c this or @c NULL if @c kill() fails. + */ + template <typename C, typename T> + inline basic_pstreambuf<C,T>* + basic_pstreambuf<C,T>::kill(int signal) + { + basic_pstreambuf<C,T>* ret = NULL; + if (is_open()) + { + if (::kill(ppid_, signal)) + error_ = errno; + else + { +#if 0 + // TODO call exited() to check for exit and clean up? leave to user? + if (signal==SIGTERM || signal==SIGKILL) + this->exited(); +#endif + ret = this; + } + } + return ret; + } + + /** + * This function can call pstreambuf::wait() and so may change the + * object's state if the child process has already exited. + * + * @return True if the associated process has exited, false otherwise. + * @see basic_pstreambuf<C,T>::wait() + */ + template <typename C, typename T> + inline bool + basic_pstreambuf<C,T>::exited() + { + return ppid_ == 0 || wait(true)==1; + } + + + /** + * @return The exit status of the child process, or -1 if wait() + * has not yet been called to wait for the child to exit. + * @see basic_pstreambuf<C,T>::wait() + */ + template <typename C, typename T> + inline int + basic_pstreambuf<C,T>::status() const + { + return status_; + } + + /** + * @return The error code of the most recently failed operation, or zero. + */ + template <typename C, typename T> + inline int + basic_pstreambuf<C,T>::error() const + { + return error_; + } + + /** + * Closes the output pipe, causing the child process to receive the + * end-of-file indicator on subsequent reads from its @c stdin stream. + */ + template <typename C, typename T> + inline void + basic_pstreambuf<C,T>::peof() + { + sync(); + destroy_buffers(pstdin); + close_fd(wpipe_); + } + + /** + * Unlike pstreambuf::exited(), this function will not call wait() and + * so will not change the object's state. This means that once a child + * process is executed successfully this function will continue to + * return true even after the process exits (until wait() is called.) + * + * @return true if a previous call to open() succeeded and wait() has + * not been called and determined that the process has exited, + * false otherwise. + */ + template <typename C, typename T> + inline bool + basic_pstreambuf<C,T>::is_open() const + { + return ppid_ > 0; + } + + /** + * Toggle the stream used for reading. If @a readerr is @c true then the + * process' @c stderr output will be used for subsequent extractions, if + * @a readerr is false the the process' stdout will be used. + * @param readerr @c true to read @c stderr, @c false to read @c stdout. + * @return @c true if the requested stream is open and will be used for + * subsequent extractions, @c false otherwise. + */ + template <typename C, typename T> + inline bool + basic_pstreambuf<C,T>::read_err(bool readerr) + { + buf_read_src src = readerr ? rsrc_err : rsrc_out; + if (rpipe_[src]>=0) + { + switch_read_buffer(src); + return true; + } + return false; + } + + /** + * Called when the internal character buffer is not present or is full, + * to transfer the buffer contents to the pipe. + * + * @param c a character to be written to the pipe. + * @return @c traits_type::eof() if an error occurs, otherwise if @a c + * is not equal to @c traits_type::eof() it will be buffered and + * a value other than @c traits_type::eof() returned to indicate + * success. + */ + template <typename C, typename T> + typename basic_pstreambuf<C,T>::int_type + basic_pstreambuf<C,T>::overflow(int_type c) + { + if (!empty_buffer()) + return traits_type::eof(); + else if (!traits_type::eq_int_type(c, traits_type::eof())) + return this->sputc(c); + else + return traits_type::not_eof(c); + } + + + template <typename C, typename T> + int + basic_pstreambuf<C,T>::sync() + { + return !exited() && empty_buffer() ? 0 : -1; + } + + /** + * @param s character buffer. + * @param n buffer length. + * @return the number of characters written. + */ + template <typename C, typename T> + std::streamsize + basic_pstreambuf<C,T>::xsputn(const char_type* s, std::streamsize n) + { + if (n < this->epptr() - this->pptr()) + { + traits_type::copy(this->pptr(), s, n); + this->pbump(n); + return n; + } + else + { + for (std::streamsize i = 0; i < n; ++i) + { + if (traits_type::eq_int_type(this->sputc(s[i]), traits_type::eof())) + return i; + } + return n; + } + } + + /** + * @return true if the buffer was emptied, false otherwise. + */ + template <typename C, typename T> + bool + basic_pstreambuf<C,T>::empty_buffer() + { + const std::streamsize count = this->pptr() - this->pbase(); + if (count > 0) + { + const std::streamsize written = this->write(this->wbuffer_, count); + if (written > 0) + { + if (const std::streamsize unwritten = count - written) + traits_type::move(this->pbase(), this->pbase()+written, unwritten); + this->pbump(-written); + return true; + } + } + return false; + } + + /** + * Called when the internal character buffer is is empty, to re-fill it + * from the pipe. + * + * @return The first available character in the buffer, + * or @c traits_type::eof() in case of failure. + */ + template <typename C, typename T> + typename basic_pstreambuf<C,T>::int_type + basic_pstreambuf<C,T>::underflow() + { + if (this->gptr() < this->egptr() || fill_buffer()) + return traits_type::to_int_type(*this->gptr()); + else + return traits_type::eof(); + } + + /** + * Attempts to make @a c available as the next character to be read by + * @c sgetc(). + * + * @param c a character to make available for extraction. + * @return @a c if the character can be made available, + * @c traits_type::eof() otherwise. + */ + template <typename C, typename T> + typename basic_pstreambuf<C,T>::int_type + basic_pstreambuf<C,T>::pbackfail(int_type c) + { + if (this->gptr() != this->eback()) + { + this->gbump(-1); + if (!traits_type::eq_int_type(c, traits_type::eof())) + *this->gptr() = traits_type::to_char_type(c); + return traits_type::not_eof(c); + } + else + return traits_type::eof(); + } + + template <typename C, typename T> + std::streamsize + basic_pstreambuf<C,T>::showmanyc() + { + int avail = 0; + if (sizeof(char_type) == 1) + avail = fill_buffer(true) ? this->egptr() - this->gptr() : -1; +#ifdef FIONREAD + else + { + if (::ioctl(rpipe(), FIONREAD, &avail) == -1) + avail = -1; + else if (avail) + avail /= sizeof(char_type); + } +#endif + return std::streamsize(avail); + } + + /** + * @return true if the buffer was filled, false otherwise. + */ + template <typename C, typename T> + bool + basic_pstreambuf<C,T>::fill_buffer(bool non_blocking) + { + const std::streamsize pb1 = this->gptr() - this->eback(); + const std::streamsize pb2 = pbsz; + const std::streamsize npb = std::min(pb1, pb2); + + char_type* const rbuf = rbuffer(); + + traits_type::move(rbuf + pbsz - npb, this->gptr() - npb, npb); + + std::streamsize rc = -1; + + if (non_blocking) + { + const int flags = ::fcntl(rpipe(), F_GETFL); + if (flags != -1) + { + const bool blocking = !(flags & O_NONBLOCK); + if (blocking) + ::fcntl(rpipe(), F_SETFL, flags | O_NONBLOCK); // set non-blocking + + error_ = 0; + rc = read(rbuf + pbsz, bufsz - pbsz); + + if (rc == -1 && error_ == EAGAIN) // nothing available + rc = 0; + else if (rc == 0) // EOF + rc = -1; + + if (blocking) + ::fcntl(rpipe(), F_SETFL, flags); // restore + } + } + else + rc = read(rbuf + pbsz, bufsz - pbsz); + + if (rc > 0 || (rc == 0 && non_blocking)) + { + this->setg( rbuf + pbsz - npb, + rbuf + pbsz, + rbuf + pbsz + rc ); + return true; + } + else + { + this->setg(NULL, NULL, NULL); + return false; + } + } + + /** + * Writes up to @a n characters to the pipe from the buffer @a s. + * + * @param s character buffer. + * @param n buffer length. + * @return the number of characters written. + */ + template <typename C, typename T> + inline std::streamsize + basic_pstreambuf<C,T>::write(const char_type* s, std::streamsize n) + { + std::streamsize nwritten = 0; + if (wpipe() >= 0) + { + nwritten = ::write(wpipe(), s, n * sizeof(char_type)); + if (nwritten == -1) + error_ = errno; + else + nwritten /= sizeof(char_type); + } + return nwritten; + } + + /** + * Reads up to @a n characters from the pipe to the buffer @a s. + * + * @param s character buffer. + * @param n buffer length. + * @return the number of characters read. + */ + template <typename C, typename T> + inline std::streamsize + basic_pstreambuf<C,T>::read(char_type* s, std::streamsize n) + { + std::streamsize nread = 0; + if (rpipe() >= 0) + { + nread = ::read(rpipe(), s, n * sizeof(char_type)); + if (nread == -1) + error_ = errno; + else + nread /= sizeof(char_type); + } + return nread; + } + + /** @return a reference to the output file descriptor */ + template <typename C, typename T> + inline typename basic_pstreambuf<C,T>::fd_type& + basic_pstreambuf<C,T>::wpipe() + { + return wpipe_; + } + + /** @return a reference to the active input file descriptor */ + template <typename C, typename T> + inline typename basic_pstreambuf<C,T>::fd_type& + basic_pstreambuf<C,T>::rpipe() + { + return rpipe_[rsrc_]; + } + + /** @return a reference to the specified input file descriptor */ + template <typename C, typename T> + inline typename basic_pstreambuf<C,T>::fd_type& + basic_pstreambuf<C,T>::rpipe(buf_read_src which) + { + return rpipe_[which]; + } + + /** @return a pointer to the start of the active input buffer area. */ + template <typename C, typename T> + inline typename basic_pstreambuf<C,T>::char_type* + basic_pstreambuf<C,T>::rbuffer() + { + return rbuffer_[rsrc_]; + } + + + /* + * member definitions for pstream_common + */ + + /** + * @class pstream_common + * Abstract Base Class providing common functionality for basic_ipstream, + * basic_opstream and basic_pstream. + * pstream_common manages the basic_pstreambuf stream buffer that is used + * by the derived classes to initialise an iostream class. + */ + + /** Creates an uninitialised stream. */ + template <typename C, typename T> + inline + pstream_common<C,T>::pstream_common() + : std::basic_ios<C,T>(NULL) + , command_() + , buf_() + { + this->init(&buf_); + } + + /** + * Initialises the stream buffer by calling + * do_open( @a command , @a mode ) + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, pmode) + */ + template <typename C, typename T> + inline + pstream_common<C,T>::pstream_common(const std::string& command, pmode mode) + : std::basic_ios<C,T>(NULL) + , command_(command) + , buf_() + { + this->init(&buf_); + do_open(command, mode); + } + + /** + * Initialises the stream buffer by calling + * do_open( @a file , @a argv , @a mode ) + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see do_open(const std::string&, const argv_type&, pmode) + */ + template <typename C, typename T> + inline + pstream_common<C,T>::pstream_common( const std::string& file, + const argv_type& argv, + pmode mode ) + : std::basic_ios<C,T>(NULL) + , command_(file) + , buf_() + { + this->init(&buf_); + do_open(file, argv, mode); + } + + /** + * This is a pure virtual function to make @c pstream_common abstract. + * Because it is the destructor it will be called by derived classes + * and so must be defined. It is also protected, to discourage use of + * the PStreams classes through pointers or references to the base class. + * + * @sa If defining a pure virtual seems odd you should read + * http://www.gotw.ca/gotw/031.htm (and the rest of the site as well!) + */ + template <typename C, typename T> + inline + pstream_common<C,T>::~pstream_common() + { + } + + /** + * Calls rdbuf()->open( @a command , @a mode ) + * and sets @c failbit on error. + * + * @param command a string containing a shell command. + * @param mode the I/O mode to use when opening the pipe. + * @see basic_pstreambuf::open(const std::string&, pmode) + */ + template <typename C, typename T> + inline void + pstream_common<C,T>::do_open(const std::string& command, pmode mode) + { + if (!buf_.open((command_=command), mode)) + this->setstate(std::ios_base::failbit); + } + + /** + * Calls rdbuf()->open( @a file, @a argv, @a mode ) + * and sets @c failbit on error. + * + * @param file a string containing the pathname of a program to execute. + * @param argv a vector of argument strings passed to the new program. + * @param mode the I/O mode to use when opening the pipe. + * @see basic_pstreambuf::open(const std::string&, const argv_type&, pmode) + */ + template <typename C, typename T> + inline void + pstream_common<C,T>::do_open( const std::string& file, + const argv_type& argv, + pmode mode ) + { + if (!buf_.open((command_=file), argv, mode)) + this->setstate(std::ios_base::failbit); + } + + /** Calls rdbuf->close() and sets @c failbit on error. */ + template <typename C, typename T> + inline void + pstream_common<C,T>::close() + { + if (!buf_.close()) + this->setstate(std::ios_base::failbit); + } + + /** + * @return rdbuf()->is_open(). + * @see basic_pstreambuf::is_open() + */ + template <typename C, typename T> + inline bool + pstream_common<C,T>::is_open() const + { + return buf_.is_open(); + } + + /** @return a string containing the command used to initialise the stream. */ + template <typename C, typename T> + inline const std::string& + pstream_common<C,T>::command() const + { + return command_; + } + + /** @return a pointer to the private stream buffer member. */ + // TODO document behaviour if buffer replaced. + template <typename C, typename T> + inline typename pstream_common<C,T>::streambuf_type* + pstream_common<C,T>::rdbuf() const + { + return const_cast<streambuf_type*>(&buf_); + } + + +#if REDI_EVISCERATE_PSTREAMS + /** + * @def REDI_EVISCERATE_PSTREAMS + * If this macro has a non-zero value then certain internals of the + * @c basic_pstreambuf template class are exposed. In general this is + * a Bad Thing, as the internal implementation is largely undocumented + * and may be subject to change at any time, so this feature is only + * provided because it might make PStreams useful in situations where + * it is necessary to do Bad Things. + */ + + /** + * @warning This function exposes the internals of the stream buffer and + * should be used with caution. It is the caller's responsibility + * to flush streams etc. in order to clear any buffered data. + * The POSIX.1 function <b>fdopen</b>(3) is used to obtain the + * @c FILE pointers from the streambuf's private file descriptor + * members so consult your system's documentation for + * <b>fdopen</b>(3). + * + * @param in A FILE* that will refer to the process' stdin. + * @param out A FILE* that will refer to the process' stdout. + * @param err A FILE* that will refer to the process' stderr. + * @return An OR of zero or more of @c pstdin, @c pstdout, @c pstderr. + * + * For each open stream shared with the child process a @c FILE* is + * obtained and assigned to the corresponding parameter. For closed + * streams @c NULL is assigned to the parameter. + * The return value can be tested to see which parameters should be + * @c !NULL by masking with the corresponding @c pmode value. + * + * @see <b>fdopen</b>(3) + */ + template <typename C, typename T> + std::size_t + basic_pstreambuf<C,T>::fopen(FILE*& in, FILE*& out, FILE*& err) + { + in = out = err = NULL; + std::size_t open_files = 0; + if (wpipe() > -1) + { + if ((in = ::fdopen(wpipe(), "w"))) + { + open_files |= pstdin; + } + } + if (rpipe(rsrc_out) > -1) + { + if ((out = ::fdopen(rpipe(rsrc_out), "r"))) + { + open_files |= pstdout; + } + } + if (rpipe(rsrc_err) > -1) + { + if ((err = ::fdopen(rpipe(rsrc_err), "r"))) + { + open_files |= pstderr; + } + } + return open_files; + } + + /** + * @warning This function exposes the internals of the stream buffer and + * should be used with caution. + * + * @param in A FILE* that will refer to the process' stdin. + * @param out A FILE* that will refer to the process' stdout. + * @param err A FILE* that will refer to the process' stderr. + * @return A bitwise-or of zero or more of @c pstdin, @c pstdout, @c pstderr. + * @see basic_pstreambuf::fopen() + */ + template <typename C, typename T> + inline std::size_t + pstream_common<C,T>::fopen(FILE*& fin, FILE*& fout, FILE*& ferr) + { + return buf_.fopen(fin, fout, ferr); + } + +#endif // REDI_EVISCERATE_PSTREAMS + + +} // namespace redi + +/** + * @mainpage PStreams Reference + * @htmlinclude mainpage.html + */ + +#endif // REDI_PSTREAM_H_SEEN + +// vim: ts=2 sw=2 expandtab + diff --git a/plugins/New_GPG/src/main.cpp b/plugins/New_GPG/src/main.cpp index 7282865ba1..5b6acd5a3e 100755 --- a/plugins/New_GPG/src/main.cpp +++ b/plugins/New_GPG/src/main.cpp @@ -27,6 +27,8 @@ int itemnum = 0; HWND hwndList_g = NULL;
BOOL CheckStateStoreDB(HWND hwndDlg, int idCtrl, const char* szSetting);
+TCHAR key_id_global[17] = {0};
+
static INT_PTR CALLBACK DlgProcFirstRun(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
{
HWND hwndList=GetDlgItem(hwndDlg, IDC_KEY_LIST);
@@ -44,6 +46,7 @@ static INT_PTR CALLBACK DlgProcFirstRun(HWND hwndDlg,UINT msg,WPARAM wParam,LPAR SetWindowText(hwndDlg, TranslateT("Set own key"));
EnableWindow(GetDlgItem(hwndDlg, IDC_COPY_PUBKEY), 0);
EnableWindow(GetDlgItem(hwndDlg, IDC_EXPORT_PRIVATE), 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE_PASSWD), 0);
col.pszText = _T("Key ID");
col.mask = LVCF_TEXT | LVCF_WIDTH;
col.fmt = LVCFMT_LEFT;
@@ -178,8 +181,8 @@ static INT_PTR CALLBACK DlgProcFirstRun(HWND hwndDlg,UINT msg,WPARAM wParam,LPAR if(expired)
{
mir_free(key_len);
- mir_free(expire_date);
mir_free(creation_date);
+ mir_free(expire_date);
//mimic normal behaviour
p = out.find("uid ", p);
p2 = out.find_first_not_of(" ", p+5);
@@ -187,15 +190,18 @@ static INT_PTR CALLBACK DlgProcFirstRun(HWND hwndDlg,UINT msg,WPARAM wParam,LPAR p++;
p2 = out.find(">", p);
//
- continue;
+ continue; //does not add to key list
}
}
}
iRow = ListView_InsertItem(hwndList, &item);
ListView_SetItemText(hwndList, iRow, 3, creation_date);
mir_free(creation_date);
- ListView_SetItemText(hwndList, iRow, 4, expire_date);
- mir_free(expire_date);
+ if(expire_date)
+ {
+ ListView_SetItemText(hwndList, iRow, 4, expire_date);
+ mir_free(expire_date);
+ }
ListView_SetItemText(hwndList, iRow, 5, key_len);
mir_free(key_len);
ListView_SetItemText(hwndList, iRow, 0, (TCHAR*)key_id.c_str());
@@ -811,7 +817,40 @@ static INT_PTR CALLBACK DlgProcFirstRun(HWND hwndDlg,UINT msg,WPARAM wParam,LPAR file.close();
}
break;
-
+ case IDC_CHANGE_PASSWD:
+ ListView_GetItemText(hwndList, itemnum, 0, key_id_global, 16);
+// extern void ShowChangePasswdDlg();
+// ShowChangePasswdDlg();
+ //temporary code follows
+ std::vector<std::wstring> cmd;
+ std::string old_pass, new_pass;
+ TCHAR tmp2[MAX_PATH] = {0};
+ string output;
+ DWORD exitcode;
+ cmd.push_back(L"--edit-key");
+ cmd.push_back(key_id_global);
+ cmd.push_back(L"passwd");
+ gpg_execution_params_pass params(cmd, old_pass, new_pass);
+ pxResult result;
+ params.useless = "";
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_passwd_change_thread, ¶ms));
+ if(!gpg_thread.timed_join(boost::posix_time::minutes(10)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": GPG execution timed out, aborted");
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ //
+ break;
}
break;
}
@@ -825,6 +864,7 @@ static INT_PTR CALLBACK DlgProcFirstRun(HWND hwndDlg,UINT msg,WPARAM wParam,LPAR EnableWindow(GetDlgItem(hwndDlg, ID_OK), 1);
EnableWindow(GetDlgItem(hwndDlg, IDC_COPY_PUBKEY), 1);
EnableWindow(GetDlgItem(hwndDlg, IDC_EXPORT_PRIVATE), 1);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE_PASSWD), 1);
itemnum = hdr->iItem;
}
}
diff --git a/plugins/New_GPG/src/resource.h b/plugins/New_GPG/src/resource.h index 38f790f6a1..cd607fb27a 100755 --- a/plugins/New_GPG/src/resource.h +++ b/plugins/New_GPG/src/resource.h @@ -18,6 +18,7 @@ #define IDD_OPT_GPG_ADVANCED 113
#define IDD_ENCRYPTED_FILE_MSG_BOX 114
#define IDD_EXPORT_TYPE 115
+#define IDD_CHANGE_PASSWD 116
#define IDC_SET_BIN_PATH 1016
#define IDC_SET_HOME_DIR 1017
#define IDC_BIN_PATH 1018
@@ -97,14 +98,19 @@ #define IDC_PRIVATE 1074
#define IDC_ALL 1075
#define IDC_EXPORT_PRIVATE 1076
+#define IDC_CHANGE_PASSWD 1077
+#define IDC_OLD_PASSWD 1078
+#define IDC_NEW_PASSWD1 1079
+#define IDC_NEW_PASSWD2 1080
+
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 115
+#define _APS_NEXT_RESOURCE_VALUE 117
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1077
+#define _APS_NEXT_CONTROL_VALUE 1081
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/plugins/New_GPG/src/utilities.cpp b/plugins/New_GPG/src/utilities.cpp index 8f42f0918f..0a43cc4cc7 100755 --- a/plugins/New_GPG/src/utilities.cpp +++ b/plugins/New_GPG/src/utilities.cpp @@ -2202,3 +2202,126 @@ void ShowExportKeysDlg() extern HINSTANCE hInst;
DialogBox(hInst, MAKEINTRESOURCE(IDD_EXPORT_TYPE), NULL, DlgProcExportKeys);
}
+
+static INT_PTR CALLBACK DlgProcChangePasswd(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_OK:
+ //TODO: show some prgress
+ {
+ std::string old_pass, new_pass;
+ extern TCHAR key_id_global[17];
+ TCHAR buf[256] = {0};
+ GetDlgItemText(hwndDlg, IDC_NEW_PASSWD1, buf, 255);
+ new_pass = toUTF8(buf);
+ GetDlgItemText(hwndDlg, IDC_NEW_PASSWD2, buf, 255);
+ if(new_pass != toUTF8(buf))
+ {
+ MessageBox(hwndDlg, TranslateT("New passwords not match"), TranslateT("Error"), MB_OK);
+ //key_id_global[0] = 0;
+ break;
+ }
+ GetDlgItemText(hwndDlg, IDC_OLD_PASSWD, buf, 255);
+ old_pass = toUTF8(buf);
+ bool old_pass_match = false;
+ TCHAR *pass = UniGetContactSettingUtf(NULL, szGPGModuleName, "szKeyPassword", _T(""));
+ if(!_tcscmp(pass,buf))
+ old_pass_match = true;
+ mir_free(pass);
+ if(!old_pass_match)
+ { + if(key_id_global[0]) + { + string dbsetting = "szKey_"; + dbsetting += toUTF8(key_id_global); + dbsetting += "_Password"; + pass = UniGetContactSettingUtf(NULL, szGPGModuleName, dbsetting.c_str(), _T("")); + if(!_tcscmp(pass,buf)) + old_pass_match = true; + mir_free(pass); + } + }
+ if(!old_pass_match)
+ {
+ if(MessageBox(hwndDlg, TranslateT("Old password not match, you can continue, but gpg will reject wrong password.\nDo you want to continue?"), TranslateT("Error"), MB_YESNO) == IDNO)
+ {
+ //key_id_global[0] = 0;
+ break;
+ }
+ }
+ std::vector<std::wstring> cmd;
+ TCHAR tmp2[MAX_PATH] = {0};
+ string output;
+ DWORD exitcode;
+ cmd.push_back(L"--edit-key");
+ cmd.push_back(key_id_global);
+ cmd.push_back(L"passwd");
+ gpg_execution_params_pass params(cmd, old_pass, new_pass);
+ pxResult result;
+ params.useless = "";
+ params.out = &output;
+ params.code = &exitcode;
+ params.result = &result;
+ boost::thread gpg_thread(boost::bind(&pxEexcute_passwd_change_thread, ¶ms));
+ if(!gpg_thread.timed_join(boost::posix_time::seconds(100)))
+ {
+ gpg_thread.~thread();
+ TerminateProcess(params.hProcess, 1);
+ params.hProcess = NULL;
+ if(bDebugLog)
+ debuglog<<std::string(time_str()+": GPG execution timed out, aborted");
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ if(result == pxNotFound)
+ break;
+ //if(result == pxSuccess)
+ //TODO: save to db
+
+
+ }
+ DestroyWindow(hwndDlg);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ {
+ extern TCHAR key_id_global[17];
+ key_id_global[0] = 0;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void ShowChangePasswdDlg()
+{
+ extern HINSTANCE hInst;
+ HWND hwndPaaswdDlg = NULL;
+ hwndPaaswdDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_CHANGE_PASSWD), NULL, DlgProcChangePasswd);
+ SetForegroundWindow(hwndPaaswdDlg);
+}
|