(file) Return to Socket.c CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Executor

  1 kumpf 1.2 /*
  2           //%2006////////////////////////////////////////////////////////////////////////
  3           //
  4           // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  5           // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  6           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  7           // IBM Corp.; EMC Corporation, The Open Group.
  8           // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  9           // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
 10           // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 11           // EMC Corporation; VERITAS Software Corporation; The Open Group.
 12           // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 13           // EMC Corporation; Symantec Corporation; The Open Group.
 14           //
 15           // Permission is hereby granted, free of charge, to any person obtaining a copy
 16           // of this software and associated documentation files (the "Software"), to
 17           // deal in the Software without restriction, including without limitation the
 18           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 19           // sell copies of the Software, and to permit persons to whom the Software is
 20           // furnished to do so, subject to the following conditions:
 21           // 
 22 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 23           // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 24           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 25           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 26           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 27           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 28           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 29           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 30           //
 31           //%/////////////////////////////////////////////////////////////////////////////
 32           */
 33           #include "Socket.h"
 34           #include <unistd.h>
 35           #include <fcntl.h>
 36           #include <signal.h>
 37           #include <string.h>
 38           #include <errno.h>
 39           #include <sys/socket.h>
 40           #include "Exit.h"
 41           #include "Globals.h"
 42           #include "Defines.h"
 43 kumpf 1.2 #include "Socket.h"
 44           
 45           /*
 46           **==============================================================================
 47           **
 48           ** CloseOnExec()
 49           **
 50           **     Direct the kernel not to keep the given file descriptor open across
 51           **     exec() system call.
 52           **
 53           **==============================================================================
 54           */
 55           
 56           int CloseOnExec(int fd)
 57           {
 58               return fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
 59           }
 60           
 61           /*
 62           **==============================================================================
 63           **
 64 kumpf 1.2 ** SetNonBlocking()
 65           **
 66           **     Set the given socket into non-blocking mode.
 67           **
 68           **==============================================================================
 69           */
 70           
 71           int SetNonBlocking(int sock)
 72           {
 73               return fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
 74           }
 75           
 76           /*
 77           **==============================================================================
 78           **
 79           ** SetBlocking()
 80           **
 81           **     Set the given socket into blocking mode.
 82           **
 83           **==============================================================================
 84           */
 85 kumpf 1.2 
 86           int SetBlocking(int sock)
 87           {
 88               return fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) & ~O_NONBLOCK);
 89           }
 90           
 91           /*
 92           **==============================================================================
 93           **
 94           ** _waitForReadEnable()
 95           **
 96           **     Wait until the given socket is read-enabled. Returns 1 if read enabled
 97           **     and 0 on timed out.
 98           **
 99           **==============================================================================
100           */
101           
102           static int _waitForReadEnable(int sock, long timeoutMsec)
103           {
104               struct timeval timeout;
105           
106 kumpf 1.2     fd_set readSet;
107               FD_ZERO(&readSet);
108               FD_SET(sock, &readSet);
109           
110               timeout.tv_sec = timeoutMsec / 1000;
111               timeout.tv_usec = (timeoutMsec % 1000) * 1000;
112           
113               return select(sock + 1, &readSet, 0, 0, &timeout);
114           }
115           
116           /*
117           **==============================================================================
118           **
119           ** _waitForWriteEnable()
120           **
121           **     Wait until the given socket is write-enabled. Returns 1 if write enabled
122           **     and 0 on timed out.
123           **
124           **==============================================================================
125           */
126           
127 kumpf 1.2 static int _waitForWriteEnable(int sock, long timeoutMsec)
128           {
129               fd_set writeSet;
130               struct timeval timeout;
131           
132               FD_ZERO(&writeSet);
133               FD_SET(sock, &writeSet);
134           
135               timeout.tv_sec = timeoutMsec / 1000;
136               timeout.tv_usec = (timeoutMsec % 1000) * 1000;
137           
138               return select(sock + 1, 0, &writeSet, 0, &timeout);
139           }
140           
141           /*
142           **==============================================================================
143           **
144           ** RecvNonBlock()
145           **
146           **     Receive at least size bytes from the given non-blocking socket.
147           **
148 kumpf 1.2 **==============================================================================
149           */
150           
151           ssize_t RecvNonBlock(
152               int sock,
153               void* buffer,
154               size_t size)
155           {
156               const long TIMEOUT_MSEC = 250;
157               size_t r = size;
158               char* p = (char*)buffer;
159           
160               if (size == 0)
161                   return -1;
162           
163               while (r)
164               {
165                   int status = _waitForReadEnable(sock, TIMEOUT_MSEC);
166                   ssize_t n;
167           
168                   if ((globals.signalMask & (1 << SIGTERM)) ||
169 kumpf 1.2             (globals.signalMask & (1 << SIGINT)))
170                   {
171                       /* Exit on either of these signals. */
172                       Exit(0);
173                   }
174           
175                   if (status == 0)
176                       continue;
177           
178                   EXECUTOR_RESTART(read(sock, p, r), n);
179           
180                   if (n == -1 && errno == EINTR)
181                       continue;
182           
183                   if (n == -1)
184                   {
185                       if (errno == EWOULDBLOCK)
186                       {
187                           size_t total = size - r;
188           
189                           if (total)
190 kumpf 1.2                     return total;
191           
192                           return -1;
193                       }
194                       else
195                           return -1;
196                   }
197                   else if (n == 0)
198                       return size - r;
199           
200                   r -= n;
201                   p += n;
202               }
203           
204               return size - r;
205           }
206           
207           /*
208           **==============================================================================
209           **
210           ** SendNonBlock()
211 kumpf 1.2 **
212           **     Sends at least size bytes on the given non-blocking socket.
213           **
214           **==============================================================================
215           */
216           
217           ssize_t SendNonBlock(
218               int sock,
219               const void* buffer,
220               size_t size)
221           {
222               const long TIMEOUT_MSEC = 250;
223               size_t r = size;
224               char* p = (char*)buffer;
225           
226               while (r)
227               {
228                   int status = _waitForWriteEnable(sock, TIMEOUT_MSEC);
229                   ssize_t n;
230           
231                   if ((globals.signalMask & (1 << SIGTERM)) ||
232 kumpf 1.2             (globals.signalMask & (1 << SIGINT)))
233                   {
234                       /* Exit on either of these signals. */
235                       Exit(0);
236                   }
237           
238                   if (status == 0)
239                       continue;
240           
241                   EXECUTOR_RESTART(write(sock, p, r), n);
242           
243                   if (n == -1)
244                   {
245                       if (errno == EWOULDBLOCK)
246                           return size - r;
247                       else
248                           return -1;
249                   }
250                   else if (n == 0)
251                       return size - r;
252           
253 kumpf 1.2         r -= n;
254                   p += n;
255               }
256           
257               return size - r;
258           }
259           
260           /*
261           **==============================================================================
262           **
263           ** SendDescriptorArray()
264           **
265           **     Send an array of descriptors (file, socket, pipe) to the child process.
266           **
267           **==============================================================================
268           */
269           
270           ssize_t SendDescriptorArray(int sock, int descriptors[], size_t count)
271           {
272               struct iovec iov[1];
273               char dummy;
274 kumpf 1.2     struct msghdr mh;
275               int result;
276           #if defined(HAVE_MSG_CONTROL)
277               size_t size;
278               char* data;
279               struct cmsghdr* cmh;
280           
281               /* Allocate space for control header plus descriptors. */
282           
283               size = CMSG_SPACE(sizeof(int) * count);
284               data = (char*)malloc(size);
285           
286               /* Initialize msghdr struct to refer to control data. */
287           
288               memset(&mh, 0, sizeof(mh));
289               mh.msg_control = data;
290               mh.msg_controllen = size;
291           
292               /* Fill in the control data struct with the descriptor and other fields. */
293           
294               cmh = CMSG_FIRSTHDR(&mh);
295 kumpf 1.2     cmh->cmsg_len = CMSG_LEN(sizeof(int) * count);
296               cmh->cmsg_level = SOL_SOCKET;
297               cmh->cmsg_type = SCM_RIGHTS;
298               memcpy((int*)CMSG_DATA(cmh), descriptors, sizeof(int) * count);
299           
300           #else /* defined(HAVE_MSG_CONTROL) */
301           
302               memset(&mh, 0, sizeof(mh));
303               mh.msg_accrights = (caddr_t)descriptors;
304               mh.msg_accrightslen = count * sizeof(int);
305           
306           #endif /* defined(HAVE_MSG_CONTROL) */
307           
308               /*
309                * Prepare to send single dummy byte. It will not be used but we must send
310                * at least one byte otherwise the call will fail on some platforms.
311                */
312           
313               memset(iov, 0, sizeof(iov));
314               dummy = '\0';
315               iov[0].iov_base = &dummy;
316 kumpf 1.2     iov[0].iov_len = 1;
317               mh.msg_iov = iov;
318               mh.msg_iovlen = 1;
319           
320               /* Send message to child. */
321           
322               result = sendmsg(sock, &mh, 0);
323           
324           #if defined(HAVE_MSG_CONTROL)
325               free(data);
326           #endif
327           
328               return result == -1 ? -1 : 0;
329           }
330           
331           /*
332           **==============================================================================
333           **
334           ** CreateSocketPair()
335           **
336           **     Send an array of descriptors (file, socket, pipe) to the child process.
337 kumpf 1.2 **
338           **==============================================================================
339           */
340           
341           int CreateSocketPair(int pair[2])
342           {
343               return socketpair(AF_UNIX, SOCK_STREAM, 0, pair);
344           }

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2