You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
6.2 KiB
178 lines
6.2 KiB
//
|
|
// Boost.Process
|
|
// ~~~~~~~~~~~~~
|
|
//
|
|
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
// Copyright (c) 2008, 2009 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
|
|
|