$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r65455 - in sandbox/SOC/2010/process: boost/process libs/process/test libs/process/test/inclusion
From: boris_at_[hidden]
Date: 2010-09-18 20:19:23
Author: bschaeling
Date: 2010-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
New Revision: 65455
URL: http://svn.boost.org/trac/boost/changeset/65455
Log:
Added support for configuring file descriptors greater than 2 on POSIX without giving up cross-platform API
Added:
   sandbox/SOC/2010/process/boost/process/stream_id.hpp   (contents, props changed)
   sandbox/SOC/2010/process/boost/process/stream_type.hpp   (contents, props changed)
   sandbox/SOC/2010/process/libs/process/test/inclusion/stream_id.cpp   (contents, props changed)
   sandbox/SOC/2010/process/libs/process/test/inclusion/stream_type.cpp   (contents, props changed)
Text files modified: 
   sandbox/SOC/2010/process/boost/process/all.hpp             |     2                                         
   sandbox/SOC/2010/process/boost/process/child.hpp           |    98 ++++--------------------                
   sandbox/SOC/2010/process/boost/process/context.hpp         |    49 ++++++-----                             
   sandbox/SOC/2010/process/boost/process/operations.hpp      |   131 +++++++++++++-------------------        
   sandbox/SOC/2010/process/boost/process/stream_behavior.hpp |    86 ++++++++++++++++++---                   
   sandbox/SOC/2010/process/libs/process/test/arguments.cpp   |     4                                         
   sandbox/SOC/2010/process/libs/process/test/child.cpp       |   160 +++++++++++++++------------------------ 
   sandbox/SOC/2010/process/libs/process/test/handle.cpp      |     2                                         
   8 files changed, 233 insertions(+), 299 deletions(-)
Modified: sandbox/SOC/2010/process/boost/process/all.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/all.hpp	(original)
+++ sandbox/SOC/2010/process/boost/process/all.hpp	2010-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -34,5 +34,7 @@
 #include <boost/process/status.hpp>
 #include <boost/process/stream_behavior.hpp>
 #include <boost/process/stream_ends.hpp>
+#include <boost/process/stream_id.hpp>
+#include <boost/process/stream_type.hpp>
 
 #endif
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-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -26,16 +26,16 @@
 #elif defined(BOOST_WINDOWS_API)
 #   include <windows.h>
 #else
-#   error "Unsupported platform." 
+#   error "Unsupported platform."
 #endif
 
 #include <boost/process/process.hpp>
 #include <boost/process/pid_type.hpp>
-#include <boost/process/pistream.hpp>
-#include <boost/process/postream.hpp>
+#include <boost/process/stream_id.hpp>
 #include <boost/process/handle.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/assert.hpp>
+#include <map>
 
 namespace boost {
 namespace process {
@@ -49,22 +49,11 @@
     /**
      * Creates a new child object that represents the just spawned child
      * process \a id.
-     *
-     * The \a hstdin, \a hstdout and \a hstderr file handles represent
-     * the parent's handles used to communicate with the corresponding
-     * data streams. They needn't be valid but their availability must
-     * match the redirections configured by the launcher that spawned this
-     * process.
      */
-    child(pid_type id, handle hstdin, handle hstdout, handle hstderr)
-        : process(id)
+    child(pid_type id, std::map<stream_id, handle> handles)
+        : process(id),
+        handles_(handles)
     {
-        if (hstdin.valid())
-            stdin_.reset(new postream(hstdin));
-        if (hstdout.valid())
-            stdout_.reset(new pistream(hstdout));
-        if (hstderr.valid())
-            stderr_.reset(new pistream(hstderr));
     }
 
 #if defined(BOOST_WINDOWS_API)
@@ -80,84 +69,29 @@
      *
      * This operation is only available on Windows systems.
      */
-    child(handle hprocess, handle hstdin, handle hstdout, handle hstderr)
-        : process(hprocess)
+    child(handle hprocess, std::map<stream_id, handle> handles)
+        : process(hprocess),
+        handles_(handles)
     {
-        if (hstdin.valid())
-            stdin_.reset(new postream(hstdin));
-        if (hstdout.valid())
-            stdout_.reset(new pistream(hstdout));
-        if (hstderr.valid())
-            stderr_.reset(new pistream(hstderr));
     }
 #endif
 
     /**
-     * Gets a reference to the child's standard input stream.
-     *
-     * Returns a reference to a postream object that represents the
-     * standard input communication channel with the child process.
-     */
-    postream &get_stdin() const
-    {
-        BOOST_ASSERT(stdin_);
-        return *stdin_;
-    }
-
-    /**
-     * Gets a reference to the child's standard output stream.
-     *
-     * Returns a reference to a pistream object that represents the
-     * standard output communication channel with the child process.
-     */
-    pistream &get_stdout() const
-    {
-        BOOST_ASSERT(stdout_);
-        return *stdout_;
-    }
-
-    /**
-     * Gets a reference to the child's standard error stream.
+     * Gets a handle to a stream attached to the child.
      *
-     * Returns a reference to a pistream object that represents the
-     * standard error communication channel with the child process.
+     * If the handle doesn't exist an invalid handle is returned.
      */
-    pistream &get_stderr() const
+    handle get_handle(stream_id id) const
     {
-        BOOST_ASSERT(stderr_);
-        return *stderr_;
+        std::map<stream_id, handle>::const_iterator it = handles_.find(id);
+        return (it != handles_.end()) ? it->second : handle();
     }
 
 private:
     /**
-     * The standard input stream attached to the child process.
-     *
-     * This postream object holds the communication channel with the
-     * child's process standard input. It is stored in a pointer because
-     * this field is only valid when the user requested to redirect this
-     * data stream.
-     */
-    boost::shared_ptr<postream> stdin_;
-
-    /**
-     * The standard output stream attached to the child process.
-     *
-     * This postream object holds the communication channel with the
-     * child's process standard output. It is stored in a pointer because
-     * this field is only valid when the user requested to redirect this
-     * data stream.
-     */
-    boost::shared_ptr<pistream> stdout_;
-
-    /**
-     * The standard error stream attached to the child process.
-     *
-     * This postream object holds the communication channel with the
-     * child's process standard error. It is stored in a pointer because
-     * this field is only valid when the user requested to redirect this
-     * data stream.
+     * Handles providing access to streams attached to the child process.
      */
-    boost::shared_ptr<pistream> stderr_;
+    std::map<stream_id, handle> handles_;
 };
 
 }
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-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -3,7 +3,8 @@
 // ~~~~~~~~~~~~~
 //
 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008, 2009 Boris Schaeling
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -28,12 +29,15 @@
 #   include <windows.h>
 #endif
 
+#include <boost/process/stream_id.hpp>
 #include <boost/process/stream_ends.hpp>
+#include <boost/process/stream_type.hpp>
 #include <boost/process/environment.hpp>
 #include <boost/process/self.hpp>
 #include <boost/process/stream_behavior.hpp>
 #include <boost/function.hpp>
 #include <string>
+#include <map>
 
 namespace boost {
 namespace process {
@@ -41,26 +45,25 @@
 /**
  * Context class to define how a child process is created.
  *
- * The context class is used to configure standard streams and to set the work
- * directory and environment variables. It is also used to change a process
+ * The context class is used to configure streams, to set the work directory
+ * and define environment variables. It is also used to change a process
  * name (the variable commonly known as argv[0]).
  */
 struct context
 {
-    /**
-     * Behavior of the standard input stream.
-     */
-    boost::function<stream_ends (bool)> stdin_behavior;
-
-    /**
-     * Behavior of the standard output stream.
-     */
-    boost::function<stream_ends (bool)> stdout_behavior;
+    typedef std::map<stream_id, boost::function<stream_ends (stream_type)> >
+        streams_t;
 
     /**
-     * Behavior of the standard error stream.
+     * Streams.
+     *
+     * Streams of a child process can be configured through factory functions
+     * which return a pair of handles - one handle to use as a stream end
+     * in the child process and possibly another handle to use as a stream end
+     * in the parent process (if a pipe is setup both processes can communicate
+     * with each other).
      */
-    boost::function<stream_ends (bool)> stderr_behavior;
+    streams_t streams;
 
     /**
      * Process name.
@@ -88,18 +91,18 @@
      * process also inherits all environment variables.
      */
     context()
+        : work_dir(self::get_work_dir()),
+        env(self::get_environment())
+    {
 #if defined(BOOST_POSIX_API)
-        : stdin_behavior(behavior::inherit(STDIN_FILENO)),
-        stdout_behavior(behavior::inherit(STDOUT_FILENO)),
-        stderr_behavior(behavior::inherit(STDERR_FILENO)),
+        streams[stdin_id] = behavior::inherit(STDIN_FILENO);
+        streams[stdout_id] = behavior::inherit(STDOUT_FILENO);
+        streams[stderr_id] = behavior::inherit(STDERR_FILENO);
 #elif defined(BOOST_WINDOWS_API)
-        : stdin_behavior(behavior::inherit(GetStdHandle(STD_INPUT_HANDLE))),
-        stdout_behavior(behavior::inherit(GetStdHandle(STD_OUTPUT_HANDLE))),
-        stderr_behavior(behavior::inherit(GetStdHandle(STD_ERROR_HANDLE))),
+        streams[stdin_id] = behavior::inherit(GetStdHandle(STD_INPUT_HANDLE));
+        streams[stdout_id] = behavior::inherit(GetStdHandle(STD_OUTPUT_HANDLE));
+        streams[stderr_id] = behavior::inherit(GetStdHandle(STD_ERROR_HANDLE));
 #endif
-        work_dir(self::get_work_dir()),
-        env(self::get_environment())
-    {
     }
 
 #if defined(BOOST_PROCESS_DOXYGEN)
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-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -44,6 +44,7 @@
 
 #include <boost/process/child.hpp>
 #include <boost/process/context.hpp>
+#include <boost/process/stream_id.hpp>
 #include <boost/process/stream_ends.hpp>
 #include <boost/process/handle.hpp>
 #include <boost/filesystem/path.hpp>
@@ -53,6 +54,7 @@
 #include <boost/assert.hpp>
 #include <string>
 #include <vector>
+#include <map>
 #include <utility>
 
 namespace boost {
@@ -188,17 +190,22 @@
 inline child create_child(const std::string &executable, Arguments args,
     Context ctx)
 {
-    stream_ends stdin_pair;
-    if (ctx.stdin_behavior)
-        stdin_pair = ctx.stdin_behavior(true);
-
-    stream_ends stdout_pair;
-    if (ctx.stdout_behavior)
-        stdout_pair = ctx.stdout_behavior(false);
-
-    stream_ends stderr_pair;
-    if (ctx.stderr_behavior)
-        stderr_pair = ctx.stderr_behavior(false);
+    typedef std::map<stream_id, stream_ends> handles_t;
+    handles_t handles;
+    typename Context::streams_t::iterator it = ctx.streams.begin();
+    for (; it != ctx.streams.end(); ++it)
+    {
+        if (it->first == stdin_id)
+            handles[it->first] = it->second(input_stream);
+        else if (it->first == stdout_id)
+            handles[it->first] = it->second(output_stream);
+        else if (it->first == stderr_id)
+            handles[it->first] = it->second(output_stream);
+#if defined(BOOST_POSIX_API)
+        else
+            handles[it->first] = it->second(unknown_stream);
+#endif
+    }
 
     std::string p_name = ctx.process_name.empty() ?
         executable_to_progname(executable) : ctx.process_name;
@@ -235,71 +242,35 @@
             _exit(127);
         }
 
-        handle hstdin = stdin_pair.child;
-        handle hstdout = stdout_pair.child;
-        handle hstderr = stderr_pair.child;
-
-        if (hstdin.valid())
+        for (handles_t::iterator it = handles.begin(); it != handles.end();
+            ++it)
         {
-            if (hstdout.native() == STDIN_FILENO)
+            if (it->second.child.valid())
             {
-                int fd = fcntl(hstdout.native(), F_DUPFD, 3);
-                if (fd == -1)
+                handles_t::iterator it2 = it;
+                ++it2;
+                for (; it2 != handles.end(); ++it2)
                 {
-                    write(STDERR_FILENO, "fcntl() failed\n", 15);
-                    _exit(127);
+                    if (it2->second.child.native() == it->first)
+                    {
+                        int fd = fcntl(it2->second.child.native(), F_DUPFD,
+                            it->first + 1);
+                        if (fd == -1)
+                        {
+                            write(STDERR_FILENO, "fcntl() failed\n", 15);
+                            _exit(127);
+                        }
+                        it2->second.child = fd;
+                    }
                 }
-                hstdout = fd;
-            }
 
-            if (hstderr.native() == STDIN_FILENO)
-            {
-                int fd = fcntl(hstderr.native(), F_DUPFD, 3);
-                if (fd == -1)
+                if (dup2(it->second.child.native(), it->first) == -1)
                 {
-                    write(STDERR_FILENO, "fcntl() failed\n", 15);
+                    write(STDERR_FILENO, "dup2() failed\n", 14);
                     _exit(127);
                 }
-                hstderr = fd;
+                closeflags[it->first] = false;
             }
-
-            if (dup2(hstdin.native(), STDIN_FILENO) == -1)
-            {
-                write(STDERR_FILENO, "dup2() failed\n", 14);
-                _exit(127);
-            }
-            closeflags[STDIN_FILENO] = false;
-        }
-
-        if (hstdout.valid())
-        {
-            if (hstderr.native() == STDOUT_FILENO)
-            {
-                int fd = fcntl(hstderr.native(), F_DUPFD, 3);
-                if (fd == -1)
-                {
-                    write(STDERR_FILENO, "fcntl() failed\n", 15);
-                    _exit(127);
-                }
-                hstderr = fd;
-            }
-
-            if (dup2(hstdout.native(), STDOUT_FILENO) == -1)
-            {
-                write(STDERR_FILENO, "dup2() failed\n", 14);
-                _exit(127);
-            }
-            closeflags[STDOUT_FILENO] = false;
-        }
-
-        if (hstderr.valid())
-        {
-            if (dup2(hstderr.native(), STDERR_FILENO) == -1)
-            {
-                write(STDERR_FILENO, "dup2() failed\n", 14);
-                _exit(127);
-            }
-            closeflags[STDERR_FILENO] = false;
         }
 
         ctx.setup(closeflags);
@@ -329,19 +300,21 @@
             delete[] envp.second[i];
         delete[] envp.second;
 
-        return child(pid,
-            stdin_pair.parent,
-            stdout_pair.parent,
-            stderr_pair.parent);
+        std::map<stream_id, handle> parent_ends;
+        for (handles_t::iterator it = handles.begin(); it != handles.end();
+            ++it)
+            parent_ends[it->first] = it->second.parent;
+
+        return child(pid, parent_ends);
     }
 #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 = stdin_pair.child.native();
-    startup_info.hStdOutput = stdout_pair.child.native();
-    startup_info.hStdError = stderr_pair.child.native();
+    startup_info.hStdInput = handles[stdin_id].child.native();
+    startup_info.hStdOutput = handles[stdout_id].child.native();
+    startup_info.hStdError = handles[stderr_id].child.native();
 
     ctx.setup(startup_info);
 
@@ -369,10 +342,12 @@
     if (CloseHandle(pi.hThread) == 0)
         BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
 
-    return child(hprocess,
-        stdin_pair.parent,
-        stdout_pair.parent,
-        stderr_pair.parent);
+    std::map<stream_id, handle> parent_ends;
+    parent_ends[stdin_id] = handles[stdin_id].parent;
+    parent_ends[stdout_id] = handles[stdout_id].parent;
+    parent_ends[stderr_id] = handles[stderr_id].parent;
+
+    return child(hprocess, parent_ends);
 #endif
 }
 
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-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -32,6 +32,7 @@
 #endif
 
 #include <boost/process/stream_ends.hpp>
+#include <boost/process/stream_type.hpp>
 #include <boost/process/handle.hpp>
 #include <string>
 #include <algorithm>
@@ -48,7 +49,7 @@
 class close
 {
 public:
-    stream_ends operator()(bool) const
+    stream_ends operator()(stream_type) const
     {
         return stream_ends();
     }
@@ -67,7 +68,7 @@
     {
     }
 
-    stream_ends operator()(bool) const
+    stream_ends operator()(stream_type) const
     {
         return stream_ends(h_, handle());
     }
@@ -84,12 +85,26 @@
 class pipe
 {
 public:
-    stream_ends operator()(bool in) const
+#if defined(BOOST_POSIX_API)
+    pipe()
+    : stype_(unknown_stream)
+    {
+    }
+
+    pipe(stream_type stype)
+    : stype_(stype)
+    {
+    }
+#endif
+
+    stream_ends operator()(stream_type stype) const
     {
         handle::native_type ends[2];
 #if defined(BOOST_POSIX_API)
         if (::pipe(ends) == -1)
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pipe(2) failed");
+        if (stype_ != unknown_stream)
+            stype = stype_;
 #elif defined(BOOST_WINDOWS_API)
         SECURITY_ATTRIBUTES sa;
         ZeroMemory(&sa, sizeof(sa));
@@ -99,8 +114,8 @@
         if (!CreatePipe(&ends[0], &ends[1], &sa, 0))
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed");
 #endif 
-        handle child_end = ends[in ? 0 : 1];
-        handle parent_end = ends[in ? 1 : 0];
+        handle child_end = ends[stype == input_stream ? 0 : 1];
+        handle parent_end = ends[stype == input_stream ? 1 : 0];
 #if defined(BOOST_WINDOWS_API)
         if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
             HANDLE_FLAG_INHERIT))
@@ -109,6 +124,11 @@
 #endif
         return stream_ends(child_end, parent_end);
     }
+
+#if defined(BOOST_POSIX_API)
+private:
+    stream_type stype_;
+#endif
 };
 
 /**
@@ -123,10 +143,21 @@
 public:
     named_pipe(const std::string &name)
     : name_(name)
+#if defined(BOOST_POSIX_API)
+    , stype_(unknown_stream)
+#endif
+    {
+    }
+
+#if defined(BOOST_POSIX_API)
+    named_pipe(const std::string &name, stream_type stype)
+    : name_(name),
+    stype_(stype)
     {
     }
+#endif
 
-    stream_ends operator()(bool in) const
+    stream_ends operator()(stream_type stype) const
     {
 #if defined(BOOST_POSIX_API)
         if (mkfifo(name_.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
@@ -143,6 +174,8 @@
         handle parent_end = open(name_.c_str(), O_WRONLY);
         if (!parent_end.valid())
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
+        if (stype_ != unknown_stream)
+            stype = stype_;
 #elif defined(BOOST_WINDOWS_API)
         SECURITY_ATTRIBUTES sa;
         ZeroMemory(&sa, sizeof(sa));
@@ -158,7 +191,7 @@
         if (!parent_end.valid())
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
 #endif
-        if (!in)
+        if (stype == output_stream)
             std::swap(child_end, parent_end);
 #if defined(BOOST_WINDOWS_API)
         if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
@@ -171,6 +204,10 @@
 
 private:
     std::string name_;
+
+#if defined(BOOST_POSIX_API)
+    stream_type stype_;
+#endif
 };
 
 /**
@@ -187,7 +224,7 @@
 class async_pipe
 {
 public:
-    stream_ends operator()(bool in) const
+    stream_ends operator()(stream_type stype) const
     {
         UUID uuid;
         RPC_STATUS s = UuidCreateSequential(&uuid);
@@ -209,7 +246,7 @@
         }
         RpcStringFreeA(&c);
         named_pipe p("\\\\.\\pipe\\boost_process_" + name);
-        return p(in);
+        return p(stype);
     }
 };
 #endif
@@ -223,26 +260,47 @@
 class null
 {
 public:
-    stream_ends operator()(bool in) const
+#if defined(BOOST_POSIX_API)
+    null()
+    : stype_(unknown_stream)
+    {
+    }
+
+    null(stream_type stype)
+    : stype_(stype)
+    {
+    }
+#endif
+
+    stream_ends operator()(stream_type stype) const
     {
 #if defined(BOOST_POSIX_API)
-        std::string filename = in ? "/dev/zero" : "/dev/null";
-        int flag = in ? O_RDONLY : O_WRONLY;
+        if (stype_ != unknown_stream)
+            stype = stype_;
+        std::string filename = (stype == input_stream) ? "/dev/zero" :
+            "/dev/null";
+        int flag = (stype == input_stream) ? O_RDONLY : O_WRONLY;
         handle child_end = open(filename.c_str(), flag);
         if (!child_end.valid())
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
 #elif defined(BOOST_WINDOWS_API)
-        DWORD access = in ? GENERIC_READ : GENERIC_WRITE;
+        DWORD access = (stype == input_stream) ? GENERIC_READ : GENERIC_WRITE;
         handle child_end = CreateFileA("NUL", access, 0, NULL, OPEN_EXISTING,
             FILE_ATTRIBUTE_NORMAL, NULL);
         if (!child_end.valid())
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
         if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
             HANDLE_FLAG_INHERIT))
-            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetHandleInformation() failed");
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
+                "SetHandleInformation() failed");
 #endif
         return stream_ends(child_end, handle());
     }
+
+#if defined(BOOST_POSIX_API)
+private:
+    stream_type stype_;
+#endif
 };
 
 }
Added: sandbox/SOC/2010/process/boost/process/stream_id.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2010/process/boost/process/stream_id.hpp	2010-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -0,0 +1,50 @@
+//
+// Boost.Process
+// ~~~~~~~~~~~~~
+//
+// 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
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+/**
+ * \file boost/process/stream_id.hpp
+ *
+ * Includes the declaration of the stream_id type.
+ */
+
+#ifndef BOOST_PROCESS_STREAM_ID_HPP
+#define BOOST_PROCESS_STREAM_ID_HPP
+
+#include <boost/process/config.hpp>
+
+namespace boost {
+namespace process {
+
+/**
+ * Standard stream id to refer to standard streams in a cross-platform manner.
+ */
+enum std_stream_id { stdin_id, stdout_id, stderr_id };
+
+#if defined(BOOST_PROCESS_DOXYGEN)
+/**
+ * Stream id type.
+ *
+ * Depending on the platform the stream id type is defined to refer to standard
+ * streams only or to support more streams.
+ */
+typedef NativeStreamId stream_id;
+#elif defined(BOOST_POSIX_API)
+typedef std_stream_id stream_id;
+#elif defined(BOOST_WINDOWS_API)
+typedef int stream_id;
+#endif
+
+}
+}
+
+#endif
Added: sandbox/SOC/2010/process/boost/process/stream_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2010/process/boost/process/stream_type.hpp	2010-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -0,0 +1,45 @@
+//
+// Boost.Process
+// ~~~~~~~~~~~~~
+//
+// 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
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+/**
+ * \file boost/process/stream_type.hpp
+ *
+ * Includes the declaration of the stream_type enumeration.
+ */
+
+#ifndef BOOST_PROCESS_STREAM_TYPE_HPP
+#define BOOST_PROCESS_STREAM_TYPE_HPP
+
+#include <boost/process/config.hpp>
+
+namespace boost {
+namespace process {
+
+/**
+ * Stream type to differentiate between input and output streams.
+ *
+ * On POSIX systems another value unknown_stream is define. It is passed
+ * to stream behaviors for file descriptors greater than 2.
+ */
+enum stream_type {
+    input_stream,
+    output_stream
+#if defined(BOOST_POSIX_API)
+    , unknown_stream
+#endif
+};
+
+}
+}
+
+#endif
Modified: sandbox/SOC/2010/process/libs/process/test/arguments.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/test/arguments.cpp	(original)
+++ sandbox/SOC/2010/process/libs/process/test/arguments.cpp	2010-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -37,10 +37,10 @@
     args.push_back(word); 
 
     bp::context ctx; 
-    ctx.stdout_behavior = bpb::pipe(); 
+    ctx.streams[bp::stdout_id] = bpb::pipe(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
-    bp::pistream &is = c.get_stdout(); 
+    bp::pistream is(c.get_handle(bp::stdout_id)); 
 
     std::string result; 
     std::getline(is, result); 
Modified: sandbox/SOC/2010/process/libs/process/test/child.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/test/child.cpp	(original)
+++ sandbox/SOC/2010/process/libs/process/test/child.cpp	2010-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -40,7 +40,7 @@
     args.push_back("is-closed-stdin"); 
 
     bp::context ctx; 
-    ctx.stdin_behavior = bpb::close(); 
+    ctx.streams[bp::stdin_id] = bpb::close(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
@@ -61,7 +61,7 @@
     args.push_back("is-closed-stdout"); 
 
     bp::context ctx1; 
-    ctx1.stdout_behavior = bpb::close(); 
+    ctx1.streams[bp::stdout_id] = bpb::close(); 
 
     bp::child c1 = bp::create_child(get_helpers_path(), args, ctx1); 
 
@@ -74,7 +74,7 @@
 #endif 
 
     bp::context ctx2; 
-    ctx2.stdout_behavior = bpb::pipe(); 
+    ctx2.streams[bp::stdout_id] = bpb::pipe(); 
 
     bp::child c2 = bp::create_child(get_helpers_path(), args, ctx2); 
 
@@ -95,7 +95,7 @@
     args.push_back("is-closed-stderr"); 
 
     bp::context ctx1; 
-    ctx1.stderr_behavior = bpb::close(); 
+    ctx1.streams[bp::stderr_id] = bpb::close(); 
 
     bp::child c1 = bp::create_child(get_helpers_path(), args, ctx1); 
 
@@ -108,7 +108,7 @@
 #endif 
 
     bp::context ctx2; 
-    ctx2.stderr_behavior = bpb::pipe(); 
+    ctx2.streams[bp::stderr_id] = bpb::pipe(); 
 
     bp::child c2 = bp::create_child(get_helpers_path(), args, ctx2); 
 
@@ -129,13 +129,13 @@
     args.push_back("stdin-to-stdout"); 
 
     bp::context ctx; 
-    ctx.stdin_behavior = bpb::pipe(); 
-    ctx.stdout_behavior = bpb::pipe(); 
+    ctx.streams[bp::stdin_id] = bpb::pipe(); 
+    ctx.streams[bp::stdout_id] = bpb::pipe(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
-    bp::postream &os = c.get_stdin(); 
-    bp::pistream &is = c.get_stdout(); 
+    bp::postream os(c.get_handle(bp::stdin_id)); 
+    bp::pistream is(c.get_handle(bp::stdout_id)); 
 
     os << "message-to-process" << std::endl; 
     os.close(); 
@@ -160,12 +160,12 @@
     args.push_back("message-stdout"); 
 
     bp::context ctx; 
-    ctx.stdout_behavior = bpb::pipe(); 
+    ctx.streams[bp::stdout_id] = bpb::pipe(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
     std::string word; 
-    bp::pistream &is = c.get_stdout(); 
+    bp::pistream is(c.get_handle(bp::stdout_id)); 
     is >> word; 
     BOOST_CHECK_EQUAL(word, "message-stdout"); 
 
@@ -185,12 +185,12 @@
     args.push_back("message-stderr"); 
 
     bp::context ctx; 
-    ctx.stderr_behavior = bpb::pipe(); 
+    ctx.streams[bp::stderr_id] = bpb::pipe(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
     std::string word; 
-    bp::pistream &is = c.get_stderr(); 
+    bp::pistream is(c.get_handle(bp::stderr_id)); 
     is >> word; 
     BOOST_CHECK_EQUAL(word, "message-stderr"); 
 
@@ -210,18 +210,18 @@
     args.push_back("message-to-two-streams"); 
 
     bp::context ctx; 
-    ctx.stdout_behavior = bpb::pipe(); 
-    ctx.stderr_behavior = bpb::pipe(); 
+    ctx.streams[bp::stdout_id] = bpb::pipe(); 
+    ctx.streams[bp::stderr_id] = bpb::pipe(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
     std::string word; 
-    bp::pistream &isout = c.get_stdout(); 
+    bp::pistream isout(c.get_handle(bp::stdout_id)); 
     isout >> word; 
     BOOST_CHECK_EQUAL(word, "stdout"); 
     isout >> word; 
     BOOST_CHECK_EQUAL(word, "message-to-two-streams"); 
-    bp::pistream &iserr = c.get_stderr(); 
+    bp::pistream iserr(c.get_handle(bp::stderr_id)); 
     iserr >> word; 
     BOOST_CHECK_EQUAL(word, "stderr"); 
     iserr >> word; 
@@ -257,15 +257,15 @@
     args.push_back("echo-stdout-stderr"); 
     args.push_back("message-to-two-streams"); 
 
-    bp::stream_ends ends = bpb::pipe()(false); 
+    bp::stream_ends ends = bpb::pipe()(bp::output_stream); 
 
     bp::context ctx; 
-    ctx.stdout_behavior = boost::bind(forward, ends); 
-    ctx.stderr_behavior = boost::bind(redirect_to, ends.child); 
+    ctx.streams[bp::stdout_id] = boost::bind(forward, ends); 
+    ctx.streams[bp::stderr_id] = boost::bind(redirect_to, ends.child); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
-    bp::pistream &is = c.get_stdout(); 
+    bp::pistream is(c.get_handle(bp::stdout_id)); 
     std::string word; 
     is >> word; 
     BOOST_CHECK_EQUAL(word, "stdout"); 
@@ -293,11 +293,11 @@
     bp::context ctx; 
     BOOST_CHECK(bfs::equivalent(ctx.work_dir, bfs::current_path().string())); 
 
-    ctx.stdout_behavior = bpb::pipe(); 
+    ctx.streams[bp::stdout_id] = bpb::pipe(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
-    bp::pistream &is = c.get_stdout(); 
+    bp::pistream is(c.get_handle(bp::stdout_id)); 
     std::string dir; 
     std::getline(is, dir); 
     std::string::size_type pos = dir.rfind('\r'); 
@@ -327,11 +327,11 @@
     { 
         bp::context ctx; 
         ctx.work_dir = wdir.string(); 
-        ctx.stdout_behavior = bpb::pipe(); 
+        ctx.streams[bp::stdout_id] = bpb::pipe(); 
 
         bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
-        bp::pistream &is = c.get_stdout(); 
+        bp::pistream is(c.get_handle(bp::stdout_id)); 
         std::string dir; 
         std::getline(is, dir); 
         std::string::size_type pos = dir.rfind('\r'); 
@@ -362,11 +362,11 @@
     args.push_back("query-env"); 
     args.push_back(var); 
 
-    ctx.stdout_behavior = bpb::pipe(); 
+    ctx.streams[bp::stdout_id] = bpb::pipe(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
-    bp::pistream &is = c.get_stdout(); 
+    bp::pistream is(c.get_handle(bp::stdout_id)); 
     std::string status; 
     is >> status; 
     std::string gotval; 
@@ -482,16 +482,16 @@
     args.push_back("async-"); 
 
     bp::context ctx; 
-    ctx.stdin_behavior = bpb::async_pipe(); 
-    ctx.stdout_behavior = bpb::async_pipe(); 
+    ctx.streams[bp::stdin_id] = bpb::async_pipe(); 
+    ctx.streams[bp::stdout_id] = bpb::async_pipe(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
-    bp::postream &os = c.get_stdin(); 
-    bp::pistream &is = c.get_stdout(); 
+    bp::handle in = c.get_handle(bp::stdin_id); 
+    bp::handle out = c.get_handle(bp::stdout_id); 
 
     ba::io_service ioservice; 
-    bp::pipe write_end(ioservice, os.handle().release()); 
-    bp::pipe read_end(ioservice, is.handle().release()); 
+    bp::pipe write_end(ioservice, in.release()); 
+    bp::pipe read_end(ioservice, out.release()); 
 
     ba::async_write(write_end, ba::buffer("test\n", 5), write_handler); 
     ba::streambuf buf; 
@@ -518,12 +518,12 @@
 #endif 
 
     bp::context ctx; 
-    ctx.stdout_behavior = bpb::pipe(); 
+    ctx.streams[bp::stdout_id] = bpb::pipe(); 
 
     bp::child c = bp::shell(cmd, ctx); 
 
     std::string word; 
-    bp::pistream &is = c.get_stdout(); 
+    bp::pistream is(c.get_handle(bp::stdout_id)); 
     is >> word; 
     BOOST_CHECK_EQUAL(word, "LINE-test"); 
 
@@ -544,7 +544,7 @@
     args.push_back("is-nul-stdin"); 
 
     bp::context ctx; 
-    ctx.stdin_behavior = bpb::null(); 
+    ctx.streams[bp::stdin_id] = bpb::null(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
@@ -565,7 +565,7 @@
     args.push_back("is-nul-stdout"); 
 
     bp::context ctx; 
-    ctx.stdout_behavior = bpb::null(); 
+    ctx.streams[bp::stdout_id] = bpb::null(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
@@ -586,7 +586,7 @@
     args.push_back("is-nul-stderr"); 
 
     bp::context ctx; 
-    ctx.stderr_behavior = bpb::null(); 
+    ctx.streams[bp::stderr_id] = bpb::null(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
@@ -600,27 +600,6 @@
 } 
 
 #if defined(BOOST_POSIX_API) 
-class context : public bp::context 
-{ 
-public: 
-    context() 
-    : ends(bpb::pipe()(false)) 
-    { 
-    } 
-
-    void setup(std::vector<bool> &closeflags) 
-    { 
-        if (dup2(ends.child.native(), 10) == -1) 
-        { 
-            write(STDERR_FILENO, "dup2() failed\n", 14); 
-            _exit(127); 
-        } 
-        closeflags[10] = false; 
-    } 
-
-    bp::stream_ends ends; 
-}; 
-
 BOOST_AUTO_TEST_CASE(test_posix) 
 { 
     check_helpers(); 
@@ -630,11 +609,13 @@
     args.push_back("10"); 
     args.push_back("test"); 
 
-    context ctx; 
+    bp::context ctx; 
+    ctx.streams[static_cast<bp::stream_id>(10)] = bpb::pipe(bp::output_stream); 
+
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
     std::string word; 
-    bp::pistream is(ctx.ends.parent); 
+    bp::pistream is(c.get_handle(static_cast<bp::stream_id>(10))); 
     is >> word; 
     BOOST_CHECK_EQUAL(word, "test"); 
 
@@ -672,27 +653,6 @@
     int fd2_; 
 }; 
 
-class context2 : public bp::context 
-{ 
-public: 
-    context2() 
-    : ends(bpb::pipe()(false)) 
-    { 
-    } 
-
-    void setup(std::vector<bool> &closeflags) 
-    { 
-        if (dup2(ends.child.native(), 3) == -1) 
-        { 
-            write(STDERR_FILENO, "dup2() failed\n", 14); 
-            _exit(127); 
-        } 
-        closeflags[3] = false; 
-    } 
-
-    bp::stream_ends ends; 
-}; 
-
 BOOST_AUTO_TEST_CASE(test_posix2) 
 { 
     check_helpers(); 
@@ -702,7 +662,9 @@
     args.push_back("3"); 
     args.push_back("test"); 
 
-    context2 ctx; 
+    bp::context ctx; 
+    ctx.streams[static_cast<bp::std_stream_id>(3)] = 
+        bpb::pipe(bp::output_stream); 
 
     // File descriptors must be closed after context is instantiated as the 
     // context constructor uses the behavior inherit which tries to dup() 
@@ -714,13 +676,13 @@
     raii_dup2 raii_stderr(STDERR_FILENO, 102); 
     close(STDERR_FILENO); 
 
-    ctx.stdin_behavior = bpb::null(); 
-    ctx.stdout_behavior = bpb::null(); 
-    ctx.stderr_behavior = bpb::null(); 
+    ctx.streams[bp::stdin_id] = bpb::null(); 
+    ctx.streams[bp::stdout_id] = bpb::null(); 
+    ctx.streams[bp::stderr_id] = bpb::null(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
-    int res = dup2(ctx.ends.parent.native(), 0); 
+    int res = dup2(c.get_handle(static_cast<bp::std_stream_id>(3)).native(), 0); 
     std::string word; 
     if (res != -1) 
         std::cin >> word; 
@@ -745,7 +707,7 @@
     args.push_back("echo-stdout-stderr"); 
     args.push_back("message-to-two-streams"); 
 
-    context ctx; 
+    bp::context ctx; 
 
     // File descriptors must be closed after context is instantiated as the 
     // context constructor uses the behavior inherit which tries to dup() 
@@ -757,16 +719,16 @@
     raii_dup2 raii_stderr(STDERR_FILENO, 102); 
     close(STDERR_FILENO); 
 
-    ctx.stdin_behavior = bpb::null(); 
-    ctx.stderr_behavior = bpb::pipe(); 
-    ctx.stdout_behavior = bpb::pipe(); 
+    ctx.streams[bp::stdin_id] = bpb::null(); 
+    ctx.streams[bp::stderr_id] = bpb::pipe(); 
+    ctx.streams[bp::stdout_id] = bpb::pipe(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
     std::string words[4]; 
-    bp::pistream &isout = c.get_stdout(); 
+    bp::pistream isout(c.get_handle(bp::stdout_id)); 
     isout >> words[0] >> words[1]; 
-    bp::pistream &iserr = c.get_stderr(); 
+    bp::pistream iserr(c.get_handle(bp::stderr_id)); 
     iserr >> words[2] >> words[3]; 
 
     raii_stdin.revert(); 
@@ -808,11 +770,11 @@
     args.push_back("windows-print-startupinfo"); 
 
     context ctx; 
-    ctx.stdout_behavior = bpb::pipe(); 
+    ctx.streams[bp::stdout_id] = bpb::pipe(); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
-    bp::pistream &is = c.get_stdout(); 
+    bp::pistream is(c.get_handle(bp::stdout_id)); 
     std::string line; 
     std::getline(is, line); 
     BOOST_CHECK_EQUAL(line, "dwFlags = " + boost::lexical_cast<std::string>( 
@@ -854,13 +816,13 @@
     args.push_back("stdin-to-stdout"); 
 
     bp::context ctx; 
-    ctx.stdin_behavior = bpb::named_pipe(create_unique_pipe_name()); 
-    ctx.stdout_behavior = bpb::named_pipe(create_unique_pipe_name()); 
+    ctx.streams[bp::stdin_id] = bpb::named_pipe(create_unique_pipe_name()); 
+    ctx.streams[bp::stdout_id] = bpb::named_pipe(create_unique_pipe_name()); 
 
     bp::child c = bp::create_child(get_helpers_path(), args, ctx); 
 
-    bp::postream &os = c.get_stdin(); 
-    bp::pistream &is = c.get_stdout(); 
+    bp::postream os(c.get_handle(bp::stdin_id)); 
+    bp::pistream is(c.get_handle(bp::stdout_id)); 
 
     os << "message-to-process" << std::endl; 
     os.close(); 
Modified: sandbox/SOC/2010/process/libs/process/test/handle.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/test/handle.cpp	(original)
+++ sandbox/SOC/2010/process/libs/process/test/handle.cpp	2010-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -28,7 +28,7 @@
 
 BOOST_AUTO_TEST_CASE(test_handle_readwrite) 
 { 
-    bp::stream_ends ends = bpb::pipe()(true); 
+    bp::stream_ends ends = bpb::pipe()(bp::input_stream); 
 
     bp::handle read_end = ends.child; 
     bp::handle write_end = ends.parent; 
Added: sandbox/SOC/2010/process/libs/process/test/inclusion/stream_id.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2010/process/libs/process/test/inclusion/stream_id.cpp	2010-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -0,0 +1,14 @@
+// 
+// Boost.Process 
+// ~~~~~~~~~~~~~ 
+// 
+// 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 
+// 
+// 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/stream_id.hpp> 
Added: sandbox/SOC/2010/process/libs/process/test/inclusion/stream_type.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2010/process/libs/process/test/inclusion/stream_type.cpp	2010-09-18 20:19:06 EDT (Sat, 18 Sep 2010)
@@ -0,0 +1,14 @@
+// 
+// Boost.Process 
+// ~~~~~~~~~~~~~ 
+// 
+// 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 
+// 
+// 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/stream_type.hpp>