File indexing completed on 2025-01-18 09:50:05
0001
0002
0003
0004
0005
0006
0007
0008
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
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
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