summaryrefslogtreecommitdiff
path: root/plugins/New_GPG/src/include/libs/process
diff options
context:
space:
mode:
authorAlexander Gluzsky <sss123next@list.ru>2013-02-03 12:54:02 +0000
committerAlexander Gluzsky <sss123next@list.ru>2013-02-03 12:54:02 +0000
commit2637b7479c3e531f891346dbe84c73805a8b5e36 (patch)
treebdfe96ed34c5f08b856fa760c2cdc70ba6763352 /plugins/New_GPG/src/include/libs/process
parent32e17cfa965980f07e8321fb29d38d62a2e1ad27 (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
Diffstat (limited to 'plugins/New_GPG/src/include/libs/process')
-rw-r--r--plugins/New_GPG/src/include/libs/process/doc/Jamfile.jam31
-rw-r--r--plugins/New_GPG/src/include/libs/process/doc/acknowledgements.qbk9
-rw-r--r--plugins/New_GPG/src/include/libs/process/doc/faq.qbk124
-rw-r--r--plugins/New_GPG/src/include/libs/process/doc/introduction.qbk18
-rw-r--r--plugins/New_GPG/src/include/libs/process/doc/posix.qbk40
-rw-r--r--plugins/New_GPG/src/include/libs/process/doc/process.qbk20
-rw-r--r--plugins/New_GPG/src/include/libs/process/doc/tutorial.qbk219
-rw-r--r--plugins/New_GPG/src/include/libs/process/doc/windows.qbk33
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/Jamfile.jam33
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/args.cpp27
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/async_io.cpp65
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/cleanup.cpp37
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/cmd_line.cpp23
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/env.cpp23
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/error_handling.cpp32
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/execute.cpp25
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/intro.cpp20
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/posix.cpp68
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/streams.cpp36
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/sync_io.cpp35
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/terminate.cpp21
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/wait.cpp62
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/windows.cpp35
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/windows_unicode.cpp27
-rw-r--r--plugins/New_GPG/src/include/libs/process/example/work_dir.cpp32
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/Jamfile.jam57
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/bind_stderr.cpp144
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/bind_stdin.cpp165
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/bind_stdin_stdout.cpp62
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/bind_stdout.cpp144
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/bind_stdout_stderr.cpp131
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/close_stderr.cpp42
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/close_stdin.cpp42
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/close_stdout.cpp42
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/exit_code.cpp106
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/extensions.cpp65
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/inherit_env.cpp58
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/posix_specific.cpp113
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/run_exe.cpp39
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/run_exe_path.cpp46
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/run_exe_wstring.cpp46
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/search_path.cpp34
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/search_path_wstring.cpp25
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/set_args.cpp83
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/set_args_wstring.cpp56
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/set_cmd_line.cpp50
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/set_cmd_line_wstring.cpp54
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/set_env.cpp57
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/set_env_wstring.cpp61
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/set_on_error.cpp27
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/shell_path.cpp29
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/shell_path_wstring.cpp31
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/show_window.cpp49
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/sparring_partner.cpp232
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/start_in_dir.cpp63
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/start_in_dir_wstring.cpp67
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/terminate.cpp48
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/throw_on_error.cpp28
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/wait.cpp71
-rw-r--r--plugins/New_GPG/src/include/libs/process/test/windows_specific.cpp53
60 files changed, 3515 insertions, 0 deletions
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);
+}