blocxx
UnnamedPipe.cpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Vintela, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Vintela, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
38
39#include "blocxx/BLOCXX_config.h"
41#include "blocxx/AutoPtr.hpp"
42#include "blocxx/String.hpp"
45
46#ifdef BLOCXX_HAVE_UNISTD_H
47#include <unistd.h> // for dup()
48#endif
49
50#include <sys/types.h>
51#ifdef BLOCXX_WIN32
52#include "blocxx/WinUnnamedPipe.hpp"
53#else
55#include <sys/socket.h> // for socketpair()
56#endif
57
58
59namespace BLOCXX_NAMESPACE
60{
61
63
68
69int
71{
72 return this->write(&value, sizeof(int));
73}
74
75int
77{
78 int rc;
79 int len = static_cast<int>(strData.length()+1);
80 if ((rc = this->writeInt(len)) != -1)
81 {
82 rc = this->write(strData.c_str(), len);
83 }
84 return rc;
85}
86
87int
89{
90 return this->read(value, sizeof(int));
91}
92
93int
95{
96 int len;
97 int rc;
98
99 if ((rc = this->readInt(&len)) != -1)
100 {
101 AutoPtrVec<char> p(new char[len+1]);
102
103 // writeString() writes the '\0' terminator, so we don't worry about it here.
104 if ((rc = this->read(p.get(), len)) != -1)
105 {
106 strData = String(String::E_TAKE_OWNERSHIP, p.release(), len);
107 }
108 }
109 return rc;
110}
111
112String
114{
115 char buf[1024];
116 int readbytes;
117 StringBuffer retval;
118 do
119 {
120 readbytes = this->read(buf, sizeof(buf)-1, E_THROW_ON_ERROR);
121 buf[readbytes] = 0; // null-terminate the buffer
122 retval += buf;
123 } while (readbytes > 0); // keep going until we don't fill up the buffer.
124 return retval.releaseString();
125}
126
128// STATIC
131{
132#ifdef BLOCXX_WIN32
133 return WinUnnamedPipe::createUnnamedPipe(doOpen);
134#else
135 return UnnamedPipeRef(new PosixUnnamedPipe(doOpen));
136#endif
137}
138
140// STATIC
143{
144#ifdef BLOCXX_WIN32
145 return WinUnnamedPipe::createStdin();
146#else
147 AutoDescriptor duped(::dup(0));
148 if (duped.get() == BLOCXX_INVALID_HANDLE)
149 {
150 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createStdin(): dup():");
151 }
152 return UnnamedPipeRef(new PosixUnnamedPipe(duped, AutoDescriptor()));
153#endif
154}
155
157// STATIC
160{
161#ifdef BLOCXX_WIN32
162 return WinUnnamedPipe::createStdout();
163#else
164 AutoDescriptor duped(::dup(1));
165 if (duped.get() == BLOCXX_INVALID_HANDLE)
166 {
167 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createStdout(): dup():");
168 }
169 return UnnamedPipeRef(new PosixUnnamedPipe(AutoDescriptor(), duped));
170#endif
171}
172
174// STATIC
177{
178#ifdef BLOCXX_WIN32
179 return WinUnnamedPipe::createStdinStdout();
180#else
181 AutoDescriptor dupedIn(::dup(0));
182 if (dupedIn.get() == BLOCXX_INVALID_HANDLE)
183 {
184 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createStdout(): dup():");
185 }
186 AutoDescriptor dupedOut(::dup(1));
187 if (dupedOut.get() == BLOCXX_INVALID_HANDLE)
188 {
189 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createStdout(): dup():");
190 }
191 return UnnamedPipeRef(new PosixUnnamedPipe(dupedIn, dupedOut));
192#endif
193}
194
196// STATIC
199{
200#ifdef BLOCXX_WIN32
201 return WinUnnamedPipe::createStderr();
202#else
203 AutoDescriptor duped(::dup(2));
204 if (duped.get() == BLOCXX_INVALID_HANDLE)
205 {
206 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createStderr(): dup():");
207 }
208 return UnnamedPipeRef(new PosixUnnamedPipe(AutoDescriptor(), duped));
209#endif
210}
211
213// static
216{
217#ifdef BLOCXX_WIN32
218 return WinUnnamedPipe::createUnnamedPipeFromDescriptor(inputAndOutput);
219#else
220 AutoDescriptor duped(::dup(inputAndOutput.get()));
221 if (duped.get() == BLOCXX_INVALID_HANDLE)
222 {
223 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "UnnamedPipe::createUnnamedPipeFromDescriptor(): dup():");
224 }
225 return UnnamedPipeRef(new PosixUnnamedPipe(inputAndOutput, duped));
226#endif
227}
228
230// static
233{
234#ifdef BLOCXX_WIN32
235 return WinUnnamedPipe::createUnnamedPipeFromDescriptor(input, output);
236#else
237 return UnnamedPipeRef(new PosixUnnamedPipe(input, output));
238#endif
239}
240
242// static
243void
245{
246#ifdef BLOCXX_WIN32
247 return WinUnnamedPipe::createConnectedPipes(first, second);
248#else
249 int fds[2];
250 if (::socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1)
251 {
252 BLOCXX_THROW_ERRNO_MSG(UnnamedPipeException, "PosixUnamedPipe::open(): soketpair()");
253 }
256#endif
257}
258
259} // end namespace BLOCXX_NAMESPACE
260
#define BLOCXX_DEFINE_EXCEPTION_WITH_ID(NAME)
Define a new exception class named <NAME>Exception that derives from Exception.
#define BLOCXX_THROW_ERRNO_MSG(exType, msg)
Throw an exception using FILE, LINE, errno and strerror(errno)
#define BLOCXX_INVALID_HANDLE
Definition Types.hpp:136
The AutoPtrVec class provides a simple class for smart pointers to a dynamically allocated array of o...
Definition AutoPtr.hpp:185
X * release()
Release ownership of the underlying array.
Definition AutoPtr.hpp:300
handle_type get() const
Return handle of resource, retaining ownership.
virtual int write(const void *dataOut, int dataOutLen, ErrorAction errorAsException=E_RETURN_ON_ERROR)=0
Write a specified number of bytes to the device that is exposing the IOIFC interface.
virtual int read(void *dataIn, int dataInLen, ErrorAction errorAsException=E_RETURN_ON_ERROR)=0
Read a specified number of bytes from the device that is exposing the IOIFC interface.
This String class is an abstract data type that represents as NULL terminated string of characters.
Definition String.hpp:67
const char * c_str() const
Definition String.cpp:905
size_t length() const
Definition String.cpp:354
Abstract interface for an UnnamedPipe.
int readString(String &strData)
Reads a String from the pipe.
static UnnamedPipeRef createStdinStdout()
Create an instance of the concrete class that implements the UnnamedPipe interface connected to stdin...
static void createConnectedPipes(UnnamedPipeRef &first, UnnamedPipeRef &second)
Create a connected pair of pipes.
static UnnamedPipeRef createStdout()
Create an instance of the concrete class that implements the UnnamedPipe interface connected to stdou...
int readInt(int *value)
Reads an int (native binary representation) from the pipe.
static UnnamedPipeRef createUnnamedPipe(EOpen doOpen=E_OPEN)
Create an instance of the concrete class that implements the UnnamedPipe interface.
int writeString(const String &strData)
Writes a String to the pipe.
int writeInt(int value)
Write an int (native binary representation) to the pipe.
static UnnamedPipeRef createStdin()
Create an instance of the concrete class that implements the UnnamedPipe interface connected to stdin...
String readAll()
Read from the pipe and collect into a string, until the other end of the pipe is closed.
static UnnamedPipeRef createUnnamedPipeFromDescriptor(AutoDescriptor inputAndOutput)
Create an instance of the concrete class that implements the UnnamedPipe interface connected bidirect...
static UnnamedPipeRef createStderr()
Create an instance of the concrete class that implements the UnnamedPipe interface connected to stder...
Taken from RFC 1321.
IntrusiveReference< UnnamedPipe > UnnamedPipeRef
AutoResource< AutoDescriptorPolicy > AutoDescriptor
An analog of std::auto_ptr for descriptors.