-
Notifications
You must be signed in to change notification settings - Fork 0
/
pipe.cpp
167 lines (164 loc) · 4.42 KB
/
pipe.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include "pipe.h"
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
using namespace rtypes;
using namespace minecraft_controller;
pipe::pipe()
{
_fdOpenRead = -1;
_fdOpenWrite = -1;
}
minecraft_controller::pipe& pipe::operator =(const pipe& obj)
{
if (this != &obj) {
_assign(obj);
_fdOpenRead = obj._fdOpenRead;
_fdOpenWrite = obj._fdOpenWrite;
}
return *this;
}
void pipe::standard_duplicate(bool includeError)
{
// this member function should run on a pipe object that exists in
// a forked child process
if ( is_valid_context() ) {
// duplicate open ends of created pipes as standard input/output
// close current IO context and load the open end as the current
// context
if (_fdOpenRead != -1) {
if (_fdOpenRead != STDIN_FILENO)
if (::dup2(_fdOpenRead,STDIN_FILENO) == -1)
throw pipe_error();
// make input in this pipe object not exist
close_input();
}
if (_fdOpenWrite != -1) {
if (_fdOpenWrite != STDOUT_FILENO)
if (::dup2(_fdOpenWrite,STDOUT_FILENO) == -1)
throw pipe_error();
if (includeError && _fdOpenWrite!=STDERR_FILENO)
if (::dup2(_fdOpenWrite,STDERR_FILENO) == -1)
throw pipe_error();
// make output in this pipe object not exist
close_output();
}
}
}
void pipe::close_open()
{
// this member function should be run on a pipe
// object that exists as a parent process that has
// just forked a child
if (_fdOpenWrite != -1) {
::close(_fdOpenWrite);
_fdOpenWrite = -1;
}
if (_fdOpenRead != -1) {
::close(_fdOpenRead);
_fdOpenRead = -1;
}
}
void pipe::duplicate(int fdInput,int fdOutput)
{
duplicate_input(fdInput);
duplicate_output(fdOutput);
}
void pipe::duplicate_input(int fd)
{
io_resource* pcontext = _getInputContext();
if (pcontext!=NULL && dup2(pcontext->interpret_as<int>(),fd)!=fd)
throw pipe_error();
}
void pipe::duplicate_output(int fd)
{
io_resource* pcontext = _getOutputContext();
if (pcontext!=NULL && dup2(pcontext->interpret_as<int>(),fd)!=fd)
throw pipe_error();
}
/*static*/ size_type pipe::pipe_atomic_limit()
{
return PIPE_BUF;
}
void pipe::_openEvent(const char*,io_access_flag access,io_resource** pinput,io_resource** poutput,void**,uint32)
{
// simulate full duplex mode by creating two pipes (that is, if the access is read/write); set
// O_NONBLOCK for the write end of the pipe (the one set for this io object)
int pipe1[2]/*read*/, pipe2[2]/*write*/;
if ((access&read_access)!=0 && ::pipe(pipe1)!=0)
throw pipe_error();
if ((access&write_access)!=0 && ::pipe(pipe2)!=0) {
::close(pipe1[0]);
::close(pipe1[1]);
throw pipe_error();
}
if (access & read_access) {
*pinput = new io_resource;
(*pinput)->assign(pipe1[0]);
_fdOpenWrite = pipe1[1];
}
if (access & write_access) {
if (fcntl(pipe2[1],F_SETFL,O_NONBLOCK) == -1)
throw pipe_error();
*poutput = new io_resource;
(*poutput)->assign(pipe2[1]);
_fdOpenRead = pipe2[0];
}
}
void pipe::_readAll(generic_string& buffer) const
{
// read
buffer.resize(4096);
read(buffer);
}
void pipe::_closeEvent(io_access_flag access)
{
if ((access&read_access)!=0 && _fdOpenRead!=-1) {
::close(_fdOpenRead);
_fdOpenRead = -1;
}
if ((access&write_access)!=0 && _fdOpenWrite != -1) {
::close(_fdOpenWrite);
_fdOpenWrite = -1;
}
}
pipe_stream::pipe_stream()
{
}
pipe_stream::pipe_stream(pipe& device)
: stream_device<pipe>(device)
{
}
pipe_stream::~pipe_stream()
{
if ( !_bufOut.is_empty() )
flush_output();
}
bool pipe_stream::_inDevice() const
{
char buffer[4960];
_device->read(buffer,4096);
if (_device->get_last_operation_status() == success_read) {
_bufIn.push_range(buffer,_device->get_last_byte_count());
return true;
}
return false;
}
void pipe_stream::_outDevice()
{
if ( !_bufOut.is_empty() ) {
_device->write(&_bufOut.peek(),_bufOut.size());
_bufOut.clear();
}
}
void pipe_stream::_clearDevice()
{
}
bool pipe_stream::_openDevice(const char*)
{
return _device->open();
}
void pipe_stream::_closeDevice()
{
_device->close();
}