$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r62520 - in sandbox/SOC/2010/process: boost/process boost/process/detail libs/process/example
From: boris_at_[hidden]
Date: 2010-06-07 16:43:14
Author: bschaeling
Date: 2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
New Revision: 62520
URL: http://svn.boost.org/trac/boost/changeset/62520
Log:
Made stream behaviors types (instead of enum values)
Text files modified: 
   sandbox/SOC/2010/process/boost/process/child.hpp                |   127 +++++++++++++++++++++                   
   sandbox/SOC/2010/process/boost/process/config.hpp               |    29 ++++                                    
   sandbox/SOC/2010/process/boost/process/context.hpp              |    28 ++--                                    
   sandbox/SOC/2010/process/boost/process/detail/file_handle.hpp   |    10                                         
   sandbox/SOC/2010/process/boost/process/detail/win32_helpers.hpp |     2                                         
   sandbox/SOC/2010/process/boost/process/operations.hpp           |    98 ++++++++++++++--                        
   sandbox/SOC/2010/process/boost/process/stream_behavior.hpp      |   228 +++++++++++++++++++++++++++++++++++++++ 
   sandbox/SOC/2010/process/libs/process/example/child_stdout.cpp  |     9 +                                       
   8 files changed, 490 insertions(+), 41 deletions(-)
Modified: sandbox/SOC/2010/process/boost/process/child.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/child.hpp	(original)
+++ sandbox/SOC/2010/process/boost/process/child.hpp	2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -22,10 +22,15 @@
 #include <boost/process/config.hpp>
 
 #if defined(BOOST_POSIX_API)
+#   include <boost/process/detail/pipe.hpp>
+#   include <boost/process/detail/posix_ops.hpp>
+#   include <boost/process/detail/stream_info.hpp>
+#   include <map>
+#   include <unistd.h>
 #elif defined(BOOST_WINDOWS_API)
-#  include <windows.h>
+#   include <windows.h>
 #else
-#  error "Unsupported platform." 
+#   error "Unsupported platform." 
 #endif
 
 #include <boost/process/process.hpp>
@@ -149,6 +154,124 @@
      */ 
     boost::shared_ptr<void> process_handle_; 
 #endif 
+
+#if defined(BOOST_POSIX_API) 
+public:
+    /**
+     * Gets a reference to the child's input stream \a desc.
+     *
+     * Returns a reference to a postream object that represents one of
+     * the multiple input communication channels with the child process.
+     * The channel is identified by \a desc as seen from the child's
+     * point of view. The parent can use the returned stream to send
+     * data to the child.
+     *
+     * Giving this function the STDIN_FILENO constant (defined in
+     * unistd.h) is a synonym for the get_stdin() call inherited from
+     * child.
+     */
+    postream &get_input(int desc) const
+    {
+        if (desc == STDIN_FILENO)
+            return posix_child::get_stdin();
+        else
+        {
+            input_map_t::const_iterator it = input_map_.find(desc);
+            BOOST_ASSERT(it != input_map_.end());
+            return *it->second;
+        }
+    }
+
+    /**
+     * Gets a reference to the child's output stream \a desc.
+     *
+     * Returns a reference to a pistream object that represents one of
+     * the multiple output communication channels with the child process.
+     * The channel is identified by \a desc as seen from the child's
+     * point of view. The parent can use the returned stream to retrieve
+     * data from the child.
+     *
+     * Giving this function the STDOUT_FILENO or STDERR_FILENO constants
+     * (both defined in unistd.h) are synonyms for the get_stdout() and
+     * get_stderr() calls inherited from child, respectively.
+     */
+    pistream &get_output(int desc) const
+    {
+        if (desc == STDOUT_FILENO)
+            return posix_child::get_stdout();
+        else if (desc == STDERR_FILENO)
+            return posix_child::get_stderr();
+        else
+        {
+            output_map_t::const_iterator it = output_map_.find(desc);
+            BOOST_ASSERT(it != output_map_.end());
+            return *it->second;
+        }
+    }
+
+    /**
+     * Creates a new child object on a POSIX platform.
+     *
+     * The \a infoin and \a infoout maps contain the pipes used to handle
+     * the redirections of the child process; at the moment, no other
+     * stream_info types are supported. If the launcher was asked to
+     * redirect any of the three standard flows, their pipes must be
+     * present in these maps.
+     */
+    child(id_type id, detail::info_map &infoin, detail::info_map &infoout)
+        : child(id,
+        detail::posix_info_locate_pipe(infoin, STDIN_FILENO, false),
+        detail::posix_info_locate_pipe(infoout, STDOUT_FILENO, true),
+        detail::posix_info_locate_pipe(infoout, STDERR_FILENO, true))
+    {
+        for (detail::info_map::iterator it = infoin.begin();
+                it != infoin.end(); ++it)
+        {
+            detail::stream_info &si = it->second;
+            if (si.type_ == detail::stream_info::use_pipe)
+            {
+                BOOST_ASSERT(si.pipe_->wend().valid());
+                boost::shared_ptr<postream> st(new postream(si.pipe_->wend()));
+                input_map_.insert(input_map_t::value_type(it->first, st));
+            }
+        }
+
+        for (detail::info_map::iterator it = infoout.begin();
+                it != infoout.end(); ++it)
+        {
+            detail::stream_info &si = it->second;
+            if (si.type_ == detail::stream_info::use_pipe)
+            {
+                BOOST_ASSERT(si.pipe_->rend().valid());
+                boost::shared_ptr<pistream> st(new pistream(si.pipe_->rend()));
+                output_map_.insert(output_map_t::value_type(it->first, st));
+            }
+        }
+    }
+
+private:
+    /**
+     * Maps child's file descriptors to postream objects.
+     */
+    typedef std::map<int, boost::shared_ptr<postream> > input_map_t;
+
+    /**
+     * Contains all relationships between child's input file
+     * descriptors and their corresponding postream objects.
+     */
+    input_map_t input_map_;
+
+    /**
+     * Maps child's file descriptors to pistream objects.
+     */
+    typedef std::map<int, boost::shared_ptr<pistream> > output_map_t;
+
+    /**
+     * Contains all relationships between child's output file
+     * descriptors and their corresponding pistream objects.
+     */
+    output_map_t output_map_;
+#endif 
 };
 
 /**
Modified: sandbox/SOC/2010/process/boost/process/config.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/config.hpp	(original)
+++ sandbox/SOC/2010/process/boost/process/config.hpp	2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -3,6 +3,7 @@
 // ~~~~~~~~~~~~~
 //
 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov
 // Copyright (c) 2008, 2009 Boris Schaeling
 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
 //
@@ -22,9 +23,16 @@
 
 #include <boost/config.hpp>
 #include <boost/system/config.hpp>
+#include <boost/preprocessor/stringize.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/throw_exception.hpp>
+
+#if defined(BOOST_WINDOWS_API)
+#   include <windows.h> 
+#endif 
 
 #if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
-#  if !defined(BOOST_PROCESS_POSIX_PATH_MAX)
+#   if !defined(BOOST_PROCESS_POSIX_PATH_MAX)
 /**
  * The macro BOOST_PROCESS_POSIX_PATH_MAX is set to a positive integer
  * value which specifies the system's maximal supported path length.
@@ -34,8 +42,23 @@
  * constructor of context tries to find out the maximal supported path 
  * length but uses BOOST_PROCESS_POSIX_PATH_MAX if it fails.
  */
-#    define BOOST_PROCESS_POSIX_PATH_MAX 259
-#  endif
+#       define BOOST_PROCESS_POSIX_PATH_MAX 259
+#   endif
 #endif
 
+#define BOOST_PROCESS_SOURCE_LOCATION \
+    "in file '" __FILE__ "', line " BOOST_PP_STRINGIZE(__LINE__) ": "
+
+#if defined(BOOST_POSIX_API)
+#   define BOOST_PROCESS_LAST_ERROR errno
+#elif defined(BOOST_WINDOWS_API)
+#   define BOOST_PROCESS_LAST_ERROR ::GetLastError()
+#endif
+
+#define BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(what) \
+    boost::throw_exception(boost::system::system_error( \
+        boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \
+                                  boost::system::get_system_category()), \
+        BOOST_PROCESS_SOURCE_LOCATION what))
+
 #endif
Modified: sandbox/SOC/2010/process/boost/process/context.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/context.hpp	(original)
+++ sandbox/SOC/2010/process/boost/process/context.hpp	2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -22,6 +22,8 @@
 #include <boost/process/stream_behavior.hpp>
 #include <boost/process/environment.hpp>
 #include <boost/process/self.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
 
 namespace boost {
 namespace process {
@@ -31,9 +33,9 @@
  */
 struct context
 {
-    stream_behavior stdin_behavior;
-    stream_behavior stdout_behavior;
-    stream_behavior stderr_behavior;
+    boost::shared_ptr<stream_behavior> stdin_behavior;
+    boost::shared_ptr<stream_behavior> stdout_behavior;
+    boost::shared_ptr<stream_behavior> stderr_behavior;
     std::string process_name;
     std::string work_dir;
     environment_t environment;
@@ -45,23 +47,21 @@
      * and environment variables. 
      */ 
     context() 
-        : stdin_behavior(inherit), 
-        stdout_behavior(inherit), 
-        stderr_behavior(inherit), 
+#if defined(BOOST_POSIX_API) 
+        : stdin_behavior(boost::make_shared<inherit>(inherit(STDIN_FILENO))), 
+        stdout_behavior(boost::make_shared<inherit>(inherit(STDOUT_FILENO))), 
+        stderr_behavior(boost::make_shared<inherit>(inherit(STDERR_FILENO))), 
+#elif defined(BOOST_WINDOWS_API) 
+        : stdin_behavior(boost::make_shared<inherit>(inherit(::GetStdHandle(STD_INPUT_HANDLE)))), 
+        stdout_behavior(boost::make_shared<inherit>(inherit(::GetStdHandle(STD_OUTPUT_HANDLE)))), 
+        stderr_behavior(boost::make_shared<inherit>(inherit(::GetStdHandle(STD_ERROR_HANDLE)))), 
+#endif 
         work_dir(self::get_work_dir()), 
         environment(self::get_environment()) 
     {
     }
 };
 
-/** 
- * Default context object. 
- * 
- * The default context object is used when child processes are created 
- * without defining a context explicitly. 
- */
-const context default_context; 
-
 }
 }
 
Modified: sandbox/SOC/2010/process/boost/process/detail/file_handle.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/file_handle.hpp	(original)
+++ sandbox/SOC/2010/process/boost/process/detail/file_handle.hpp	2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -23,12 +23,12 @@
 #include <boost/process/config.hpp>
 
 #if defined(BOOST_POSIX_API)
-#  include <cerrno>
-#  include <unistd.h>
+#   include <cerrno>
+#   include <unistd.h>
 #elif defined(BOOST_WINDOWS_API)
-#  include <windows.h>
+#   include <windows.h>
 #else
-#  error "Unsupported platform." 
+#   error "Unsupported platform." 
 #endif
 
 #include <boost/assert.hpp>
@@ -108,7 +108,7 @@
     file_handle(handle_type h)
         : handle_(h)
     {
-        BOOST_ASSERT(handle_ != invalid_value());
+        // BOOST_ASSERT(handle_ != invalid_value());
     }
 
     /**
Modified: sandbox/SOC/2010/process/boost/process/detail/win32_helpers.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/win32_helpers.hpp	(original)
+++ sandbox/SOC/2010/process/boost/process/detail/win32_helpers.hpp	2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -141,6 +141,7 @@
  * It recieves stream_detail from that stream and return a file_handle
  * that contains the handle to the stream.
  */
+/*
 inline file_handle configure_win32_stream(stream_detail &sd)
 {
     file_handle return_handle;
@@ -198,6 +199,7 @@
 
     return return_handle;
 }
+*/
 
 }
 }
Modified: sandbox/SOC/2010/process/boost/process/operations.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/operations.hpp	(original)
+++ sandbox/SOC/2010/process/boost/process/operations.hpp	2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -22,19 +22,19 @@
 #include <boost/process/config.hpp>
 
 #if defined(BOOST_POSIX_API)
-#  include <boost/process/detail/posix_helpers.hpp>
-#  include <stdlib.h>
-#  include <unistd.h>
-#  if defined(__CYGWIN__)
-#    include <boost/scoped_array.hpp>
-#    include <sys/cygwin.h>
-#  endif
+#   include <boost/process/detail/posix_helpers.hpp>
+#   include <stdlib.h>
+#   include <unistd.h>
+#   if defined(__CYGWIN__)
+#       include <boost/scoped_array.hpp>
+#       include <sys/cygwin.h>
+#   endif
 #elif defined(BOOST_WINDOWS_API)
-#  include <boost/process/detail/win32_helpers.hpp>
-#  include <boost/algorithm/string/predicate.hpp>
-#  include <windows.h>
+#   include <boost/process/detail/win32_helpers.hpp>
+#   include <boost/algorithm/string/predicate.hpp>
+#   include <windows.h>
 #else
-#  error "Unsupported platform."
+#   error "Unsupported platform."
 #endif
 
 #include <boost/process/child.hpp>
@@ -174,7 +174,7 @@
  * \return A handle to the new child process.
  */
 template <class Arguments>
-inline child create_child(const std::string &executable, Arguments args, context ctx = default_context)
+inline child create_child(const std::string &executable, Arguments args, context ctx = context())
 {
     /*
      * BEHAVIOR | BEFORE fork/CreateProcess        | AFTER fork/CreateProcess 
@@ -190,6 +190,77 @@
      * close    |                                  | POSIX: close explicitly 
      */
 
+    std::string p_name = ctx.process_name.empty() ? executable : ctx.process_name; 
+    args.insert(args.begin(), p_name); 
+
+#if defined(BOOST_POSIX_API)
+    child::id_type pid = ::fork();
+
+    if (pid == -1)
+        BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fork(2) failed"); 
+
+    if (pid == 0) 
+    { 
+        std::pair<std::size_t, char**> argcv = detail::collection_to_posix_argv(args);
+        char **envp = detail::environment_to_envp(ctx.environment);
+        ::execve(executable.c_str(), argcv.second, envp);
+
+        boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::create_child: execve(2) failed"); 
+
+        for (std::size_t i = 0; i < argcv.first; ++i) 
+            delete[] argcv.second[i]; 
+        delete[] argcv.second; 
+
+        for (std::size_t i = 0; i < env.size(); ++i) 
+            delete[] envp[i]; 
+        delete[] envp; 
+
+        ::write(STDERR_FILENO, e.what(), std::strlen(e.what())); 
+        ::write(STDERR_FILENO, "\n", 1); 
+        std::exit(EXIT_FAILURE); 
+    } 
+
+    BOOST_ASSERT(pid > 0);
+
+    return child(pid, 
+        detail::file_handle(ctx.stdin_behavior->get_parent_end()), 
+        detail::file_handle(ctx.stdout_behavior->get_parent_end()), 
+        detail::file_handle(ctx.stderr_behavior->get_parent_end())); 
+#elif defined(BOOST_WINDOWS_API)
+    STARTUPINFOA startup_info;
+    ::ZeroMemory(&startup_info, sizeof(startup_info));
+    startup_info.cb = sizeof(startup_info);
+    startup_info.dwFlags |= STARTF_USESTDHANDLES;
+    startup_info.hStdInput = ctx.stdin_behavior->get_child_end();
+    startup_info.hStdOutput = ctx.stdout_behavior->get_child_end();
+    startup_info.hStdError = ctx.stderr_behavior->get_child_end();
+
+    PROCESS_INFORMATION pi;
+    ::ZeroMemory(&pi, sizeof(pi));
+
+    boost::shared_array<char> cmdline = detail::collection_to_win32_cmdline(args);
+
+    boost::scoped_array<char> exe(new char[executable.size() + 1]);
+    ::strcpy_s(exe.get(), executable.size() + 1, executable.c_str());
+
+    boost::scoped_array<char> workdir(new char[ctx.work_dir.size() + 1]);
+    ::strcpy_s(workdir.get(), ctx.work_dir.size() + 1, ctx.work_dir.c_str());
+
+    boost::shared_array<char> envstrs = detail::environment_to_win32_strings(ctx.environment);
+
+    if (::CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, 0, envstrs.get(), workdir.get(), &startup_info, &pi) == 0)
+        BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed"); 
+
+    if (!::CloseHandle(pi.hThread))
+        BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed"); 
+
+    return child(pi.dwProcessId, 
+        detail::file_handle(ctx.stdin_behavior->get_parent_end()), 
+        detail::file_handle(ctx.stdout_behavior->get_parent_end()), 
+        detail::file_handle(ctx.stderr_behavior->get_parent_end()), 
+        detail::file_handle(pi.hProcess)); 
+#endif 
+    /*
     detail::file_handle fhstdin, fhstdout, fhstderr;
 
     //start structures that represents a std stream.
@@ -319,9 +390,10 @@
 
     return child(pi.dwProcessId, fhstdin, fhstdout, fhstderr, detail::file_handle(pi.hProcess));
 #endif
+    */
 }
 
-inline child create_child(const std::string &executable, context ctx = default_context)
+inline child create_child(const std::string &executable, context ctx = context())
 {
     return create_child(executable, std::vector<std::string>(), ctx); 
 }
Modified: sandbox/SOC/2010/process/boost/process/stream_behavior.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/stream_behavior.hpp	(original)
+++ sandbox/SOC/2010/process/boost/process/stream_behavior.hpp	2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -22,6 +22,16 @@
 
 #include <boost/process/config.hpp>
 
+#if defined(BOOST_POSIX_API) 
+#   include <sys/stat.h>
+#   include <fcntl.h>
+#   include <unistd.h>
+#elif defined(BOOST_WINDOWS_API) 
+#   include <boost/lexical_cast.hpp> 
+#   include <string> 
+#   include <windows.h> 
+#endif 
+
 namespace boost {
 namespace process {
 
@@ -35,7 +45,223 @@
  * close: A stream is closed. 
  *
  */
-enum stream_behavior { inherit, capture, mute, close }; 
+// enum stream_behavior { inherit, capture, mute, close }; 
+
+class stream_behavior 
+{ 
+public: 
+#if defined(BOOST_POSIX_API) 
+    typedef int native_type; 
+#elif defined(BOOST_WINDOWS_API) 
+    typedef HANDLE native_type; 
+#endif 
+
+    virtual native_type get_child_end() const 
+    { 
+#if defined(BOOST_POSIX_API) 
+        return -1; 
+#elif defined(BOOST_WINDOWS_API) 
+        return INVALID_HANDLE_VALUE; 
+#endif 
+    } 
+
+    virtual native_type get_parent_end() const 
+    { 
+#if defined(BOOST_POSIX_API) 
+        return -1; 
+#elif defined(BOOST_WINDOWS_API) 
+        return INVALID_HANDLE_VALUE; 
+#endif 
+    } 
+}; 
+
+typedef stream_behavior close; 
+
+class inherit : public stream_behavior 
+{ 
+public: 
+    inherit(native_type child_end) 
+    : child_end_(child_end) 
+    { 
+#if defined(BOOST_WINDOWS_API) 
+        if (!::DuplicateHandle(::GetCurrentProcess(), child_end_, ::GetCurrentProcess(), &child_end_, 0, TRUE, DUPLICATE_SAME_ACCESS)) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("DuplicateHandle() failed"); 
+#endif 
+    } 
+
+    native_type get_child_end() const 
+    { 
+        return child_end_; 
+    } 
+
+private: 
+    native_type child_end_; 
+}; 
+
+class capture : public stream_behavior 
+{ 
+public: 
+    enum stream_type { input_stream, output_stream }; 
+
+    capture(stream_type stream) 
+    { 
+        native_type natives[2]; 
+#if defined(BOOST_POSIX_API) 
+        if (::pipe(natives) == -1) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pipe(2) failed"); 
+#elif defined(BOOST_WINDOWS_API) 
+        SECURITY_ATTRIBUTES sa;
+        ZeroMemory(&sa, sizeof(sa));
+        sa.nLength = sizeof(sa);
+        sa.lpSecurityDescriptor = NULL;
+        sa.bInheritHandle = TRUE;
+        if (!::CreatePipe(&natives[0], &natives[1], &sa, 0)) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed"); 
+#endif 
+        child_end_ = natives[(stream == input_stream) ? 0 : 1]; 
+        parent_end_ = natives[(stream == input_stream) ? 1 : 0]; 
+#if defined(BOOST_WINDOWS_API) 
+        if (!::SetHandleInformation(child_end_, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetHandleInformation() failed"); 
+#endif 
+    } 
+
+    native_type get_child_end() const 
+    { 
+        return child_end_; 
+    } 
+
+    native_type get_parent_end() const 
+    { 
+        return parent_end_; 
+    } 
+
+private: 
+    native_type child_end_; 
+    native_type parent_end_; 
+}; 
+
+class capture_with_named_pipe : public stream_behavior 
+{ 
+public: 
+    enum stream_type { input_stream, output_stream }; 
+
+    capture_with_named_pipe(stream_type stream) 
+    { 
+        native_type natives[2]; 
+#if defined(BOOST_POSIX_API) 
+        // TODO: Use RAII to close HANDLEs if an exception is thrown. 
+        if (::mkfifo("/tmp/fifo.1", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("mkfifo(3) failed"); 
+        if (stream == input_stream) 
+        { 
+            child_end_ = ::open("/tmp/fifo.1", O_RDONLY); 
+            if (child_end_ == -1) 
+                BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); 
+            parent_end_ = ::open("/tmp/fifo.1", O_WRONLY); 
+            if (parent_end_ == -1) 
+                BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); 
+        } 
+        else 
+        { 
+            child_end_ = ::open("/tmp/fifo.1", O_WRONLY); 
+            if (child_end_ == -1) 
+                BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); 
+            parent_end_ = ::open("/tmp/fifo.1", O_RDONLY); 
+            if (parent_end_ == -1) 
+                BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); 
+        } 
+#elif defined(BOOST_WINDOWS_API) 
+        // TODO: Use RAII to close HANDLEs if an exception is thrown. 
+        SECURITY_ATTRIBUTES sa;
+        ZeroMemory(&sa, sizeof(sa));
+        sa.nLength = sizeof(sa);
+        sa.lpSecurityDescriptor = NULL;
+        sa.bInheritHandle = TRUE;
+        // TODO: Make this thread-safe (create unique filename differently). 
+        static unsigned int nextid = 0; 
+        std::string pipe = "\\\\.\\pipe\\boost_process_" + boost::lexical_cast<std::string>(::GetCurrentProcessId()) + "_" + boost::lexical_cast<std::string>(nextid++); 
+        natives[0] = ::CreateNamedPipeA(pipe.c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa); 
+        if (natives[0] == INVALID_HANDLE_VALUE) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateNamedPipe() failed"); 
+        natives[1] = ::CreateFileA(pipe.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 
+        if (natives[1] == INVALID_HANDLE_VALUE) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed"); 
+
+        OVERLAPPED overlapped; 
+        ZeroMemory(&overlapped, sizeof(overlapped)); 
+        overlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); 
+        if (!overlapped.hEvent) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateEvent() failed"); 
+        BOOL b = ::ConnectNamedPipe(natives[0], &overlapped); 
+        if (!b) 
+        { 
+            if (::GetLastError() == ERROR_IO_PENDING) 
+            { 
+                if (::WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_FAILED) 
+                { 
+                    ::CloseHandle(overlapped.hEvent); 
+                    BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("WaitForSingleObject() failed"); 
+                } 
+            } 
+            else if (::GetLastError() != ERROR_PIPE_CONNECTED) 
+            { 
+                ::CloseHandle(overlapped.hEvent); 
+                BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("ConnectNamedPipe() failed"); 
+            } 
+        } 
+        ::CloseHandle(overlapped.hEvent); 
+#endif 
+        child_end_ = natives[(stream == input_stream) ? 0 : 1]; 
+        parent_end_ = natives[(stream == input_stream) ? 1 : 0]; 
+#if defined(BOOST_WINDOWS_API) 
+        if (!::SetHandleInformation(child_end_, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetHandleInformation() failed"); 
+#endif 
+    } 
+
+    native_type get_child_end() const 
+    { 
+        return child_end_; 
+    } 
+
+    native_type get_parent_end() const 
+    { 
+        return parent_end_; 
+    } 
+
+private: 
+    native_type child_end_; 
+    native_type parent_end_; 
+}; 
+
+class mute : public stream_behavior 
+{ 
+public: 
+    enum stream_type { input_stream, output_stream }; 
+
+    mute(stream_type stream) 
+    { 
+#if defined(BOOST_POSIX_API) 
+        std::string filename = (stream == input_stream) ? "/dev/zero" : "/dev/null"; 
+        child_end_ = ::open(filename.c_str(), O_RDONLY); 
+        if (child_end_ == -1) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); 
+#elif defined(BOOST_WINDOWS_API) 
+        child_end_ = ::CreateFileA("NUL", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
+        if (child_end_ == INVALID_HANDLE_VALUE) 
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed"); 
+#endif 
+    } 
+
+    native_type get_child_end() const 
+    { 
+        return child_end_; 
+    } 
+
+private: 
+    native_type child_end_; 
+}; 
 
 }
 }
Modified: sandbox/SOC/2010/process/libs/process/example/child_stdout.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/child_stdout.cpp	(original)
+++ sandbox/SOC/2010/process/libs/process/example/child_stdout.cpp	2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -10,7 +10,8 @@
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
-#include <boost/all/process.hpp> 
+#include <boost/process/all.hpp> 
+#include <boost/make_shared.hpp> 
 #include <string> 
 #include <iostream> 
 
@@ -20,8 +21,10 @@
 { 
     std::string exe = find_executable_in_path("hostname"); 
     context ctx; 
-    ctx.stdout_behavior = capture; 
+    ctx.stdout_behavior = boost::make_shared<capture>(capture(capture::output_stream)); 
     child c = create_child(exe, ctx); 
     pistream &is = c.get_stdout(); 
-    std::cout << is.rdbuf(); 
+    std::string hostname; 
+    is >> hostname; 
+    std::cout << hostname << std::endl; 
 }