xref: /minix3/external/bsd/atf/dist/tools/io.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc //
2*0a6a1f1dSLionel Sambuc // Automated Testing Framework (atf)
3*0a6a1f1dSLionel Sambuc //
4*0a6a1f1dSLionel Sambuc // Copyright (c) 2007 The NetBSD Foundation, Inc.
5*0a6a1f1dSLionel Sambuc // All rights reserved.
6*0a6a1f1dSLionel Sambuc //
7*0a6a1f1dSLionel Sambuc // Redistribution and use in source and binary forms, with or without
8*0a6a1f1dSLionel Sambuc // modification, are permitted provided that the following conditions
9*0a6a1f1dSLionel Sambuc // are met:
10*0a6a1f1dSLionel Sambuc // 1. Redistributions of source code must retain the above copyright
11*0a6a1f1dSLionel Sambuc //    notice, this list of conditions and the following disclaimer.
12*0a6a1f1dSLionel Sambuc // 2. Redistributions in binary form must reproduce the above copyright
13*0a6a1f1dSLionel Sambuc //    notice, this list of conditions and the following disclaimer in the
14*0a6a1f1dSLionel Sambuc //    documentation and/or other materials provided with the distribution.
15*0a6a1f1dSLionel Sambuc //
16*0a6a1f1dSLionel Sambuc // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*0a6a1f1dSLionel Sambuc // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*0a6a1f1dSLionel Sambuc // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*0a6a1f1dSLionel Sambuc // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*0a6a1f1dSLionel Sambuc // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*0a6a1f1dSLionel Sambuc // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*0a6a1f1dSLionel Sambuc // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*0a6a1f1dSLionel Sambuc // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*0a6a1f1dSLionel Sambuc // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*0a6a1f1dSLionel Sambuc // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*0a6a1f1dSLionel Sambuc // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*0a6a1f1dSLionel Sambuc // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*0a6a1f1dSLionel Sambuc //
29*0a6a1f1dSLionel Sambuc 
30*0a6a1f1dSLionel Sambuc extern "C" {
31*0a6a1f1dSLionel Sambuc #include <fcntl.h>
32*0a6a1f1dSLionel Sambuc #include <poll.h>
33*0a6a1f1dSLionel Sambuc #include <signal.h>
34*0a6a1f1dSLionel Sambuc #include <unistd.h>
35*0a6a1f1dSLionel Sambuc }
36*0a6a1f1dSLionel Sambuc 
37*0a6a1f1dSLionel Sambuc #include <cassert>
38*0a6a1f1dSLionel Sambuc #include <cerrno>
39*0a6a1f1dSLionel Sambuc #include <cstring>
40*0a6a1f1dSLionel Sambuc 
41*0a6a1f1dSLionel Sambuc #include "auto_array.hpp"
42*0a6a1f1dSLionel Sambuc #include "exceptions.hpp"
43*0a6a1f1dSLionel Sambuc #include "io.hpp"
44*0a6a1f1dSLionel Sambuc 
45*0a6a1f1dSLionel Sambuc namespace impl = tools::io;
46*0a6a1f1dSLionel Sambuc #define IMPL_NAME "tools::io"
47*0a6a1f1dSLionel Sambuc 
48*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
49*0a6a1f1dSLionel Sambuc // The "file_handle" class.
50*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
51*0a6a1f1dSLionel Sambuc 
file_handle(void)52*0a6a1f1dSLionel Sambuc impl::file_handle::file_handle(void) :
53*0a6a1f1dSLionel Sambuc     m_handle(invalid_value())
54*0a6a1f1dSLionel Sambuc {
55*0a6a1f1dSLionel Sambuc }
56*0a6a1f1dSLionel Sambuc 
file_handle(handle_type h)57*0a6a1f1dSLionel Sambuc impl::file_handle::file_handle(handle_type h) :
58*0a6a1f1dSLionel Sambuc     m_handle(h)
59*0a6a1f1dSLionel Sambuc {
60*0a6a1f1dSLionel Sambuc     assert(m_handle != invalid_value());
61*0a6a1f1dSLionel Sambuc }
62*0a6a1f1dSLionel Sambuc 
file_handle(const file_handle & fh)63*0a6a1f1dSLionel Sambuc impl::file_handle::file_handle(const file_handle& fh) :
64*0a6a1f1dSLionel Sambuc     m_handle(fh.m_handle)
65*0a6a1f1dSLionel Sambuc {
66*0a6a1f1dSLionel Sambuc     fh.m_handle = invalid_value();
67*0a6a1f1dSLionel Sambuc }
68*0a6a1f1dSLionel Sambuc 
~file_handle(void)69*0a6a1f1dSLionel Sambuc impl::file_handle::~file_handle(void)
70*0a6a1f1dSLionel Sambuc {
71*0a6a1f1dSLionel Sambuc     if (is_valid())
72*0a6a1f1dSLionel Sambuc         close();
73*0a6a1f1dSLionel Sambuc }
74*0a6a1f1dSLionel Sambuc 
75*0a6a1f1dSLionel Sambuc impl::file_handle&
operator =(const file_handle & fh)76*0a6a1f1dSLionel Sambuc impl::file_handle::operator=(const file_handle& fh)
77*0a6a1f1dSLionel Sambuc {
78*0a6a1f1dSLionel Sambuc     m_handle = fh.m_handle;
79*0a6a1f1dSLionel Sambuc     fh.m_handle = invalid_value();
80*0a6a1f1dSLionel Sambuc 
81*0a6a1f1dSLionel Sambuc     return *this;
82*0a6a1f1dSLionel Sambuc }
83*0a6a1f1dSLionel Sambuc 
84*0a6a1f1dSLionel Sambuc bool
is_valid(void) const85*0a6a1f1dSLionel Sambuc impl::file_handle::is_valid(void)
86*0a6a1f1dSLionel Sambuc     const
87*0a6a1f1dSLionel Sambuc {
88*0a6a1f1dSLionel Sambuc     return m_handle != invalid_value();
89*0a6a1f1dSLionel Sambuc }
90*0a6a1f1dSLionel Sambuc 
91*0a6a1f1dSLionel Sambuc void
close(void)92*0a6a1f1dSLionel Sambuc impl::file_handle::close(void)
93*0a6a1f1dSLionel Sambuc {
94*0a6a1f1dSLionel Sambuc     assert(is_valid());
95*0a6a1f1dSLionel Sambuc 
96*0a6a1f1dSLionel Sambuc     ::close(m_handle);
97*0a6a1f1dSLionel Sambuc 
98*0a6a1f1dSLionel Sambuc     m_handle = invalid_value();
99*0a6a1f1dSLionel Sambuc }
100*0a6a1f1dSLionel Sambuc 
101*0a6a1f1dSLionel Sambuc impl::file_handle::handle_type
disown(void)102*0a6a1f1dSLionel Sambuc impl::file_handle::disown(void)
103*0a6a1f1dSLionel Sambuc {
104*0a6a1f1dSLionel Sambuc     assert(is_valid());
105*0a6a1f1dSLionel Sambuc 
106*0a6a1f1dSLionel Sambuc     handle_type h = m_handle;
107*0a6a1f1dSLionel Sambuc     m_handle = invalid_value();
108*0a6a1f1dSLionel Sambuc     return h;
109*0a6a1f1dSLionel Sambuc }
110*0a6a1f1dSLionel Sambuc 
111*0a6a1f1dSLionel Sambuc impl::file_handle::handle_type
get(void) const112*0a6a1f1dSLionel Sambuc impl::file_handle::get(void)
113*0a6a1f1dSLionel Sambuc     const
114*0a6a1f1dSLionel Sambuc {
115*0a6a1f1dSLionel Sambuc     assert(is_valid());
116*0a6a1f1dSLionel Sambuc 
117*0a6a1f1dSLionel Sambuc     return m_handle;
118*0a6a1f1dSLionel Sambuc }
119*0a6a1f1dSLionel Sambuc 
120*0a6a1f1dSLionel Sambuc void
posix_remap(handle_type h)121*0a6a1f1dSLionel Sambuc impl::file_handle::posix_remap(handle_type h)
122*0a6a1f1dSLionel Sambuc {
123*0a6a1f1dSLionel Sambuc     assert(is_valid());
124*0a6a1f1dSLionel Sambuc 
125*0a6a1f1dSLionel Sambuc     if (m_handle == h)
126*0a6a1f1dSLionel Sambuc         return;
127*0a6a1f1dSLionel Sambuc 
128*0a6a1f1dSLionel Sambuc     if (::dup2(m_handle, h) == -1)
129*0a6a1f1dSLionel Sambuc         throw tools::system_error(IMPL_NAME "::file_handle::posix_remap",
130*0a6a1f1dSLionel Sambuc                                 "dup2(2) failed", errno);
131*0a6a1f1dSLionel Sambuc 
132*0a6a1f1dSLionel Sambuc     if (::close(m_handle) == -1) {
133*0a6a1f1dSLionel Sambuc         ::close(h);
134*0a6a1f1dSLionel Sambuc         throw tools::system_error(IMPL_NAME "::file_handle::posix_remap",
135*0a6a1f1dSLionel Sambuc                                 "close(2) failed", errno);
136*0a6a1f1dSLionel Sambuc     }
137*0a6a1f1dSLionel Sambuc 
138*0a6a1f1dSLionel Sambuc     m_handle = h;
139*0a6a1f1dSLionel Sambuc }
140*0a6a1f1dSLionel Sambuc 
141*0a6a1f1dSLionel Sambuc impl::file_handle::handle_type
invalid_value(void)142*0a6a1f1dSLionel Sambuc impl::file_handle::invalid_value(void)
143*0a6a1f1dSLionel Sambuc {
144*0a6a1f1dSLionel Sambuc     return -1;
145*0a6a1f1dSLionel Sambuc }
146*0a6a1f1dSLionel Sambuc 
147*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
148*0a6a1f1dSLionel Sambuc // The "systembuf" class.
149*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
150*0a6a1f1dSLionel Sambuc 
systembuf(handle_type h,std::size_t bufsize)151*0a6a1f1dSLionel Sambuc impl::systembuf::systembuf(handle_type h, std::size_t bufsize) :
152*0a6a1f1dSLionel Sambuc     m_handle(h),
153*0a6a1f1dSLionel Sambuc     m_bufsize(bufsize),
154*0a6a1f1dSLionel Sambuc     m_read_buf(NULL),
155*0a6a1f1dSLionel Sambuc     m_write_buf(NULL)
156*0a6a1f1dSLionel Sambuc {
157*0a6a1f1dSLionel Sambuc     assert(m_handle >= 0);
158*0a6a1f1dSLionel Sambuc     assert(m_bufsize > 0);
159*0a6a1f1dSLionel Sambuc 
160*0a6a1f1dSLionel Sambuc     try {
161*0a6a1f1dSLionel Sambuc         m_read_buf = new char[bufsize];
162*0a6a1f1dSLionel Sambuc         m_write_buf = new char[bufsize];
163*0a6a1f1dSLionel Sambuc     } catch (...) {
164*0a6a1f1dSLionel Sambuc         if (m_read_buf != NULL)
165*0a6a1f1dSLionel Sambuc             delete [] m_read_buf;
166*0a6a1f1dSLionel Sambuc         if (m_write_buf != NULL)
167*0a6a1f1dSLionel Sambuc             delete [] m_write_buf;
168*0a6a1f1dSLionel Sambuc         throw;
169*0a6a1f1dSLionel Sambuc     }
170*0a6a1f1dSLionel Sambuc 
171*0a6a1f1dSLionel Sambuc     setp(m_write_buf, m_write_buf + m_bufsize);
172*0a6a1f1dSLionel Sambuc }
173*0a6a1f1dSLionel Sambuc 
~systembuf(void)174*0a6a1f1dSLionel Sambuc impl::systembuf::~systembuf(void)
175*0a6a1f1dSLionel Sambuc {
176*0a6a1f1dSLionel Sambuc     delete [] m_read_buf;
177*0a6a1f1dSLionel Sambuc     delete [] m_write_buf;
178*0a6a1f1dSLionel Sambuc }
179*0a6a1f1dSLionel Sambuc 
180*0a6a1f1dSLionel Sambuc impl::systembuf::int_type
underflow(void)181*0a6a1f1dSLionel Sambuc impl::systembuf::underflow(void)
182*0a6a1f1dSLionel Sambuc {
183*0a6a1f1dSLionel Sambuc     assert(gptr() >= egptr());
184*0a6a1f1dSLionel Sambuc 
185*0a6a1f1dSLionel Sambuc     bool ok;
186*0a6a1f1dSLionel Sambuc     ssize_t cnt = ::read(m_handle, m_read_buf, m_bufsize);
187*0a6a1f1dSLionel Sambuc     ok = (cnt != -1 && cnt != 0);
188*0a6a1f1dSLionel Sambuc 
189*0a6a1f1dSLionel Sambuc     if (!ok)
190*0a6a1f1dSLionel Sambuc         return traits_type::eof();
191*0a6a1f1dSLionel Sambuc     else {
192*0a6a1f1dSLionel Sambuc         setg(m_read_buf, m_read_buf, m_read_buf + cnt);
193*0a6a1f1dSLionel Sambuc         return traits_type::to_int_type(*gptr());
194*0a6a1f1dSLionel Sambuc     }
195*0a6a1f1dSLionel Sambuc }
196*0a6a1f1dSLionel Sambuc 
197*0a6a1f1dSLionel Sambuc impl::systembuf::int_type
overflow(int c)198*0a6a1f1dSLionel Sambuc impl::systembuf::overflow(int c)
199*0a6a1f1dSLionel Sambuc {
200*0a6a1f1dSLionel Sambuc     assert(pptr() >= epptr());
201*0a6a1f1dSLionel Sambuc     if (sync() == -1)
202*0a6a1f1dSLionel Sambuc         return traits_type::eof();
203*0a6a1f1dSLionel Sambuc     if (!traits_type::eq_int_type(c, traits_type::eof())) {
204*0a6a1f1dSLionel Sambuc         traits_type::assign(*pptr(), c);
205*0a6a1f1dSLionel Sambuc         pbump(1);
206*0a6a1f1dSLionel Sambuc     }
207*0a6a1f1dSLionel Sambuc     return traits_type::not_eof(c);
208*0a6a1f1dSLionel Sambuc }
209*0a6a1f1dSLionel Sambuc 
210*0a6a1f1dSLionel Sambuc int
sync(void)211*0a6a1f1dSLionel Sambuc impl::systembuf::sync(void)
212*0a6a1f1dSLionel Sambuc {
213*0a6a1f1dSLionel Sambuc     ssize_t cnt = pptr() - pbase();
214*0a6a1f1dSLionel Sambuc 
215*0a6a1f1dSLionel Sambuc     bool ok;
216*0a6a1f1dSLionel Sambuc     ok = ::write(m_handle, pbase(), cnt) == cnt;
217*0a6a1f1dSLionel Sambuc 
218*0a6a1f1dSLionel Sambuc     if (ok)
219*0a6a1f1dSLionel Sambuc         pbump(-cnt);
220*0a6a1f1dSLionel Sambuc     return ok ? 0 : -1;
221*0a6a1f1dSLionel Sambuc }
222*0a6a1f1dSLionel Sambuc 
223*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
224*0a6a1f1dSLionel Sambuc // The "pistream" class.
225*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
226*0a6a1f1dSLionel Sambuc 
pistream(const int fd)227*0a6a1f1dSLionel Sambuc impl::pistream::pistream(const int fd) :
228*0a6a1f1dSLionel Sambuc     std::istream(NULL),
229*0a6a1f1dSLionel Sambuc     m_systembuf(fd)
230*0a6a1f1dSLionel Sambuc {
231*0a6a1f1dSLionel Sambuc     rdbuf(&m_systembuf);
232*0a6a1f1dSLionel Sambuc }
233*0a6a1f1dSLionel Sambuc 
234*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
235*0a6a1f1dSLionel Sambuc // The "muxer" class.
236*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
237*0a6a1f1dSLionel Sambuc 
238*0a6a1f1dSLionel Sambuc static int
safe_poll(struct pollfd fds[],nfds_t nfds,int timeout)239*0a6a1f1dSLionel Sambuc safe_poll(struct pollfd fds[], nfds_t nfds, int timeout)
240*0a6a1f1dSLionel Sambuc {
241*0a6a1f1dSLionel Sambuc     int ret = ::poll(fds, nfds, timeout);
242*0a6a1f1dSLionel Sambuc     if (ret == -1) {
243*0a6a1f1dSLionel Sambuc         if (errno == EINTR)
244*0a6a1f1dSLionel Sambuc             ret = 0;
245*0a6a1f1dSLionel Sambuc         else
246*0a6a1f1dSLionel Sambuc             throw tools::system_error(IMPL_NAME "::safe_poll", "poll(2) failed",
247*0a6a1f1dSLionel Sambuc                                     errno);
248*0a6a1f1dSLionel Sambuc     }
249*0a6a1f1dSLionel Sambuc     assert(ret >= 0);
250*0a6a1f1dSLionel Sambuc     return ret;
251*0a6a1f1dSLionel Sambuc }
252*0a6a1f1dSLionel Sambuc 
253*0a6a1f1dSLionel Sambuc static size_t
safe_read(const int fd,void * buffer,const size_t nbytes,const bool report_errors)254*0a6a1f1dSLionel Sambuc safe_read(const int fd, void* buffer, const size_t nbytes,
255*0a6a1f1dSLionel Sambuc           const bool report_errors)
256*0a6a1f1dSLionel Sambuc {
257*0a6a1f1dSLionel Sambuc     int ret;
258*0a6a1f1dSLionel Sambuc     while ((ret = ::read(fd, buffer, nbytes)) == -1 && errno == EINTR) {}
259*0a6a1f1dSLionel Sambuc     if (ret == -1) {
260*0a6a1f1dSLionel Sambuc         assert(errno != EINTR);
261*0a6a1f1dSLionel Sambuc 
262*0a6a1f1dSLionel Sambuc         if (report_errors)
263*0a6a1f1dSLionel Sambuc             throw tools::system_error(IMPL_NAME "::safe_read", "read(2) failed",
264*0a6a1f1dSLionel Sambuc                                     errno);
265*0a6a1f1dSLionel Sambuc         else
266*0a6a1f1dSLionel Sambuc             ret = 0;
267*0a6a1f1dSLionel Sambuc     }
268*0a6a1f1dSLionel Sambuc     assert(ret >= 0);
269*0a6a1f1dSLionel Sambuc     return static_cast< size_t >(ret);
270*0a6a1f1dSLionel Sambuc }
271*0a6a1f1dSLionel Sambuc 
muxer(const int * fds,const size_t nfds,const size_t bufsize)272*0a6a1f1dSLionel Sambuc impl::muxer::muxer(const int* fds, const size_t nfds, const size_t bufsize) :
273*0a6a1f1dSLionel Sambuc     m_fds(fds),
274*0a6a1f1dSLionel Sambuc     m_nfds(nfds),
275*0a6a1f1dSLionel Sambuc     m_bufsize(bufsize),
276*0a6a1f1dSLionel Sambuc     m_buffers(new std::string[nfds])
277*0a6a1f1dSLionel Sambuc {
278*0a6a1f1dSLionel Sambuc }
279*0a6a1f1dSLionel Sambuc 
~muxer(void)280*0a6a1f1dSLionel Sambuc impl::muxer::~muxer(void)
281*0a6a1f1dSLionel Sambuc {
282*0a6a1f1dSLionel Sambuc }
283*0a6a1f1dSLionel Sambuc 
284*0a6a1f1dSLionel Sambuc size_t
read_one(const size_t index,const int fd,std::string & accum,const bool report_errors)285*0a6a1f1dSLionel Sambuc impl::muxer::read_one(const size_t index, const int fd, std::string& accum,
286*0a6a1f1dSLionel Sambuc                       const bool report_errors)
287*0a6a1f1dSLionel Sambuc {
288*0a6a1f1dSLionel Sambuc     tools::auto_array< char > buffer(new char[m_bufsize]);
289*0a6a1f1dSLionel Sambuc     const size_t nbytes = safe_read(fd, buffer.get(), m_bufsize - 1,
290*0a6a1f1dSLionel Sambuc                                     report_errors);
291*0a6a1f1dSLionel Sambuc     assert(nbytes < m_bufsize);
292*0a6a1f1dSLionel Sambuc     buffer[nbytes] = '\0';
293*0a6a1f1dSLionel Sambuc 
294*0a6a1f1dSLionel Sambuc     std::string line(accum);
295*0a6a1f1dSLionel Sambuc 
296*0a6a1f1dSLionel Sambuc     size_t line_start = 0;
297*0a6a1f1dSLionel Sambuc     for (size_t i = 0; i < nbytes; i++) {
298*0a6a1f1dSLionel Sambuc         if (buffer[i] == '\n') {
299*0a6a1f1dSLionel Sambuc             line_callback(index, line);
300*0a6a1f1dSLionel Sambuc             line.clear();
301*0a6a1f1dSLionel Sambuc             accum.clear();
302*0a6a1f1dSLionel Sambuc             line_start = i + 1;
303*0a6a1f1dSLionel Sambuc         } else if (buffer[i] == '\r') {
304*0a6a1f1dSLionel Sambuc             // Do nothing.
305*0a6a1f1dSLionel Sambuc         } else {
306*0a6a1f1dSLionel Sambuc             line.append(1, buffer[i]);
307*0a6a1f1dSLionel Sambuc         }
308*0a6a1f1dSLionel Sambuc     }
309*0a6a1f1dSLionel Sambuc     accum.append(&buffer[line_start]);
310*0a6a1f1dSLionel Sambuc 
311*0a6a1f1dSLionel Sambuc     return nbytes;
312*0a6a1f1dSLionel Sambuc }
313*0a6a1f1dSLionel Sambuc 
314*0a6a1f1dSLionel Sambuc void
mux(volatile const bool & terminate)315*0a6a1f1dSLionel Sambuc impl::muxer::mux(volatile const bool& terminate)
316*0a6a1f1dSLionel Sambuc {
317*0a6a1f1dSLionel Sambuc     tools::auto_array< struct pollfd > poll_fds(new struct pollfd[m_nfds]);
318*0a6a1f1dSLionel Sambuc     for (size_t i = 0; i < m_nfds; i++) {
319*0a6a1f1dSLionel Sambuc         poll_fds[i].fd = m_fds[i];
320*0a6a1f1dSLionel Sambuc         poll_fds[i].events = POLLIN;
321*0a6a1f1dSLionel Sambuc     }
322*0a6a1f1dSLionel Sambuc 
323*0a6a1f1dSLionel Sambuc     size_t nactive = m_nfds;
324*0a6a1f1dSLionel Sambuc     while (nactive > 0 && !terminate) {
325*0a6a1f1dSLionel Sambuc         int ret;
326*0a6a1f1dSLionel Sambuc         while (!terminate && (ret = safe_poll(poll_fds.get(), 2, 250)) == 0) {}
327*0a6a1f1dSLionel Sambuc 
328*0a6a1f1dSLionel Sambuc         for (size_t i = 0; !terminate && i < m_nfds; i++) {
329*0a6a1f1dSLionel Sambuc             if (poll_fds[i].events == 0)
330*0a6a1f1dSLionel Sambuc                 continue;
331*0a6a1f1dSLionel Sambuc 
332*0a6a1f1dSLionel Sambuc             if (poll_fds[i].revents & POLLHUP) {
333*0a6a1f1dSLionel Sambuc                 // Any data still available at this point will be processed by
334*0a6a1f1dSLionel Sambuc                 // a call to the flush method.
335*0a6a1f1dSLionel Sambuc                 poll_fds[i].events = 0;
336*0a6a1f1dSLionel Sambuc 
337*0a6a1f1dSLionel Sambuc                 assert(nactive >= 1);
338*0a6a1f1dSLionel Sambuc                 nactive--;
339*0a6a1f1dSLionel Sambuc             } else if (poll_fds[i].revents & (POLLIN | POLLRDNORM | POLLRDBAND |
340*0a6a1f1dSLionel Sambuc                                        POLLPRI)) {
341*0a6a1f1dSLionel Sambuc                 (void)read_one(i, poll_fds[i].fd, m_buffers[i], true);
342*0a6a1f1dSLionel Sambuc             }
343*0a6a1f1dSLionel Sambuc         }
344*0a6a1f1dSLionel Sambuc     }
345*0a6a1f1dSLionel Sambuc }
346*0a6a1f1dSLionel Sambuc 
347*0a6a1f1dSLionel Sambuc void
flush(void)348*0a6a1f1dSLionel Sambuc impl::muxer::flush(void)
349*0a6a1f1dSLionel Sambuc {
350*0a6a1f1dSLionel Sambuc     for (size_t i = 0; i < m_nfds; i++) {
351*0a6a1f1dSLionel Sambuc         while (read_one(i, m_fds[i], m_buffers[i], false) > 0) {}
352*0a6a1f1dSLionel Sambuc 
353*0a6a1f1dSLionel Sambuc         if (!m_buffers[i].empty())
354*0a6a1f1dSLionel Sambuc             line_callback(i, m_buffers[i]);
355*0a6a1f1dSLionel Sambuc     }
356*0a6a1f1dSLionel Sambuc }
357