// 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 // Copyright (c) 2011, 2012 Jeff Flinn, 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) #ifndef BOOST_PROCESS_POSIX_PIPE_HPP #define BOOST_PROCESS_POSIX_PIPE_HPP #include #include #include #include #include #include #include namespace boost { namespace process { namespace detail { namespace posix { template> class basic_pipe { int _source = -1; int _sink = -1; public: explicit basic_pipe(int source, int sink) : _source(source), _sink(sink) {} explicit basic_pipe(int source, int sink, const std::string&) : _source(source), _sink(sink) {} typedef CharT char_type ; typedef Traits traits_type; typedef typename Traits::int_type int_type ; typedef typename Traits::pos_type pos_type ; typedef typename Traits::off_type off_type ; typedef int native_handle_type; basic_pipe() { int fds[2]; if (::pipe(fds) == -1) boost::process::detail::throw_last_error("pipe(2) failed"); _source = fds[0]; _sink = fds[1]; } inline basic_pipe(const basic_pipe& rhs); explicit inline basic_pipe(const std::string& name); basic_pipe(basic_pipe&& lhs) : _source(lhs._source), _sink(lhs._sink) { lhs._source = -1; lhs._sink = -1; } inline basic_pipe& operator=(const basic_pipe& ); basic_pipe& operator=(basic_pipe&& lhs) { _source = lhs._source; _sink = lhs._sink ; lhs._source = -1; lhs._sink = -1; return *this; } ~basic_pipe() { if (_sink != -1) ::close(_sink); if (_source != -1) ::close(_source); } native_handle_type native_source() const {return _source;} native_handle_type native_sink () const {return _sink;} void assign_source(native_handle_type h) { _source = h;} void assign_sink (native_handle_type h) { _sink = h;} int_type write(const char_type * data, int_type count) { int_type write_len; while ((write_len = ::write(_sink, data, count * sizeof(char_type))) == -1) { //Try again if interrupted auto err = errno; if (err != EINTR) ::boost::process::detail::throw_last_error(); } return write_len; } int_type read(char_type * data, int_type count) { int_type read_len; while ((read_len = ::read(_source, data, count * sizeof(char_type))) == -1) { //Try again if interrupted auto err = errno; if (err != EINTR) ::boost::process::detail::throw_last_error(); } return read_len; } bool is_open() const { return (_source != -1) || (_sink != -1); } void close() { if (_source != -1) ::close(_source); if (_sink != -1) ::close(_sink); _source = -1; _sink = -1; } }; template basic_pipe::basic_pipe(const basic_pipe & rhs) { if (rhs._source != -1) { _source = ::dup(rhs._source); if (_source == -1) ::boost::process::detail::throw_last_error("dup() failed"); } if (rhs._sink != -1) { _sink = ::dup(rhs._sink); if (_sink == -1) ::boost::process::detail::throw_last_error("dup() failed"); } } template basic_pipe &basic_pipe::operator=(const basic_pipe & rhs) { if (rhs._source != -1) { _source = ::dup(rhs._source); if (_source == -1) ::boost::process::detail::throw_last_error("dup() failed"); } if (rhs._sink != -1) { _sink = ::dup(rhs._sink); if (_sink == -1) ::boost::process::detail::throw_last_error("dup() failed"); } return *this; } template basic_pipe::basic_pipe(const std::string & name) { auto fifo = mkfifo(name.c_str(), 0666 ); if (fifo != 0) boost::process::detail::throw_last_error("mkfifo() failed"); int read_fd = open(name.c_str(), O_RDWR); if (read_fd == -1) boost::process::detail::throw_last_error(); int write_fd = dup(read_fd); if (write_fd == -1) boost::process::detail::throw_last_error(); _sink = write_fd; _source = read_fd; ::unlink(name.c_str()); } template inline bool operator==(const basic_pipe & lhs, const basic_pipe & rhs) { return compare_handles(lhs.native_source(), rhs.native_source()) && compare_handles(lhs.native_sink(), rhs.native_sink()); } template inline bool operator!=(const basic_pipe & lhs, const basic_pipe & rhs) { return !compare_handles(lhs.native_source(), rhs.native_source()) || !compare_handles(lhs.native_sink(), rhs.native_sink()); } }}}} #endif