2
* Copyright (C) 2007-2013 Frank Mertens.
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version
7
* 2 of the License, or (at your option) any later version.
10
#include <sys/types.h>
11
#include <sys/uio.h> // readv
14
#include <unistd.h> // read, write, select
15
#include <fcntl.h> // fcntl
16
#include <math.h> // modf
17
#include "SystemStream.hpp"
22
SystemStream::SystemStream(int fd)
27
SystemStream::~SystemStream()
30
if (fd_ >= 3) // because of StandardStreams concurrency
34
int SystemStream::fd() const { return fd_; }
36
bool SystemStream::isTeletype() const
39
isatty_ = ::isatty(fd_);
45
bool SystemStream::isOpen() const { return fd_ != -1; }
47
void SystemStream::close()
49
if (::close(fd_) == -1)
54
bool SystemStream::readyRead(double timeout)
61
tv.tv_usec = modf(timeout, &sec) * 1e6;
63
int ret = ::select(fd_ + 1, &set, 0, 0, &tv);
69
bool SystemStream::readyReadOrWrite(double timeout)
77
tv.tv_usec = modf(timeout, &sec) * 1e6;
79
int ret = ::select(fd_ + 1, &rset, &wset, 0, &tv);
85
int SystemStream::readAvail(void *buf, int bufSize)
89
ret = ::read(fd_, buf, bufSize);
93
if (errno == EWOULDBLOCK)
95
if (isTeletype()) { ret = 0; break; } // fancy HACK, needs review
103
void SystemStream::write(const void *buf, int bufFill)
105
const uint8_t *buf2 = static_cast<const uint8_t*>(buf);
108
ssize_t ret = ::write(fd_, buf2, bufFill);
110
if (errno == EINTR) throw Interrupt();
111
if (errno == EWOULDBLOCK) throw Timeout();
112
DRY_SYSTEM_EXCEPTION;
119
void SystemStream::write(StringList *parts, const char *sep)
121
int n = parts->length();
122
int sepLen = str::len(sep);
124
if (sepLen > 0) n += n - 1;
126
for (int i = 0, j = 0; i < n; ++i) {
127
if ((sepLen > 0) && ((i % 2) == 1)) {
128
iov[i].iov_base = const_cast<char*>(sep);
129
iov[i].iov_len = sepLen;
132
ByteArray *part = parts->at(j++);
133
iov[i].iov_base = part->data();
134
iov[i].iov_len = part->size();
137
ssize_t ret = ::writev(fd_, &iov[0], n);
139
if (errno == EINTR) throw Interrupt();
140
if (errno == EWOULDBLOCK) throw Timeout();
141
DRY_SYSTEM_EXCEPTION;
145
void SystemStream::closeOnExec()
147
if (::fcntl(fd_, F_SETFD, FD_CLOEXEC) == -1)
148
DRY_SYSTEM_EXCEPTION;