Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r62640 - in sandbox/SOC/2010/process: boost/process boost/process/detail libs/process/example
From: boris_at_[hidden]
Date: 2010-06-09 03:54:40


Author: bschaeling
Date: 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
New Revision: 62640
URL: http://svn.boost.org/trac/boost/changeset/62640

Log:
Updated entire code base after having introduced new stream behavior classes
Removed:
   sandbox/SOC/2010/process/boost/process/detail/helper_functions.hpp
   sandbox/SOC/2010/process/boost/process/detail/pipe.hpp
   sandbox/SOC/2010/process/boost/process/detail/stream_detail.hpp
   sandbox/SOC/2010/process/boost/process/posix_child.hpp
Text files modified:
   sandbox/SOC/2010/process/boost/process/all.hpp | 29 +---
   sandbox/SOC/2010/process/boost/process/child.hpp | 141 +++++++++++++-------------
   sandbox/SOC/2010/process/boost/process/context.hpp | 2
   sandbox/SOC/2010/process/boost/process/detail/file_handle.hpp | 136 -------------------------
   sandbox/SOC/2010/process/boost/process/detail/posix_helpers.hpp | 109 ++++----------------
   sandbox/SOC/2010/process/boost/process/detail/systembuf.hpp | 8
   sandbox/SOC/2010/process/boost/process/detail/win32_helpers.hpp | 84 ---------------
   sandbox/SOC/2010/process/boost/process/environment.hpp | 2
   sandbox/SOC/2010/process/boost/process/operations.hpp | 208 +++++++++++----------------------------
   sandbox/SOC/2010/process/boost/process/process.hpp | 30 ++---
   sandbox/SOC/2010/process/boost/process/self.hpp | 49 ++++-----
   sandbox/SOC/2010/process/boost/process/status.hpp | 4
   sandbox/SOC/2010/process/boost/process/stream_behavior.hpp | 91 +++++++++++++----
   sandbox/SOC/2010/process/libs/process/example/child_stdin.cpp | 4
   14 files changed, 281 insertions(+), 616 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-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -14,30 +14,21 @@
  * \file boost/process/all.hpp
  *
  * Convenience header that includes all other Boost.Process public header
- * files. It is important to note that those headers that are specific to
- * a given platform are only included if the library is being used in that
- * same platform.
+ * files.
  */
 
 #ifndef BOOST_PROCESS_ALL_HPP
 #define BOOST_PROCESS_ALL_HPP
 
 #include <boost/process/config.hpp>
-
-#if defined(BOOST_POSIX_API)
-#elif defined(BOOST_WINDOWS_API)
-#else
-# error "Unsupported platform."
-#endif
-
-# include <boost/process/child.hpp>
-# include <boost/process/context.hpp>
-# include <boost/process/environment.hpp>
-# include <boost/process/operations.hpp>
-# include <boost/process/pistream.hpp>
-# include <boost/process/postream.hpp>
-# include <boost/process/process.hpp>
-# include <boost/process/status.hpp>
-# include <boost/process/stream_behavior.hpp>
+#include <boost/process/child.hpp>
+#include <boost/process/context.hpp>
+#include <boost/process/environment.hpp>
+#include <boost/process/operations.hpp>
+#include <boost/process/pistream.hpp>
+#include <boost/process/postream.hpp>
+#include <boost/process/process.hpp>
+#include <boost/process/status.hpp>
+#include <boost/process/stream_behavior.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-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -45,15 +45,40 @@
 namespace process {
 
 /**
- * Generic implementation of the Child concept.
- *
- * The child class implements the Child concept in an operating system
- * agnostic way.
+ * The child class provides access to a child process.
  */
 class child : public process
 {
 public:
     /**
+ * Creates a new child object that represents the just spawned child
+ * process \a id.
+ *
+ * The \a fhstdin, \a fhstdout and \a fhstderr 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.
+ *
+ * The \a fhprocess handle represents a handle to the child process.
+ * It is only used on Windows as the implementation of wait() needs a
+ * process handle.
+ */
+ child(id_type id, detail::file_handle &fhstdin, detail::file_handle &fhstdout, detail::file_handle &fhstderr, detail::file_handle fhprocess = detail::file_handle())
+ : process(id)
+#if defined(BOOST_WINDOWS_API)
+ , process_handle_(fhprocess.release(), ::CloseHandle)
+#endif
+ {
+ if (fhstdin.valid())
+ stdin_.reset(new postream(fhstdin));
+ if (fhstdout.valid())
+ stdout_.reset(new pistream(fhstdout));
+ if (fhstderr.valid())
+ stderr_.reset(new pistream(fhstderr));
+ }
+
+ /**
      * Gets a reference to the child's standard input stream.
      *
      * Returns a reference to a postream object that represents the
@@ -89,34 +114,6 @@
         return *stderr_;
     }
 
- /**
- * Creates a new child object that represents the just spawned child
- * process \a id.
- *
- * The \a fhstdin, \a fhstdout and \a fhstderr 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.
- *
- * The \a fhprocess handle represents a handle to the child process.
- * It is only used on Windows as the implementation of wait() needs a
- * process handle.
- */
- child(id_type id, detail::file_handle &fhstdin, detail::file_handle &fhstdout, detail::file_handle &fhstderr, detail::file_handle fhprocess = detail::file_handle())
- : process(id)
-#if defined(BOOST_WINDOWS_API)
- ,process_handle_(fhprocess.release(), ::CloseHandle)
-#endif
- {
- if (fhstdin.valid())
- stdin_.reset(new postream(fhstdin));
- if (fhstdout.valid())
- stdout_.reset(new pistream(fhstdout));
- if (fhstderr.valid())
- stderr_.reset(new pistream(fhstderr));
- }
-
 private:
     /**
      * The standard input stream attached to the child process.
@@ -158,6 +155,46 @@
 #if defined(BOOST_POSIX_API)
 public:
     /**
+ * 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));
+ }
+ }
+ }
+
+ /**
      * Gets a reference to the child's input stream \a desc.
      *
      * Returns a reference to a postream object that represents one of
@@ -209,46 +246,6 @@
         }
     }
 
- /**
- * 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.

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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -38,7 +38,7 @@
     boost::shared_ptr<stream_behavior> stderr_behavior;
     std::string process_name;
     std::string work_dir;
- environment_t environment;
+ environment environment;
 
     /**
      * Constructs a process 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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -32,9 +32,6 @@
 #endif
 
 #include <boost/assert.hpp>
-#include <boost/system/system_error.hpp>
-#include <boost/throw_exception.hpp>
-#include <stdio.h>
 
 namespace boost {
 namespace process {
@@ -108,6 +105,8 @@
     file_handle(handle_type h)
         : handle_(h)
     {
+ // Boris: I wonder why this assert existed before (also in
+ // previous Boost.Process versions).
         // BOOST_ASSERT(handle_ != invalid_value());
     }
 
@@ -232,67 +231,6 @@
         ::close(handle_);
         handle_ = invalid_value();
     }
-
- /**
- * Changes the native file handle to the given one.
- *
- * Given a new native file handle \a h, this operation assigns this
- * handle to the current object, closing its old native file handle.
- * In other words, it first calls dup2() to remap the old handle to
- * the new one and then closes the old handle.
- *
- * If \a h is open, it is automatically closed by dup2().
- *
- * This operation is only available in POSIX systems.
- *
- * \pre The file handle is valid.
- * \pre The native file handle \a h is valid; i.e., it must be
- * closeable.
- * \post The file handle's native file handle is \a h.
- * \throw boost::system::system_error If the internal remapping
- * operation fails.
- */
- void posix_remap(handle_type &h)
- {
- BOOST_ASSERT(valid());
-
- if (::dup2(handle_, h) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_remap: dup2(2) failed"));
-
- if (::close(handle_) == -1)
- ::close(h);
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_remap: close(2) failed"));
-
- if(::dup2(handle_,h) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_remap: dup2(2) failed"));
-
- handle_ = h;
- }
-
- /**
- * Duplicates an open native file handle.
- *
- * Given a native file handle \a h1, this routine duplicates it so
- * that it ends up being identified by the native file handle \a h2
- * and returns a new \a file_handle owning \a h2.
- *
- * This operation is only available in POSIX systems.
- *
- * \pre The native file handle \a h1 is open.
- * \pre The native file handle \a h2 is valid (non-negative).
- * \post The native file handle \a h1 is closed.
- * \post The native file handle \a h2 is the same as the old \a h1
- * from the operating system's point of view.
- * \return A new \a file_handle object that owns \a h2.
- * \throw boost::system::system_error If dup2() fails.
- */
- static file_handle duplicate(int h1, int h2)
- {
- if (::dup2(h1, h2) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_dup: dup2(2) failed"));
-
- return file_handle(h2);
- }
 #endif
 
 #if defined(BOOST_WINDOWS_API) || defined(BOOST_PROCESS_DOXYGEN)
@@ -312,76 +250,6 @@
         ::CloseHandle(handle_);
         handle_ = invalid_value();
     }
-
- /**
- * Duplicates the \a h native file handle.
- *
- * Given a native file handle \a h, this routine constructs a new
- * \a file_handle object that owns a new duplicate of \a h. The
- * duplicate's inheritable flag is set to the value of \a inheritable.
- *
- * This operation is only available in Windows systems.
- *
- * \pre The native file handle \a h is valid.
- * \return A file handle owning a duplicate of \a h.
- * \throw boost::system::system_error If DuplicateHandle() fails.
- */
- static file_handle win32_dup(HANDLE h, bool inheritable)
- {
- HANDLE h2;
-
- if (::DuplicateHandle(::GetCurrentProcess(), h, ::GetCurrentProcess(), &h2, 0, inheritable ? TRUE : FALSE, DUPLICATE_SAME_ACCESS) == 0)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_dup: DuplicateHandle failed"));
-
- return file_handle(h2);
- }
-
- /**
- * Creates a new duplicate of a standard file handle.
- *
- * Constructs a new \a file_handle object that owns a duplicate of a
- * standard file handle. The \a d parameter specifies which standard
- * file handle to duplicate and can be one of \a STD_INPUT_HANDLE,
- * \a STD_OUTPUT_HANDLE or \a STD_ERROR_HANDLE. The duplicate's
- * inheritable flag is set to the value of \a inheritable.
- *
- * This operation is only available in Windows systems.
- *
- * \pre \a d refers to one of the standard handles as described above.
- * \return A file handle owning a duplicate of the standard handle
- * referred to by \a d.
- * \throw boost::system::system_error If GetStdHandle() or
- * DuplicateHandle() fails.
- */
- static file_handle win32_dup_std(DWORD d, bool inheritable)
- {
- BOOST_ASSERT(d == STD_INPUT_HANDLE || d == STD_OUTPUT_HANDLE || d == STD_ERROR_HANDLE);
- HANDLE h = ::GetStdHandle(d);
- if (h == INVALID_HANDLE_VALUE)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_std:GetStdHandle failed"));
- file_handle dh = win32_dup(h, inheritable);
- return dh;
- }
-
- /**
- * Changes the file handle's inheritable flag.
- *
- * Changes the file handle's inheritable flag to \a i. It is not
- * necessary for the file handle's flag to be different than \a i.
- *
- * This operation is only available in Windows systems.
- *
- * \pre The file handle is valid.
- * \post The native file handle's inheritable flag is set to \a i.
- * \throw boost::system::system_error If the property change fails.
- */
- void win32_set_inheritable(bool i)
- {
- BOOST_ASSERT(valid());
-
- if (!::SetHandleInformation(handle_, HANDLE_FLAG_INHERIT, i ? HANDLE_FLAG_INHERIT : 0))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_set_inheritable: SetHandleInformation failed"));
- }
 #endif
 
 private:

Deleted: sandbox/SOC/2010/process/boost/process/detail/helper_functions.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/helper_functions.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
+++ (empty file)
@@ -1,34 +0,0 @@
-//
-// Boost.Process
-// ~~~~~~~~~~~~~
-//
-// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008, 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/detail/helper_functions.hpp
- *
- * Includes the declaration of helper functions for the operations.
- * It's for internal purposes.
- *
- */
-
-#include <boost/process/config.hpp>
-
-#ifndef BOOST_PROCESS_HELPER_FUNCTIONS_HPP
-#define BOOST_PROCESS_HELPER_FUNCTIONS_HPP
-
-namespace boost {
-namespace process {
-namespace detail {
-
-}
-}
-}
-
-#endif

Deleted: sandbox/SOC/2010/process/boost/process/detail/pipe.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/pipe.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
+++ (empty file)
@@ -1,188 +0,0 @@
-//
-// Boost.Process
-// ~~~~~~~~~~~~~
-//
-// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008, 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/detail/pipe.hpp
- *
- * Includes the declaration of the pipe class. This file is for
- * internal usage only and must not be included by the library user.
- */
-
-#ifndef BOOST_PROCESS_DETAIL_PIPE_HPP
-#define BOOST_PROCESS_DETAIL_PIPE_HPP
-
-#include <boost/process/config.hpp>
-
-#if defined(BOOST_POSIX_API)
-# include <unistd.h>
-# include <cerrno>
-#elif defined(BOOST_WINDOWS_API)
-# if defined(BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE)
-# include <boost/lexical_cast.hpp>
-# include <string>
-# endif
-# include <windows.h>
-#else
-# error "Unsupported platform."
-#endif
-
-#include <boost/process/detail/file_handle.hpp>
-#include <boost/system/system_error.hpp>
-#include <boost/throw_exception.hpp>
-
-namespace boost {
-namespace process {
-namespace detail {
-
-/**
- * Simple RAII model for anonymous pipes.
- *
- * The pipe class is a simple RAII model for anonymous pipes. It
- * provides a portable constructor that allocates a new %pipe and creates
- * a pipe object that owns the two file handles associated to it: the
- * read end and the write end.
- *
- * These handles can be retrieved for modification according to
- * file_handle semantics. Optionally, their ownership can be transferred
- * to external \a file_handle objects which comes handy when the two
- * ends need to be used in different places (i.e. after a POSIX fork()
- * system call).
- *
- * Pipes can be copied following the same semantics as file handles.
- * In other words, copying a %pipe object invalidates the source one.
- *
- * \see file_handle
- */
-class pipe
-{
-public:
- /**
- * Creates a new %pipe.
- *
- * The default pipe constructor allocates a new anonymous %pipe
- * and assigns its ownership to the created pipe object. On Windows
- * when the macro BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE is defined
- * a named pipe is created. This is required if asynchronous I/O
- * should be used as asynchronous I/O is only supported by named
- * pipes on Windows.
- *
- * \throw boost::system::system_error If the anonymous %pipe
- * creation fails.
- */
- pipe()
- {
- file_handle::handle_type hs[2];
-
-#if defined(BOOST_POSIX_API)
- if (::pipe(hs) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::pipe::pipe: 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 defined(BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE)
- static unsigned int nextid = 0;
- std::string pipe = "\\\\.\\pipe\\boost_process_" + boost::lexical_cast<std::string>(::GetCurrentProcessId()) + "_" + boost::lexical_cast<std::string>(nextid++);
- hs[0] = ::CreateNamedPipeA(pipe.c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa);
- if (hs[0] == INVALID_HANDLE_VALUE)
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreateNamedPipe failed"));
- hs[1] = ::CreateFileA(pipe.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (hs[1] == INVALID_HANDLE_VALUE)
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreateFile failed"));
-
- OVERLAPPED overlapped;
- ZeroMemory(&overlapped, sizeof(overlapped));
- overlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!overlapped.hEvent)
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreateEvent failed"));
- BOOL b = ::ConnectNamedPipe(hs[0], &overlapped);
- if (!b)
- {
- if (::GetLastError() == ERROR_IO_PENDING)
- {
- if (::WaitForSingleObject(overlapped.hEvent, INFINITE)
- == WAIT_FAILED)
- {
- ::CloseHandle(overlapped.hEvent);
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: WaitForSingleObject failed"));
- }
- }
- else if (::GetLastError() != ERROR_PIPE_CONNECTED)
- {
- ::CloseHandle(overlapped.hEvent);
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: ConnectNamedPipe failed"));
- }
- }
- ::CloseHandle(overlapped.hEvent);
-# else
- if (!::CreatePipe(&hs[0], &hs[1], &sa, 0))
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreatePipe failed"));
-# endif
-#endif
-
- read_end_ = file_handle(hs[0]);
- write_end_ = file_handle(hs[1]);
- }
-
- /**
- * Returns the %pipe's read end file handle.
- *
- * Obtains a reference to the %pipe's read end file handle. Care
- * should be taken to not duplicate the returned object if ownership
- * shall remain to the %pipe.
- *
- * Duplicating the returned object invalidates its corresponding file
- * handle in the %pipe.
- *
- * \return A reference to the %pipe's read end file handle.
- */
- file_handle &rend()
- {
- return read_end_;
- }
-
- /**
- * Returns the %pipe's write end file handle.
- *
- * Obtains a reference to the %pipe's write end file handle. Care
- * should be taken to not duplicate the returned object if ownership
- * shall remain to the %pipe.
- *
- * Duplicating the returned object invalidates its corresponding file
- * handle in the %pipe.
- *
- * \return A reference to the %pipe's write end file handle.
- */
- file_handle &wend()
- {
- return write_end_;
- }
-
-private:
- /**
- * The %pipe's read end file handle.
- */
- file_handle read_end_;
-
- /**
- * The %pipe's write end file handle.
- */
- file_handle write_end_;
-};
-
-}
-}
-}
-
-#endif

Modified: sandbox/SOC/2010/process/boost/process/detail/posix_helpers.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/posix_helpers.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/detail/posix_helpers.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -13,90 +13,24 @@
 /**
  * \file boost/process/detail/posix_helper.hpp
  *
- * Includes the declaration of helper functions for the operations in a posix
- * system. It's for internal purposes.
+ * Includes the declaration of helper functions for the operations in a POSIX
+ * system.
  *
  */
 
-#include <boost/process/config.hpp>
-
-#if defined(BOOST_POSIX_API)
-# include <unistd.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-# include <stdio.h>
-#endif
-
-#include <boost/optional.hpp>
-#include <boost/process/stream_behavior.hpp>
-#include <boost/process/detail/stream_detail.hpp>
-#include <map>
-#include <string.h>
-
 #ifndef BOOST_PROCESS_POSIX_HELPERS_HPP
 #define BOOST_PROCESS_POSIX_HELPERS_HPP
 
+#include <boost/process/config.hpp>
+#include <boost/process/environment.hpp>
+#include <string>
+#include <utility>
+#include <cstring>
+
 namespace boost {
 namespace process {
 namespace detail {
 
-/*
- * This is the declaration of configure_stream function.
- * This function, given an stream_detail inherit from the current process
- * father, configure the stream.
- *
- * Note that this function is meant to be called on a brand-new child.
- *
- */
-inline configure_child_posix_stream(stream_detail &s)
-{
- switch (s.behavior)
- {
- case dummy:
- {
- std::string null_file;
- if(s.stream_type == stdin_type)
- null_file = "/dev/null";
- else
- null_file = "/dev/zero";
-
- int fd;
- if(s.stream_type == stdin_type)
- fd = ::open(null_file.c_str(), O_RDONLY);
- else
- fd = ::open(null_file.c_str(), O_WRONLY);
-
- if (fd == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::setup_input: open(2) of " + s.object.file_ + " failed"));
-
- s.object.handle_ = file_handle(fd);
- s.object.handle_.posix_remap(s.stream_handle);
- s.object.handle_.release();
- break;
- }
- case closed:
- ::close(s.stream_handle);
- break;
- case inherit:
- //do nothing since is default?
- break;
- case capture:
- if (s.stream_type == stdin_type)
- {
- s.object.pipe_.wend().close();
- s.object.pipe_.rend().posix_remap(s.stream_handle);
- }
- else
- {
- s.object.pipe_.rend().close();
- s.object.pipe_.wend().posix_remap(s.stream_handle);
- }
- break;
- default:
- BOOST_ASSERT(false);
- }
-}
-
 /**
  * Converts an environment to a char** table as used by execve().
  *
@@ -111,20 +45,21 @@
  * the environment's content. Each array entry is a
  * NULL-terminated string of the form var=value.
  */
-inline char **environment_to_envp(environment_t env)
+inline char **environment_to_envp(const environment &env)
 {
- char **envp = new char*[env.size() + 1];
+ char **envp = new char*[env.size() + 1];
 
- unsigned int i = 0;
- for (environment_t::const_iterator it = env.begin(); it != env.end(); ++it)
- {
- std::string s = (*it).first + "=" + (*it).second;
- envp[i] = new char[s.size() + 1];
- ::strncpy(envp[i], s.c_str(), s.size() + 1);
- ++i;
- }
- envp[i] = 0;
- return envp;
+ environment::size_type i = 0;
+ for (environment::const_iterator it = env.begin(); it != env.end(); ++it)
+ {
+ std::string s = it->first + "=" + it->second;
+ envp[i] = new char[s.size() + 1];
+ std::strncpy(envp[i], s.c_str(), s.size() + 1);
+ ++i;
+ }
+ envp[i] = 0;
+
+ return envp;
 }
 
 /**
@@ -152,7 +87,7 @@
     for (typename Arguments::const_iterator it = args.begin(); it != args.end(); ++it)
     {
         argv[i] = new char[it->size() + 1];
- ::strncpy(argv[i], it->c_str(), it->size() + 1);
+ std::strncpy(argv[i], it->c_str(), it->size() + 1);
         ++i;
     }
     argv[nargs] = 0;

Deleted: sandbox/SOC/2010/process/boost/process/detail/stream_detail.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/stream_detail.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
+++ (empty file)
@@ -1,124 +0,0 @@
-//
-// Boost.Process
-// ~~~~~~~~~~~~~
-//
-// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008, 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/detail/stream_detail.hpp
- *
- * Includes the declaration of the stream_detail struct.
- * It's for internal purposes
- *
- */
-
-#ifndef BOOST_PROCESS_STREAM_DETAIL_HPP
-#define BOOST_PROCESS_STREAM_DETAIL_HPP
-
-#include <boost/process/config.hpp>
-#include <boost/process/stream_behavior.hpp>
-#include <boost/process/detail/file_handle.hpp>
-#include <boost/process/detail/pipe.hpp>
-#include <boost/optional.hpp>
-#include <map>
-
-namespace boost {
-namespace process {
-namespace detail {
-
-/*
- * This is the declaration of stream_object.
- * It represents all types that can be assign of an stream object
- * representation. For example, it can point to another stream or
- * to a pipe.
- */
-struct stream_object
-{
- int desc_to;
- std::string file_;
- file_handle handle_;
- pipe pipe_;
-};
-
-/*
- * This defines the std_stream_type enum.
- * It lists all possible std stream types.
- */
-enum std_stream_type { stdin_type = 0, stdout_type = 1, stderr_type = 2 };
-
-/*
- * This is the declaration of a stream detail.
- * A stream detail contains all details from one standard stream
- * (in, out or err) that are needed for adjust it
- * when a new process is created.
- *
- * stream_end: The adress of the stream
- * stream_type: Defines if the stream is a stdin, out or error.
- * behavior: The behavior this stream will assume
- * object: The object required to this behavior (see stream_object above)
- *
- */
-struct stream_detail
-{
-#if defined(BOOST_POSIX_API)
- int stream_handle;
-#elif defined(BOOST_WINDOWS_API)
- DWORD stream_handle;
-#endif
-
- struct stream_object object;
- std_stream_type stream_type;
- stream_behavior behavior;
-
- stream_detail(std_stream_type st)
- {
- stream_type = st;
- object.pipe_ = pipe();
- switch(st)
- {
- case stdin_type:
- {
-#if defined(BOOST_POSIX_API)
- stream_handle = STDIN_FILENO;
-#elif defined(BOOST_WINDOWS_API)
- stream_handle = STD_INPUT_HANDLE;
-#endif
- break;
- }
- case stdout_type:
- {
-#if defined(BOOST_POSIX_API)
- stream_handle = STDOUT_FILENO;
-#elif defined(BOOST_WINDOWS_API)
- stream_handle = STD_OUTPUT_HANDLE;
-#endif
- break;
- }
- case stderr_type:
- {
-#if defined(BOOST_POSIX_API)
- stream_handle = STDERR_FILENO;
-#elif defined(BOOST_WINDOWS_API)
- stream_handle = STD_ERROR_HANDLE;
-#endif
- break;
- }
- default:
- {
- BOOST_ASSERT(false);
- }
- }
- }
-};
-
-}
-}
-}
-
-#endif

Modified: sandbox/SOC/2010/process/boost/process/detail/systembuf.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/systembuf.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/detail/systembuf.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -23,12 +23,12 @@
 #include <boost/process/config.hpp>
 
 #if defined(BOOST_POSIX_API)
-# include <sys/types.h>
-# include <unistd.h>
+# include <sys/types.h>
+# include <unistd.h>
 #elif defined(BOOST_WINDOWS_API)
-# include <windows.h>
+# include <windows.h>
 #else
-# error "Unsupported platform."
+# error "Unsupported platform."
 #endif
 
 #include <boost/noncopyable.hpp>

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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -14,7 +14,7 @@
  * \file boost/process/detail/helper_functions.hpp
  *
  * Includes the declaration of helper functions for the operations in a win32
- * system. It's for internal purposes.
+ * system.
  *
  */
 
@@ -22,19 +22,9 @@
 #define BOOST_PROCESS_WIN32_HELPERS_HPP
 
 #include <boost/process/config.hpp>
-#include <boost/process/child.hpp>
-#include <boost/process/detail/file_handle.hpp>
-#include <boost/process/detail/stream_detail.hpp>
-#include <boost/process/detail/pipe.hpp>
-#include <boost/scoped_ptr.hpp>
 #include <boost/shared_array.hpp>
-#include <boost/scoped_array.hpp>
-#include <boost/assert.hpp>
-#include <boost/system/system_error.hpp>
-#include <boost/throw_exception.hpp>
-#include <vector>
-#include <map>
 #include <string>
+#include <vector>
 #include <cstddef>
 #include <string.h>
 #include <windows.h>
@@ -55,7 +45,7 @@
  * the environment's content. This string is of the form
  * var1=value1\\0var2=value2\\0\\0.
  */
-inline boost::shared_array<char>environment_to_win32_strings(environment_t &env)
+inline boost::shared_array<char> environment_to_win32_strings(environment &env)
 {
     boost::shared_array<char> envp;
 
@@ -67,8 +57,7 @@
     else
     {
         std::string s;
- for (environment_t::const_iterator it = env.begin();
- it != env.end(); ++it)
+ for (environment::const_iterator it = env.begin(); it != env.end(); ++it)
         {
             s += (*it).first + "=" + (*it).second;
             s.push_back(0);
@@ -136,71 +125,6 @@
     return cmdline;
 }
 
-/*
- * This function configures the std stream of the new process.
- * 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;
-
- switch (sd.behavior)
- {
- case close:
- {
- return_handle = file_handle();
- break;
- }
- case inherit:
- {
- return_handle = file_handle::win32_dup_std(sd.stream_handle, true);
- break;
- }
- case mute:
- {
- HANDLE h;
- if(sd.stream_type == stdin_type)
- {
- h = ::CreateFileA("NUL", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- }
- else
- {
- h = ::CreateFileA("NUL", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- }
- if (h == INVALID_HANDLE_VALUE)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateFile failed"));
- return_handle = file_handle(h);
- break;
- }
-
- case capture:
- {
- if(sd.stream_type == stdin_type)
- {
- sd.object.pipe_.rend().win32_set_inheritable(true);
- return_handle = sd.object.pipe_.rend();
- }
- else
- {
- sd.object.pipe_.wend().win32_set_inheritable(true);
- return_handle = sd.object.pipe_.wend();
- }
-
- break;
- }
-
- default:
- {
- BOOST_ASSERT(false);
- }
- }
-
- return return_handle;
-}
-*/
-
 }
 }
 }

Modified: sandbox/SOC/2010/process/boost/process/environment.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/environment.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/environment.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -43,7 +43,7 @@
  * This is provided for-free by the map container used to implement this
  * type, and this behavior is required by Windows systems.
  */
-typedef std::map<std::string, std::string> environment_t;
+typedef std::map<std::string, std::string> environment;
 
 }
 }

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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -42,7 +42,6 @@
 #include <boost/process/stream_behavior.hpp>
 #include <boost/process/status.hpp>
 #include <boost/process/detail/file_handle.hpp>
-#include <boost/process/detail/stream_detail.hpp>
 #include <boost/filesystem/path.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/system/system_error.hpp>
@@ -128,7 +127,7 @@
 #endif
 
     if (result.empty())
- boost::throw_exception(boost::filesystem::filesystem_error("boost::process::find_executable_in_path: file not found", file, boost::system::errc::make_error_code(boost::system::errc::no_such_file_or_directory)));
+ boost::throw_exception(boost::filesystem::filesystem_error(BOOST_PROCESS_SOURCE_LOCATION "file not found", file, boost::system::errc::make_error_code(boost::system::errc::no_such_file_or_directory)));
 
     return result;
 }
@@ -176,22 +175,8 @@
 template <class Arguments>
 inline child create_child(const std::string &executable, Arguments args, context ctx = context())
 {
- /*
- * BEHAVIOR | BEFORE fork/CreateProcess | AFTER fork/CreateProcess
- * ---------+----------------------------------+---------------------------------
- * inherit | Windows: duplicate handle and |
- * | save it in STARTUPINFO |
- * capture | POSIX: create pipe | POSIX: use one end to initialize
- * | Windows: create pipe and save | child process object
- * | one end in STARTUPINFO |
- * mute | POSIX: open file |
- * | Windows: open file and save |
- * | handle in STARTUPINFO |
- * close | | POSIX: close explicitly
- */
-
- std::string p_name = ctx.process_name.empty() ? executable : ctx.process_name;
- args.insert(args.begin(), p_name);
+ 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();
@@ -201,11 +186,56 @@
 
     if (pid == 0)
     {
+#if defined(F_MAXFD)
+ int maxdescs = ::fcntl(-1, F_MAXFD, 0);
+ if (maxdescs == -1)
+ maxdescs = ::sysconf(_SC_OPEN_MAX);
+#else
+ int maxdescs = ::sysconf(_SC_OPEN_MAX);
+#endif
+ if (maxdescs == -1)
+ maxdescs = 1024;
+ try
+ {
+ boost::scoped_array<bool> closeflags(new bool[maxdescs]);
+ for (int i = 0; i < maxdescs; ++i)
+ closeflags[i] = true;
+
+ // setup_input(infoin, closeflags.get(), maxdescs);
+ // setup_output(infoout, closeflags.get(), maxdescs);
+
+ int stdin_fd = ctx.stdin_behavior->get_child_end();
+ if (stdin_fd != -1 && stdin_fd < maxdescs)
+ closeflags[stdin_fd] = false;
+
+ int stdout_fd = ctx.stdout_behavior->get_child_end();
+ if (stdout_fd != -1 && stdout_fd < maxdescs)
+ closeflags[stdout_fd] = false;
+
+ int stderr_fd = ctx.stderr_behavior->get_child_end();
+ if (stderr_fd != -1 && stderr_fd < maxdescs)
+ closeflags[stderr_fd] = false;
+
+ for (int i = 0; i < maxdescs; ++i)
+ {
+ if (closeflags[i])
+ ::close(i);
+ }
+
+ // setup();
+ }
+ catch (const boost::system::system_error &e)
+ {
+ ::write(STDERR_FILENO, e.what(), std::strlen(e.what()));
+ ::write(STDERR_FILENO, "\n", 1);
+ std::exit(EXIT_FAILURE);
+ }
+
         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");
+ boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), BOOST_PROCESS_SOURCE_LOCATION "execve(2) failed");
 
         for (std::size_t i = 0; i < argcv.first; ++i)
             delete[] argcv.second[i];
@@ -217,11 +247,20 @@
 
         ::write(STDERR_FILENO, e.what(), std::strlen(e.what()));
         ::write(STDERR_FILENO, "\n", 1);
+ // TODO: Use return values which is less likely used by the
+ // program which should have been started.
         std::exit(EXIT_FAILURE);
     }
 
     BOOST_ASSERT(pid > 0);
 
+ if (ctx.stdin_behavior->get_child_end() != -1)
+ ::close(ctx.stdin_behavior->get_child_end());
+ if (ctx.stdout_behavior->get_child_end() != -1)
+ ::close(ctx.stdout_behavior->get_child_end());
+ if (ctx.stderr_behavior->get_child_end() != -1)
+ ::close(ctx.stderr_behavior->get_child_end());
+
     return child(pid,
         detail::file_handle(ctx.stdin_behavior->get_parent_end()),
         detail::file_handle(ctx.stdout_behavior->get_parent_end()),
@@ -260,137 +299,6 @@
         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.
- detail::stream_detail stdin_stream(detail::stdin_type),
- stdout_stream(detail::stdout_type),
- stderr_stream(detail::stderr_type);
-
- stdin_stream.behavior = ctx.stdin_behavior;
- stdout_stream.behavior = ctx.stdout_behavior;
- stderr_stream.behavior = ctx.stderr_behavior;
-
- //adjust process name
- 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::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::create_child: fork(2) failed"));
-
- if (pid == 0)
- {
- // child process
- detail::configure_posix_stream(stdin_stream);
- detail::configure_posix_stream(stdout_stream);
- detail::configure_posix_stream(stderr_stream);
-
- 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);
-
- // error handling in case execve() failed
- 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);
-
- //adjust father pipes
- if(ctx.stdin_behavior == capture)
- {
- stdin_stream.object.pipe_.rend().close();
- fhstdin = stdin_stream.object.pipe_.wend().release();
- BOOST_ASSERT(fhstdin.valid());
- }
-
- if(ctx.stdout_behavior == capture)
- {
- stdout_stream.object.pipe_.wend().close();
- fhstdout = stdout_stream.object.pipe_.wend().release();
- BOOST_ASSERT(fhstdout.valid());
- }
-
- if(ctx.stderr_behavior == capture)
- {
- stderr_stream.object.pipe_.wend().close();
- fhstderr = stderr_stream.object.pipe_.wend().release();
- BOOST_ASSERT(fhstderr.valid());
- }
-
- return child(pid, fhstdin, fhstdout, fhstderr);
-#elif defined(BOOST_WINDOWS_API)
- //Set up the pipes when needed for the current process.
- if (stdin_stream.behavior == capture)
- fhstdin = stdin_stream.object.pipe_.wend();
- if (stdout_stream.behavior == capture)
- fhstdout = stdout_stream.object.pipe_.rend();
- if (stderr_stream.behavior == capture)
- fhstderr = stderr_stream.object.pipe_.rend();
-
- //define startup info from the new child
- STARTUPINFOA startup_info;
- ::ZeroMemory(&startup_info, sizeof(startup_info));
- startup_info.cb = sizeof(startup_info);
-
- startup_info.dwFlags |= STARTF_USESTDHANDLES;
-
- //configure std stream info for the child
- //TODO: Find a better way to do it,without file handle
- detail::file_handle fh;
-
- fh = configure_win32_stream(stdin_stream);
- if(fh.valid())
- startup_info.hStdInput = fh.get();
-
- fh = configure_win32_stream(stdout_stream);
- if(fh.valid())
- startup_info.hStdOutput = fh.get();
-
- fh = configure_win32_stream(stderr_stream);
- if(fh.valid())
- startup_info.hStdError = fh.get();
-
- //define process info and create it
- 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);
-
- //create the process
- if (::CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, 0, envstrs.get(), workdir.get(), &startup_info, &pi) == 0)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateProcess failed"));
-
- if (!::CloseHandle(pi.hThread))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::launch: CloseHandle failed"));
-
- return child(pi.dwProcessId, fhstdin, fhstdout, fhstderr, detail::file_handle(pi.hProcess));
-#endif
- */
 }
 
 inline child create_child(const std::string &executable, context ctx = context())

Deleted: sandbox/SOC/2010/process/boost/process/posix_child.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/posix_child.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
+++ (empty file)
@@ -1,181 +0,0 @@
-//
-// Boost.Process
-// ~~~~~~~~~~~~~
-//
-// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008, 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/posix_child.hpp
- *
- * Includes the declaration of the posix_child class.
- */
-
-#ifndef BOOST_PROCESS_POSIX_CHILD_HPP
-#define BOOST_PROCESS_POSIX_CHILD_HPP
-
-#include <boost/process/child.hpp>
-#include <boost/process/pistream.hpp>
-#include <boost/process/postream.hpp>
-#include <boost/process/detail/pipe.hpp>
-#include <boost/process/detail/posix_ops.hpp>
-#include <boost/process/detail/stream_info.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/assert.hpp>
-#include <map>
-#include <unistd.h>
-
-namespace boost {
-namespace process {
-
-/**
- * POSIX implementation of the Child concept.
- *
- * The posix_child class implements the Child concept in a POSIX
- * operating system.
- *
- * A POSIX child differs from a regular child (represented by a
- * child object) in that it supports more than three communication
- * channels with its parent. These channels are identified by regular
- * file descriptors (integers).
- *
- * This class is built on top of the generic child so as to allow its
- * trivial adoption. When a program is changed to use the POSIX-specific
- * context (posix_context), it will most certainly need to migrate its
- * use of the child class to posix_child. Doing so is only a matter of
- * redefining the appropriate object and later using the required extra
- * features: there should be no need to modify the existing code (e.g.
- * method calls) in any other way.
- */
-class posix_child : public child
-{
-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;
- }
- }
-
- /**
- * Constructs a new POSIX child object representing a just
- * spawned child process.
- *
- * Creates a new child object that represents the just spawned process
- * \a id.
- *
- * 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.
- */
- posix_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/process.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/process.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/process.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -22,13 +22,13 @@
 #include <boost/process/config.hpp>
 
 #if defined(BOOST_POSIX_API)
-# include <cerrno>
-# include <signal.h>
+# include <cerrno>
+# include <signal.h>
 #elif defined(BOOST_WINDOWS_API)
-# include <cstdlib>
-# include <windows.h>
+# include <cstdlib>
+# include <windows.h>
 #else
-# error "Unsupported platform."
+# error "Unsupported platform."
 #endif
 
 #include <boost/process/status.hpp>
@@ -40,10 +40,8 @@
 namespace process {
 
 /**
- * Generic implementation of the Process concept.
- *
- * The process class implements the Process concept in an operating system
- * agnostic way.
+ * The process class provides access to an unrelated process (a process
+ * which is neither a child process nor a parent process nor self).
  */
 class process
 {
@@ -105,19 +103,19 @@
     {
 #if defined(BOOST_POSIX_API)
         if (::kill(id_, force ? SIGKILL : SIGTERM) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::process::terminate: kill(2) failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("kill(2) failed");
 #elif defined(BOOST_WINDOWS_API)
         HANDLE h = ::OpenProcess(PROCESS_TERMINATE, FALSE, id_);
         if (h == NULL)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::terminate: OpenProcess failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
 
         if (!::TerminateProcess(h, EXIT_FAILURE))
         {
             ::CloseHandle(h);
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::terminate: TerminateProcess failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("TerminateProcess() failed");
         }
         if (!::CloseHandle(h))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::terminate: CloseHandle failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
 #endif
     }
 
@@ -137,14 +135,14 @@
 #if defined(BOOST_POSIX_API)
         int s;
         if (::waitpid(get_id(), &s, 0) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::process::wait: waitpid(2) failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("waitpid(2) failed");
         return status(s);
 #elif defined(BOOST_WINDOWS_API)
         // TODO
         // Boris: Where do we get the process handle from? It should be possible to fetch it
         // as we do have the process ID saved in the member variable id_. I guess
         // there must be a Windows API function to get a process handle from a process ID?
- if (::WaitForSingleObject(process_handle_.get(),INFINITE) == WAIT_FAILED)
+ if (::WaitForSingleObject(process_handle_.get(), INFINITE) == WAIT_FAILED)
         {
             // TODO
             // Boris: What should happen if WaitForSingleObject() fails? Under what
@@ -154,7 +152,7 @@
         }
         DWORD code;
         if (!::GetExitCodeProcess(process_handle_.get(), &code))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::wait: GetExitCodeProcess failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetExitCodeProcess() failed");
         return status(code);
 #endif
     }

Modified: sandbox/SOC/2010/process/boost/process/self.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/self.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/self.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -22,16 +22,16 @@
 #include <boost/process/config.hpp>
 
 #if defined(BOOST_POSIX_API)
-# include <boost/scoped_array.hpp>
-# include <cerrno>
-# include <unistd.h>
-# if defined(__APPLE__)
-# include <crt_externs.h>
-# endif
+# include <boost/scoped_array.hpp>
+# include <cerrno>
+# include <unistd.h>
+# if defined(__APPLE__)
+# include <crt_externs.h>
+# endif
 #elif defined(BOOST_WINDOWS_API)
-# include <windows.h>
+# include <windows.h>
 #else
-# error "Unsupported platform."
+# error "Unsupported platform."
 #endif
 
 #include <boost/process/process.hpp>
@@ -53,9 +53,7 @@
 namespace process {
 
 /**
- * Generic implementation of the Process concept.
- *
- * The self singleton provides access to the current process.
+ * The self class provides access to the process itself.
  */
 class self : public process, boost::noncopyable
 {
@@ -77,33 +75,32 @@
      * Returns the current process' environment variables. Modifying the
      * returned object has no effect on the current environment.
      */
- static environment_t get_environment()
+ static environment get_environment()
     {
- environment_t e;
+ environment e;
 
 #if defined(BOOST_POSIX_API)
-# if defined(__APPLE__)
+# if defined(__APPLE__)
         char **env = *_NSGetEnviron();
-# else
+# else
         char **env = ::environ;
-# endif
+# endif
 
         while (*env)
         {
             std::string s = *env;
             std::string::size_type pos = s.find('=');
- e.insert(boost::process::environment_t::value_type(s.substr(0, pos), s.substr(pos + 1)));
+ e.insert(boost::process::environment::value_type(s.substr(0, pos), s.substr(pos + 1)));
             ++env;
         }
-
 #elif defined(BOOST_WINDOWS_API)
-# ifdef GetEnvironmentStrings
-# undef GetEnvironmentStrings
-# endif
+# ifdef GetEnvironmentStrings
+# undef GetEnvironmentStrings
+# endif
 
         char *ms_environ = ::GetEnvironmentStrings();
         if (!ms_environ)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::self::get_environment: GetEnvironmentStrings failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetEnvironmentStrings() failed");
         try
         {
             char *env = ms_environ;
@@ -111,7 +108,7 @@
             {
                 std::string s = env;
                 std::string::size_type pos = s.find('=');
- e.insert(boost::process::environment_t::value_type(s.substr(0, pos), s.substr(pos + 1)));
+ e.insert(boost::process::environment::value_type(s.substr(0, pos), s.substr(pos + 1)));
                 env += s.size() + 1;
             }
         }
@@ -132,20 +129,20 @@
         errno = 0;
         long size = ::pathconf(".", _PC_PATH_MAX);
         if (size == -1 && errno)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::self::get_work_dir: pathconf(2) failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pathconf(2) failed");
         else if (size == -1)
             size = BOOST_PROCESS_POSIX_PATH_MAX;
         BOOST_ASSERT(size > 0);
         boost::scoped_array<char> cwd(new char[size]);
         if (!::getcwd(cwd.get(), size))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::self::get_work_dir: getcwd(2) failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("getcwd(2) failed");
         BOOST_ASSERT(cwd[0] != '\0');
         return cwd.get();
 #elif defined(BOOST_WINDOWS_API)
         BOOST_ASSERT(MAX_PATH > 0);
         char cwd[MAX_PATH];
         if (!::GetCurrentDirectoryA(sizeof(cwd), cwd))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::self::get_work_dir: GetCurrentDirectory failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetCurrentDirectory() failed");
         BOOST_ASSERT(cwd[0] != '\0');
         return cwd;
 #endif

Modified: sandbox/SOC/2010/process/boost/process/status.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/status.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/status.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -22,10 +22,10 @@
 #include <boost/process/config.hpp>
 
 #if defined(BOOST_POSIX_API)
-# include <sys/wait.h>
+# include <sys/wait.h>
 #elif defined(BOOST_WINDOWS_API)
 #else
-# error "Unsupported platform."
+# error "Unsupported platform."
 #endif
 
 #include <boost/assert.hpp>

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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -13,7 +13,7 @@
 /**
  * \file boost/process/stream_behavior.hpp
  *
- * Includes the declaration of the stream_behavior enumeration.
+ * Includes the declaration of the stream_behavior classes.
  *
  */
 
@@ -35,18 +35,26 @@
 namespace boost {
 namespace process {
 
+/*
+ * BEHAVIOR | BEFORE fork/CreateProcess | AFTER fork/CreateProcess
+ * ---------+----------------------------------+---------------------------------
+ * close | | POSIX: close explicitly
+ * inherit | Windows: duplicate handle and |
+ * | save it in STARTUPINFO |
+ * capture | POSIX: create pipe | POSIX: use one end to initialize
+ * | Windows: create pipe and save | child process object
+ * | one end in STARTUPINFO | Windows: same
+ * mute | POSIX: open file |
+ * | Windows: open file and save |
+ * | handle in STARTUPINFO |
+ */
+
 /**
+ * Stream behaviors are used to configure streams of a child process.
  *
- * Stream behaviors to define how standard streams are passed to a child process.
- *
- * inherit: A stream is inherited from its parent process.
- * capture: A stream is redirected to its parent process (anonymous pipe).
- * mute: A stream is redirected to /dev/null, /dev/zero or NUL.
- * close: A stream is closed.
- *
+ * The class stream_behavior is the base class all other stream behavior
+ * classes must be derived from.
  */
-// enum stream_behavior { inherit, capture, mute, close };
-
 class stream_behavior
 {
 public:
@@ -75,8 +83,19 @@
     }
 };
 
+/**
+ * Stream behavior to close streams of a child process.
+ *
+ * A child process will not be able to use its streams.
+ */
 typedef stream_behavior close;
 
+/**
+ * Stream behavior to make a child process inherit streams.
+ *
+ * A child process will use the very same streams the current
+ * process uses.
+ */
 class inherit : public stream_behavior
 {
 public:
@@ -98,6 +117,12 @@
     native_type child_end_;
 };
 
+/**
+ * Stream behavior to redirect streams with a pipe.
+ *
+ * A child process will be able to communicate with the current
+ * process.
+ */
 class capture : public stream_behavior
 {
 public:
@@ -141,50 +166,66 @@
     native_type parent_end_;
 };
 
+/**
+ * Stream behavior to redirect streams with a named pipe.
+ *
+ * A child process will be able to communicate with the current
+ * process. On Windows this stream behavior must be used for
+ * asynchronous I/O (as only named pipes support asynchronous I/O
+ * on Windows).
+ */
 class capture_with_named_pipe : public stream_behavior
 {
 public:
     enum stream_type { input_stream, output_stream };
 
- capture_with_named_pipe(stream_type stream)
+ capture_with_named_pipe(stream_type stream, std::string name = "")
     {
         native_type natives[2];
 #if defined(BOOST_POSIX_API)
+ if (name.empty())
+ // TODO: Generate unique filename.
+ name = "/tmp/fifo.1";
+
         // 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)
+ if (::mkfifo(name.c_str(), 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);
+ child_end_ = ::open(name.c_str(), O_RDONLY);
             if (child_end_ == -1)
                 BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
- parent_end_ = ::open("/tmp/fifo.1", O_WRONLY);
+ parent_end_ = ::open(name.c_str(), O_WRONLY);
             if (parent_end_ == -1)
                 BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
         }
         else
         {
- child_end_ = ::open("/tmp/fifo.1", O_WRONLY);
+ child_end_ = ::open(name.c_str(), O_WRONLY);
             if (child_end_ == -1)
                 BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
- parent_end_ = ::open("/tmp/fifo.1", O_RDONLY);
+ parent_end_ = ::open(name.c_str(), O_RDONLY);
             if (parent_end_ == -1)
                 BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
         }
 #elif defined(BOOST_WINDOWS_API)
+ if (name.empty())
+ {
+ // TODO: Make this thread-safe (create unique filename differently).
+ static unsigned int nextid = 0;
+ name = "\\\\.\\pipe\\boost_process_" + boost::lexical_cast<std::string>(::GetCurrentProcessId()) + "_" + boost::lexical_cast<std::string>(nextid++);
+ }
+
         // 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);
+ natives[0] = ::CreateNamedPipeA(name.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);
+ natives[1] = ::CreateFileA(name.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");
 
@@ -235,6 +276,12 @@
     native_type parent_end_;
 };
 
+/**
+ * Stream behavior to mute streams.
+ *
+ * A child process will be able to use streams. But data written to an
+ * output stream is discarded and data read from an input stream is 0.
+ */
 class mute : public stream_behavior
 {
 public:
@@ -249,7 +296,7 @@
             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)
+ if (child_end_ == INVALID_HANDLE_VALUE)
             BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
 #endif
     }

Modified: sandbox/SOC/2010/process/libs/process/example/child_stdin.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/child_stdin.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/example/child_stdin.cpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -10,7 +10,7 @@
 // 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 <string>
 #include <iostream>
 
@@ -20,7 +20,7 @@
 {
     std::string exe = find_executable_in_path("ftp");
     context ctx;
- ctx.stdin_behavior = capture;
+ ctx.stdin_behavior = boost::make_shared<capture>(capture(capture::input_stream));
     child c = create_child(exe, ctx);
     postream &os = c.get_stdin();
     os << "quit" << std::endl;


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