// // 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 #include #include #include #include #include #include #include #include #include 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 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 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 > 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 > output_map_t; /** * Contains all relationships between child's output file * descriptors and their corresponding pistream objects. */ output_map_t output_map_; }; } } #endif