Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:05

0001 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
0002 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
0003 // Copyright (c) 2009 Boris Schaeling
0004 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
0005 // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 #ifndef BOOST_PROCESS_POSIX_PIPE_HPP
0011 #define BOOST_PROCESS_POSIX_PIPE_HPP
0012 
0013 
0014 #include <boost/process/filesystem.hpp>
0015 #include <boost/process/detail/posix/compare_handles.hpp>
0016 #include <system_error>
0017 #include <array>
0018 #include <unistd.h>
0019 #include <fcntl.h>
0020 #include <memory>
0021 
0022 namespace boost { namespace process { namespace detail { namespace posix {
0023 
0024 
0025 template<class CharT, class Traits = std::char_traits<CharT>>
0026 class basic_pipe
0027 {
0028     int _source = -1;
0029     int _sink   = -1;
0030 public:
0031     explicit basic_pipe(int source, int sink) : _source(source), _sink(sink) {}
0032     explicit basic_pipe(int source, int sink, const std::string&) : _source(source), _sink(sink) {}
0033     typedef CharT                      char_type  ;
0034     typedef          Traits            traits_type;
0035     typedef typename Traits::int_type  int_type   ;
0036     typedef typename Traits::pos_type  pos_type   ;
0037     typedef typename Traits::off_type  off_type   ;
0038     typedef          int               native_handle_type;
0039 
0040     basic_pipe()
0041     {
0042         int fds[2];
0043         if (::pipe(fds) == -1)
0044             boost::process::detail::throw_last_error("pipe(2) failed");
0045 
0046         _source = fds[0];
0047         _sink   = fds[1];
0048     }
0049     inline basic_pipe(const basic_pipe& rhs);
0050     explicit inline basic_pipe(const std::string& name);
0051     basic_pipe(basic_pipe&& lhs)  : _source(lhs._source), _sink(lhs._sink)
0052     {
0053         lhs._source = -1;
0054         lhs._sink   = -1;
0055     }
0056     inline basic_pipe& operator=(const basic_pipe& );
0057     basic_pipe& operator=(basic_pipe&& lhs)
0058     {
0059         _source = lhs._source;
0060         _sink   = lhs._sink ;
0061 
0062         lhs._source = -1;
0063         lhs._sink   = -1;
0064 
0065         return *this;
0066     }
0067     ~basic_pipe()
0068     {
0069         if (_sink   != -1)
0070             ::close(_sink);
0071         if (_source != -1)
0072             ::close(_source);
0073     }
0074     native_handle_type native_source() const {return _source;}
0075     native_handle_type native_sink  () const {return _sink;}
0076 
0077     void assign_source(native_handle_type h) { _source = h;}
0078     void assign_sink  (native_handle_type h) { _sink = h;}
0079 
0080     int_type write(const char_type * data, int_type count)
0081     {
0082         ssize_t write_len;
0083         while ((write_len = ::write(_sink, data, count * sizeof(char_type))) == -1)
0084         {
0085             //Try again if interrupted
0086             auto err = errno;
0087             if (err != EINTR)
0088                 ::boost::process::detail::throw_last_error();
0089         }
0090         return static_cast<int_type>(write_len);
0091     }
0092     int_type read(char_type * data, int_type count)
0093     {
0094         ssize_t read_len;
0095         while ((read_len = ::read(_source, data, count * sizeof(char_type))) == -1)
0096         {
0097             //Try again if interrupted
0098             auto err = errno;
0099             if (err != EINTR)
0100                 ::boost::process::detail::throw_last_error();
0101         }
0102         return static_cast<int_type>(read_len);
0103     }
0104 
0105     bool is_open() const
0106     {
0107         return (_source != -1) ||
0108                (_sink   != -1);
0109     }
0110 
0111     void close()
0112     {
0113         if (_source != -1)
0114             ::close(_source);
0115         if (_sink != -1)
0116             ::close(_sink);
0117         _source = -1;
0118         _sink   = -1;
0119     }
0120 };
0121 
0122 template<class CharT, class Traits>
0123 basic_pipe<CharT, Traits>::basic_pipe(const basic_pipe & rhs)
0124 {
0125        if (rhs._source != -1)
0126        {
0127            _source = ::dup(rhs._source);
0128            if (_source == -1)
0129                ::boost::process::detail::throw_last_error("dup() failed");
0130        }
0131     if (rhs._sink != -1)
0132     {
0133         _sink = ::dup(rhs._sink);
0134         if (_sink == -1)
0135             ::boost::process::detail::throw_last_error("dup() failed");
0136 
0137     }
0138 }
0139 
0140 template<class CharT, class Traits>
0141 basic_pipe<CharT, Traits> &basic_pipe<CharT, Traits>::operator=(const basic_pipe & rhs)
0142 {
0143        if (rhs._source != -1)
0144        {
0145            _source = ::dup(rhs._source);
0146            if (_source == -1)
0147                ::boost::process::detail::throw_last_error("dup() failed");
0148        }
0149     if (rhs._sink != -1)
0150     {
0151         _sink = ::dup(rhs._sink);
0152         if (_sink == -1)
0153             ::boost::process::detail::throw_last_error("dup() failed");
0154 
0155     }
0156     return *this;
0157 }
0158 
0159 
0160 template<class CharT, class Traits>
0161 basic_pipe<CharT, Traits>::basic_pipe(const std::string & name)
0162 {
0163     auto fifo = mkfifo(name.c_str(), 0666 );
0164             
0165     if (fifo != 0) 
0166         boost::process::detail::throw_last_error("mkfifo() failed");
0167 
0168     
0169     int  read_fd = open(name.c_str(), O_RDWR);
0170         
0171     if (read_fd == -1)
0172         boost::process::detail::throw_last_error();
0173     
0174     int write_fd = dup(read_fd);
0175     
0176     if (write_fd == -1)
0177         boost::process::detail::throw_last_error();
0178 
0179     _sink = write_fd;
0180     _source = read_fd;
0181     ::unlink(name.c_str());
0182 }
0183 
0184 template<class Char, class Traits>
0185 inline bool operator==(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs)
0186 {
0187     return compare_handles(lhs.native_source(), rhs.native_source()) &&
0188            compare_handles(lhs.native_sink(),   rhs.native_sink());
0189 }
0190 
0191 template<class Char, class Traits>
0192 inline bool operator!=(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs)
0193 {
0194     return !compare_handles(lhs.native_source(), rhs.native_source()) ||
0195            !compare_handles(lhs.native_sink(),   rhs.native_sink());
0196 }
0197 
0198 }}}}
0199 
0200 #endif