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 
39 #include "blocxx/BLOCXX_config.h"
40 #include "blocxx/UnnamedPipe.hpp"
41 #include "blocxx/AutoPtr.hpp"
42 #include "blocxx/String.hpp"
43 #include "blocxx/StringBuffer.hpp"
44 #include "blocxx/ExceptionIds.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 
59 namespace BLOCXX_NAMESPACE
60 {
61 
63 
66 {
67 }
69 int
71 {
72  return this->write(&value, sizeof(int));
73 }
75 int
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 }
87 int
89 {
90  return this->read(value, sizeof(int));
91 }
93 int
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 }
112 String
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
243 void
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_INVALID_HANDLE
Definition: Types.hpp:136
static UnnamedPipeRef createStderr()
Create an instance of the concrete class that implements the UnnamedPipe interface connected to stder...
static UnnamedPipeRef createStdout()
Create an instance of the concrete class that implements the UnnamedPipe interface connected to stdou...
Taken from RFC 1321.
int readString(String &strData)
Reads a String from the pipe.
Definition: UnnamedPipe.cpp:94
int readInt(int *value)
Reads an int (native binary representation) from the pipe.
Definition: UnnamedPipe.cpp:88
static UnnamedPipeRef createStdin()
Create an instance of the concrete class that implements the UnnamedPipe interface connected to stdin...
Abstract interface for an UnnamedPipe.
Definition: UnnamedPipe.hpp:60
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.
This String class is an abstract data type that represents as NULL terminated string of characters...
Definition: String.hpp:66
#define BLOCXX_DEFINE_EXCEPTION_WITH_ID(NAME)
Define a new exception class named <NAME>Exception that derives from Exception.
Definition: Exception.hpp:449
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.
const char * c_str() const
Definition: String.cpp:905
String readAll()
Read from the pipe and collect into a string, until the other end of the pipe is closed.
size_t length() const
Definition: String.cpp:354
static UnnamedPipeRef createUnnamedPipeFromDescriptor(AutoDescriptor inputAndOutput)
Create an instance of the concrete class that implements the UnnamedPipe interface connected bidirect...
AutoResource< AutoDescriptorPolicy > AutoDescriptor
An analog of std::auto_ptr for descriptors.
PURPOSE: The AutoResource class template is an analog of std::auto_ptr for managing arbitrary resourc...
int writeInt(int value)
Write an int (native binary representation) to the pipe.
Definition: UnnamedPipe.cpp:70
The AutoPtrVec class provides a simple class for smart pointers to a dynamically allocated array of o...
Definition: AutoPtr.hpp:184
X * release()
Release ownership of the underlying array.
Definition: AutoPtr.hpp:300
IntrusiveReference< UnnamedPipe > UnnamedPipeRef
Definition: CommonFwd.hpp:105
handle_type get() const
Return handle of resource, retaining ownership.
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 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.
Definition: UnnamedPipe.cpp:76
#define BLOCXX_THROW_ERRNO_MSG(exType, msg)
Throw an exception using FILE, LINE, errno and strerror(errno)
Definition: Exception.hpp:312