1    	// Copyright (c) 2006, 2007 Julio M. Merino Vidal
2    	// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
3    	// Copyright (c) 2009 Boris Schaeling
4    	// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
5    	// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
6    	//
7    	// Distributed under the Boost Software License, Version 1.0. (See accompanying
8    	// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9    	
10   	#ifndef BOOST_PROCESS_POSIX_PIPE_HPP
11   	#define BOOST_PROCESS_POSIX_PIPE_HPP
12   	
13   	
14   	#include <boost/filesystem.hpp>
15   	#include <boost/process/detail/posix/compare_handles.hpp>
16   	#include <system_error>
17   	#include <array>
18   	#include <unistd.h>
19   	#include <fcntl.h>
20   	#include <memory>
21   	
22   	namespace boost { namespace process { namespace detail { namespace posix {
23   	
24   	
25   	template<class CharT, class Traits = std::char_traits<CharT>>
26   	class basic_pipe
27   	{
28   	    int _source = -1;
29   	    int _sink   = -1;
30   	public:
31   	    explicit basic_pipe(int source, int sink) : _source(source), _sink(sink) {}
32   	    explicit basic_pipe(int source, int sink, const std::string&) : _source(source), _sink(sink) {}
33   	    typedef CharT                      char_type  ;
34   	    typedef          Traits            traits_type;
35   	    typedef typename Traits::int_type  int_type   ;
36   	    typedef typename Traits::pos_type  pos_type   ;
37   	    typedef typename Traits::off_type  off_type   ;
38   	    typedef          int               native_handle_type;
39   	
40   	    basic_pipe()
41   	    {
42   	        int fds[2];
43   	        if (::pipe(fds) == -1)
(1) Event fun_call_w_exception: Called function throws an exception of type "boost::process::process_error". [details]
44   	            boost::process::detail::throw_last_error("pipe(2) failed");
45   	
46   	        _source = fds[0];
47   	        _sink   = fds[1];
48   	    }
49   	    inline basic_pipe(const basic_pipe& rhs);
50   	    explicit inline basic_pipe(const std::string& name);
51   	    basic_pipe(basic_pipe&& lhs)  : _source(lhs._source), _sink(lhs._sink)
52   	    {
53   	        lhs._source = -1;
54   	        lhs._sink   = -1;
55   	    }
56   	    inline basic_pipe& operator=(const basic_pipe& );
57   	    basic_pipe& operator=(basic_pipe&& lhs)
58   	    {
59   	        _source = lhs._source;
60   	        _sink   = lhs._sink ;
61   	
62   	        lhs._source = -1;
63   	        lhs._sink   = -1;
64   	
65   	        return *this;
66   	    }
67   	    ~basic_pipe()
68   	    {
69   	        if (_sink   != -1)
70   	            ::close(_sink);
71   	        if (_source != -1)
72   	            ::close(_source);
73   	    }
74   	    native_handle_type native_source() const {return _source;}
75   	    native_handle_type native_sink  () const {return _sink;}
76   	
77   	    void assign_source(native_handle_type h) { _source = h;}
78   	    void assign_sink  (native_handle_type h) { _sink = h;}
79   	
80   	
81   	
82   	
83   	    int_type write(const char_type * data, int_type count)
84   	    {
85   	        auto write_len = ::write(_sink, data, count * sizeof(char_type));
86   	        if (write_len == -1)
87   	            ::boost::process::detail::throw_last_error();
88   	
89   	        return write_len;
90   	    }
91   	    int_type read(char_type * data, int_type count)
92   	    {
93   	        auto read_len = ::read(_source, data, count * sizeof(char_type));
94   	        if (read_len == -1)
95   	            ::boost::process::detail::throw_last_error();
96   	
97   	        return read_len;
98   	    }
99   	
100  	    bool is_open()
101  	    {
102  	        return (_source != -1) ||
103  	               (_sink   != -1);
104  	    }
105  	
106  	    void close()
107  	    {
108  	        if (_source != -1)
109  	            ::close(_source);
110  	        if (_sink != -1)
111  	            ::close(_sink);
112  	        _source = -1;
113  	        _sink   = -1;
114  	    }
115  	};
116  	
117  	template<class CharT, class Traits>
118  	basic_pipe<CharT, Traits>::basic_pipe(const basic_pipe & rhs)
119  	{
120  	       if (rhs._source != -1)
121  	       {
122  	           _source = ::dup(rhs._source);
123  	           if (_source == -1)
124  	               ::boost::process::detail::throw_last_error("dup() failed");
125  	       }
126  	    if (rhs._sink != -1)
127  	    {
128  	        _sink = ::dup(rhs._sink);
129  	        if (_sink == -1)
130  	            ::boost::process::detail::throw_last_error("dup() failed");
131  	
132  	    }
133  	}
134  	
135  	template<class CharT, class Traits>
136  	basic_pipe<CharT, Traits> &basic_pipe<CharT, Traits>::operator=(const basic_pipe & rhs)
137  	{
138  	       if (rhs._source != -1)
139  	       {
140  	           _source = ::dup(rhs._source);
141  	           if (_source == -1)
142  	               ::boost::process::detail::throw_last_error("dup() failed");
143  	       }
144  	    if (rhs._sink != -1)
145  	    {
146  	        _sink = ::dup(rhs._sink);
147  	        if (_sink == -1)
148  	            ::boost::process::detail::throw_last_error("dup() failed");
149  	
150  	    }
151  	    return *this;
152  	}
153  	
154  	
155  	template<class CharT, class Traits>
156  	basic_pipe<CharT, Traits>::basic_pipe(const std::string & name)
157  	{
158  	    auto fifo = mkfifo(name.c_str(), 0666 );
159  	            
160  	    if (fifo != 0) 
161  	        boost::process::detail::throw_last_error("mkfifo() failed");
162  	
163  	    
164  	    int  read_fd = open(name.c_str(), O_RDWR);
165  	        
166  	    if (read_fd == -1)
167  	        boost::process::detail::throw_last_error();
168  	    
169  	    int write_fd = dup(read_fd);
170  	    
171  	    if (write_fd == -1)
172  	        boost::process::detail::throw_last_error();
173  	
174  	    _sink = write_fd;
175  	    _source = read_fd;
176  	    ::unlink(name.c_str());
177  	}
178  	
179  	template<class Char, class Traits>
180  	inline bool operator==(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs)
181  	{
182  	    return compare_handles(lhs.native_source(), rhs.native_source()) &&
183  	           compare_handles(lhs.native_sink(),   rhs.native_sink());
184  	}
185  	
186  	template<class Char, class Traits>
187  	inline bool operator!=(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs)
188  	{
189  	    return !compare_handles(lhs.native_source(), rhs.native_source()) ||
190  	           !compare_handles(lhs.native_sink(),   rhs.native_sink());
191  	}
192  	
193  	}}}}
194  	
195  	#endif
196