Boost logo

Boost-Commit :

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>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk