11 gs.keenan 1.1 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
19 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
20 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Carol Ann Krug Graves, Hewlett-Packard Company
31 // (carolann_graves@hp.com)
32 gs.keenan 1.1 //
33 // Modified By: Sean Keenan Hewlett_Packard Company (sean.keenan@hp.cpm)
34 //
35 //%/////////////////////////////////////////////////////////////////////////////
36
37
38 #include "AnonymousPipe.h"
39 #include <Pegasus/Common/Signal.h>
40
41 #include <climsgdef.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <perror.h>
45 #include <processes.h>
46 #include <unistd.h>
47 #include <errno.h>
48
49 PEGASUS_NAMESPACE_BEGIN
50
51 AnonymousPipe::AnonymousPipe ()
52 {
53 gs.keenan 1.1 PEG_METHOD_ENTER (TRC_OS_ABSTRACTION, "AnonymousPipe::AnonymousPipe ()");
54
55 AnonymousPipeHandle thePipe [2];
56 if (pipe (thePipe) < 0)
57 {
58 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
59 "Failed to create pipe: %s", strerror (errno));
60 PEG_METHOD_EXIT ();
61
62 MessageLoaderParms mlp ("Common.AnonymousPipe.CREATE_PIPE_FAILED",
63 "Failed to create pipe.");
64 throw Exception (mlp);
65 }
66
67 _readHandle = thePipe [0];
68 _writeHandle = thePipe [1];
69 _readOpen = true;
70 _writeOpen = true;
71
72 PEG_METHOD_EXIT ();
73 }
74 gs.keenan 1.1
75 AnonymousPipe::AnonymousPipe (
76 const char * readHandle,
77 const char * writeHandle)
78 {
79 PEG_METHOD_ENTER (TRC_OS_ABSTRACTION,
80 "AnonymousPipe::AnonymousPipe (const char *, const char *)");
81
82 _readHandle = 0;
83 _writeHandle = 0;
84 _readOpen = false;
85 _writeOpen = false;
86
87 if (readHandle != NULL)
88 {
89 if (sscanf (readHandle, "%d", &_readHandle) != 1)
90 {
91 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
92 "Failed to create pipe: invalid read handle %s", readHandle);
93 PEG_METHOD_EXIT ();
94
95 gs.keenan 1.1 MessageLoaderParms mlp ("Common.AnonymousPipe.CREATE_PIPE_FAILED",
96 "Failed to create pipe.");
97 throw Exception (mlp);
98 }
99 _readOpen = true;
100 }
101
102 if (writeHandle != NULL)
103 {
104 if (sscanf (writeHandle, "%d", &_writeHandle) != 1)
105 {
106 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
107 "Failed to create pipe: invalid write handle %s", writeHandle);
108 PEG_METHOD_EXIT ();
109
110 MessageLoaderParms mlp ("Common.AnonymousPipe.CREATE_PIPE_FAILED",
111 "Failed to create pipe.");
112 throw Exception (mlp);
113 }
114 _writeOpen = true;
115 }
116 gs.keenan 1.1
117 PEG_METHOD_EXIT ();
118 }
119
120 AnonymousPipe::~AnonymousPipe ()
121 {
122 PEG_METHOD_ENTER (TRC_OS_ABSTRACTION, "AnonymousPipe::~AnonymousPipe");
123
124 if (_readOpen)
125 {
126 closeReadHandle ();
127 }
128 if (_writeOpen)
129 {
130 closeWriteHandle ();
131 }
132
133 PEG_METHOD_EXIT ();
134 }
135
136 AnonymousPipe::Status AnonymousPipe::writeBuffer (
137 gs.keenan 1.1 const void * buffer,
138 Uint32 bytesToWrite)
139 {
140 //
141 // Treat invalid handle as connection closed
142 //
143 if (!_writeOpen)
144 {
145 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
146 "Attempted to write to pipe whose write handle is not open");
147 return STATUS_CLOSED;
148 }
149
150 //
151 // Ignore SIGPIPE signals
152 //
153 SignalHandler::ignore (PEGASUS_SIGPIPE);
154
155 const char * writeBuffer = reinterpret_cast<const char*>(buffer);
156 int expectedBytes = bytesToWrite;
157 do
158 gs.keenan 1.1 {
159 int bytesWritten = write (_writeHandle, writeBuffer, expectedBytes);
160
161 if (bytesWritten < 0)
162 {
163 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
164 "Failed to write buffer to pipe: %s", strerror (errno));
165
166 if (errno == EPIPE)
167 {
168 //
169 // Other end of pipe is closed
170 //
171 return STATUS_CLOSED;
172 }
173 else if (errno == EINTR)
174 {
175 //
176 // Keep trying to write
177 //
178 bytesWritten = 0;
179 gs.keenan 1.1 }
180 else
181 {
182 return STATUS_ERROR;
183 }
184 }
185
186 expectedBytes -= bytesWritten;
187 writeBuffer += bytesWritten;
188 } while (expectedBytes > 0);
189
190 return STATUS_SUCCESS;
191 }
192
193 AnonymousPipe::Status AnonymousPipe::readBuffer (
194 void * buffer,
195 Uint32 bytesToRead)
196 {
197 //
198 // Treat invalid handle as connection closed
199 //
200 gs.keenan 1.1 if (!_readOpen)
201 {
202 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
203 "Attempted to read from pipe whose read handle is not open");
204 return STATUS_CLOSED;
205 }
206
207 Uint32 expectedBytes = bytesToRead;
208
209 do
210 {
211 int bytesRead = read (_readHandle, buffer, bytesToRead);
212
213 if (bytesRead == 0)
214 {
215 //
216 // Connection closed
217 //
218 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
219 "Failed to read buffer from pipe: connection closed");
220 return STATUS_CLOSED;
221 gs.keenan 1.1 }
222
223 if (bytesRead < 0)
224 {
225 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
226 "Failed to read buffer from pipe: %s", strerror (errno));
227
228 //
229 // If read was interrupted, keep trying
230 // Otherwise, return error
231 //
232 if (errno == EINTR)
233 {
234 if (bytesToRead == expectedBytes)
235 {
236 //
237 // Got a signal and haven't read any bytes yet
238 //
239 return STATUS_INTERRUPT;
240 }
241 bytesRead = 0;
242 gs.keenan 1.1 }
243 else
244 {
245 //
246 // Error reading from pipe
247 //
248 return STATUS_ERROR;
249 }
250 }
251
252 buffer = reinterpret_cast<char *>(buffer) + bytesRead;
253 bytesToRead -= bytesRead;
254 } while (bytesToRead > 0);
255
256 return STATUS_SUCCESS;
257 }
258
259 void AnonymousPipe::exportReadHandle (
260 char * buffer) const
261 {
262 PEG_METHOD_ENTER (TRC_OS_ABSTRACTION, "AnonymousPipe::exportReadHandle");
263 gs.keenan 1.1
264 sprintf (buffer, "%d", _readHandle);
265
266 PEG_METHOD_EXIT ();
267 }
268
269 void AnonymousPipe::exportWriteHandle (
270 char * buffer) const
271 {
272 PEG_METHOD_ENTER (TRC_OS_ABSTRACTION, "AnonymousPipe::exportWriteHandle");
273
274 sprintf (buffer, "%d", _writeHandle);
275
276 PEG_METHOD_EXIT ();
277 }
278
279 void AnonymousPipe::closeReadHandle ()
280 {
281 PEG_METHOD_ENTER (TRC_OS_ABSTRACTION, "AnonymousPipe::closeReadHandle");
282
283 if (_readOpen)
284 gs.keenan 1.1 {
285 if (close (_readHandle) != 0)
286 {
287 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
288 "Failed to close read handle: %s", strerror (errno));
289 }
290 else
291 {
292 _readOpen = false;
293 }
294 }
295 else
296 {
297 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
298 "Attempted to close read handle that was not open");
299 }
300
301 PEG_METHOD_EXIT ();
302 }
303
304 void AnonymousPipe::closeWriteHandle ()
305 gs.keenan 1.1 {
306 PEG_METHOD_ENTER (TRC_OS_ABSTRACTION, "AnonymousPipe::closeWriteHandle");
307
308 if (_writeOpen)
309 {
310 if (close (_writeHandle) != 0)
311 {
312 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
313 "Failed to close write handle: %s", strerror (errno));
314 }
315 else
316 {
317 _writeOpen = false;
318 }
319 }
320 else
321 {
322 Tracer::trace (TRC_OS_ABSTRACTION, Tracer::LEVEL2,
323 "Attempted to close write handle that was not open");
324 }
325
326 gs.keenan 1.1 PEG_METHOD_EXIT ();
327 }
328
329 PEGASUS_NAMESPACE_END
|