merge the formfield patch from ooo-build
[ooovba.git] / sal / osl / unx / pipe.c
blob410eaaef00ab6516b5257aec17b8101414eeb804
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pipe.c,v $
10 * $Revision: 1.20 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 #include "system.h"
34 #include <osl/pipe.h>
35 #include <osl/diagnose.h>
36 /*#include <osl/signal.h>*/
37 #include <osl/thread.h>
38 #include <osl/interlck.h>
40 #include "sockimpl.h"
42 #define PIPEDEFAULTPATH "/tmp"
43 #define PIPEALTERNATEPATH "/var/tmp"
45 #define PIPENAMEMASK "OSL_PIPE_%s"
46 #define SECPIPENAMEMASK "OSL_PIPE_%s_%s"
48 sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax);
49 oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options, oslSecurity Security);
51 /*#define DEBUG_OSL_PIPE*/
52 /*#define TRACE_OSL_PIPE*/
55 /*****************************************************************************/
56 /* enum oslPipeError */
57 /*****************************************************************************/
59 static struct
61 int errcode;
62 oslPipeError error;
63 } PipeError[]= {
64 { 0, osl_Pipe_E_None }, /* no error */
65 { EPROTOTYPE, osl_Pipe_E_NoProtocol }, /* Protocol wrong type for socket */
66 { ENOPROTOOPT, osl_Pipe_E_NoProtocol }, /* Protocol not available */
67 { EPROTONOSUPPORT, osl_Pipe_E_NoProtocol }, /* Protocol not supported */
68 { ESOCKTNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Socket type not supported */
69 { EPFNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Protocol family not supported */
70 { EAFNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Address family not supported by */
71 /* protocol family */
72 { ENETRESET, osl_Pipe_E_NetworkReset }, /* Network dropped connection because */
73 /* of reset */
74 { ECONNABORTED, osl_Pipe_E_ConnectionAbort }, /* Software caused connection abort */
75 { ECONNRESET, osl_Pipe_E_ConnectionReset }, /* Connection reset by peer */
76 { ENOBUFS, osl_Pipe_E_NoBufferSpace }, /* No buffer space available */
77 { ETIMEDOUT, osl_Pipe_E_TimedOut }, /* Connection timed out */
78 { ECONNREFUSED, osl_Pipe_E_ConnectionRefused }, /* Connection refused */
79 { -1, osl_Pipe_E_invalidError }
83 /* map */
84 /* mfe: NOT USED
85 static int osl_NativeFromPipeError(oslPipeError errorCode)
87 int i = 0;
89 while ((PipeError[i].error != osl_Pipe_E_invalidError) &&
90 (PipeError[i].error != errorCode)) i++;
92 return PipeError[i].errcode;
97 /* reverse map */
98 static oslPipeError osl_PipeErrorFromNative(int nativeType)
100 int i = 0;
102 while ((PipeError[i].error != osl_Pipe_E_invalidError) &&
103 (PipeError[i].errcode != nativeType)) i++;
105 return PipeError[i].error;
109 /* macros */
110 #define ERROR_TO_NATIVE(x) osl_NativeFromPipeError(x)
111 #define ERROR_FROM_NATIVE(y) osl_PipeErrorFromNative(y)
114 /*****************************************************************************/
115 /* osl_create/destroy-PipeImpl */
116 /*****************************************************************************/
118 oslPipe __osl_createPipeImpl()
120 oslPipe pPipeImpl;
122 pPipeImpl = (oslPipe)calloc(1, sizeof(struct oslPipeImpl));
123 pPipeImpl->m_nRefCount =1;
124 pPipeImpl->m_bClosed = sal_False;
125 #if defined(LINUX)
126 pPipeImpl->m_bIsInShutdown = sal_False;
127 pPipeImpl->m_bIsAccepting = sal_False;
128 #endif
129 return pPipeImpl;
132 void __osl_destroyPipeImpl(oslPipe pImpl)
134 if (pImpl != NULL)
135 free(pImpl);
139 /*****************************************************************************/
140 /* osl_createPipe */
141 /*****************************************************************************/
142 oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options, oslSecurity Security)
144 oslPipe pPipe=0;
145 rtl_String* strPipeName=0;
146 sal_Char* pszPipeName=0;
148 if ( ustrPipeName != 0 )
150 rtl_uString2String( &strPipeName,
151 rtl_uString_getStr(ustrPipeName),
152 rtl_uString_getLength(ustrPipeName),
153 osl_getThreadTextEncoding(),
154 OUSTRING_TO_OSTRING_CVTFLAGS );
155 pszPipeName = rtl_string_getStr(strPipeName);
156 pPipe = osl_psz_createPipe(pszPipeName, Options, Security);
158 if ( strPipeName != 0 )
160 rtl_string_release(strPipeName);
164 return pPipe;
168 oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options,
169 oslSecurity Security)
171 int Flags;
172 size_t len;
173 struct sockaddr_un addr;
175 sal_Char name[PATH_MAX + 1];
176 oslPipe pPipe;
178 if (access(PIPEDEFAULTPATH, R_OK|W_OK) == 0)
180 strncpy(name, PIPEDEFAULTPATH, sizeof(name));
182 else
184 strncpy(name, PIPEALTERNATEPATH, sizeof(name));
188 strncat(name, "/", sizeof(name));
190 if (Security)
192 sal_Char Ident[256];
194 Ident[0] = '\0';
196 OSL_VERIFY(osl_psz_getUserIdent(Security, Ident, sizeof(Ident)));
198 snprintf(&name[strlen(name)], sizeof(name), SECPIPENAMEMASK, Ident, pszPipeName);
200 else
202 snprintf(&name[strlen(name)], sizeof(name), PIPENAMEMASK, pszPipeName);
206 /* alloc memory */
207 pPipe= __osl_createPipeImpl();
209 /* create socket */
210 pPipe->m_Socket = socket(AF_UNIX, SOCK_STREAM, 0);
211 if ( pPipe->m_Socket < 0 )
213 OSL_TRACE("osl_createPipe socket failed. Errno: %d; %s\n",errno, strerror(errno));
214 __osl_destroyPipeImpl(pPipe);
215 return NULL;
218 /* OSL_TRACE("osl_createPipe : new Pipe on fd %i\n",pPipe->m_Socket);*/
220 /* set close-on-exec flag */
221 if ((Flags = fcntl(pPipe->m_Socket, F_GETFD, 0)) != -1)
223 Flags |= FD_CLOEXEC;
224 if (fcntl(pPipe->m_Socket, F_SETFD, Flags) == -1)
226 OSL_TRACE("osl_createPipe failed changing socket flags. Errno: %d; %s\n",errno,strerror(errno));
230 memset(&addr, 0, sizeof(addr));
232 OSL_TRACE("osl_createPipe : Pipe Name '%s'",name);
234 addr.sun_family = AF_UNIX;
235 strncpy(addr.sun_path, name, sizeof(addr.sun_path));
236 #if defined(FREEBSD)
237 len = SUN_LEN(&addr);
238 #else
239 len = sizeof(addr);
240 #endif
242 if ( Options & osl_Pipe_CREATE )
244 struct stat status;
246 /* check if there exists an orphan filesystem entry */
247 if ( ( stat(name, &status) == 0) &&
248 ( S_ISSOCK(status.st_mode) || S_ISFIFO(status.st_mode) ) )
250 if ( connect(pPipe->m_Socket,(struct sockaddr *)&addr,len) >= 0 )
252 OSL_TRACE("osl_createPipe : Pipe already in use. Errno: %d; %s\n",errno,strerror(errno));
253 close (pPipe->m_Socket);
254 __osl_destroyPipeImpl(pPipe);
255 return NULL;
258 unlink(name);
261 /* ok, fs clean */
262 if ( bind(pPipe->m_Socket, (struct sockaddr *)&addr, len) < 0 )
264 OSL_TRACE("osl_createPipe : failed to bind socket. Errno: %d; %s\n",errno,strerror(errno));
265 close (pPipe->m_Socket);
266 __osl_destroyPipeImpl(pPipe);
267 return NULL;
270 /* Only give access to all if no security handle was specified, otherwise security
271 depends on umask */
273 if ( !Security )
274 chmod(name,S_IRWXU | S_IRWXG |S_IRWXO);
277 strncpy(pPipe->m_Name, name, sizeof(pPipe->m_Name));
279 if ( listen(pPipe->m_Socket, 5) < 0 )
281 OSL_TRACE("osl_createPipe failed to listen. Errno: %d; %s\n",errno,strerror(errno));
282 unlink(name); /* remove filesystem entry */
283 close (pPipe->m_Socket);
284 __osl_destroyPipeImpl(pPipe);
285 return NULL;
288 return (pPipe);
290 else
291 { /* osl_pipe_OPEN */
292 if ( access(name, F_OK) != -1 )
294 if ( connect( pPipe->m_Socket, (struct sockaddr *)&addr, len) >= 0 )
296 return (pPipe);
299 OSL_TRACE("osl_createPipe failed to connect. Errno: %d; %s\n",errno,strerror(errno));
302 close (pPipe->m_Socket);
303 __osl_destroyPipeImpl(pPipe);
304 return NULL;
308 void SAL_CALL osl_acquirePipe( oslPipe pPipe )
310 osl_incrementInterlockedCount( &(pPipe->m_nRefCount) );
313 void SAL_CALL osl_releasePipe( oslPipe pPipe )
316 if( 0 == pPipe )
317 return;
319 if( 0 == osl_decrementInterlockedCount( &(pPipe->m_nRefCount) ) )
321 if( ! pPipe->m_bClosed )
322 osl_closePipe( pPipe );
324 __osl_destroyPipeImpl( pPipe );
328 void SAL_CALL osl_closePipe( oslPipe pPipe )
330 int nRet;
331 #if defined(LINUX)
332 size_t len;
333 struct sockaddr_un addr;
334 int fd;
335 #endif
336 int ConnFD;
338 if( ! pPipe )
340 return;
343 if( pPipe->m_bClosed )
345 return;
348 ConnFD = pPipe->m_Socket;
351 Thread does not return from accept on linux, so
352 connect to the accepting pipe
354 #if defined(LINUX)
355 if ( pPipe->m_bIsAccepting )
357 pPipe->m_bIsInShutdown = sal_True;
358 pPipe->m_Socket = -1;
359 fd = socket(AF_UNIX, SOCK_STREAM, 0);
360 memset(&addr, 0, sizeof(addr));
362 OSL_TRACE("osl_destroyPipe : Pipe Name '%s'",pPipe->m_Name);
364 addr.sun_family = AF_UNIX;
365 strncpy(addr.sun_path, pPipe->m_Name, sizeof(addr.sun_path));
366 len = sizeof(addr);
368 nRet = connect( fd, (struct sockaddr *)&addr, len);
369 #if OSL_DEBUG_LEVEL > 1
370 if ( nRet < 0 )
372 perror("connect in osl_destroyPipe");
374 #endif /* OSL_DEBUG_LEVEL */
375 close(fd);
377 #endif /* LINUX */
380 nRet = shutdown(ConnFD, 2);
381 if ( nRet < 0 )
383 OSL_TRACE("shutdown in destroyPipe failed : '%s'\n",strerror(errno));
386 nRet = close(ConnFD);
387 if ( nRet < 0 )
389 OSL_TRACE("close in destroyPipe failed : '%s'\n",strerror(errno));
391 /* remove filesystem entry */
392 if ( strlen(pPipe->m_Name) > 0 )
394 unlink(pPipe->m_Name);
396 pPipe->m_bClosed = sal_True;
398 /* OSL_TRACE("Out osl_destroyPipe"); */
402 /*****************************************************************************/
403 /* osl_acceptPipe */
404 /*****************************************************************************/
405 oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe)
407 int s, flags;
408 oslPipe pAcceptedPipe;
410 OSL_ASSERT(pPipe);
411 if ( pPipe == 0 )
413 return NULL;
416 OSL_ASSERT(strlen(pPipe->m_Name) > 0);
418 #if defined(LINUX)
419 pPipe->m_bIsAccepting = sal_True;
420 #endif
422 s = accept(pPipe->m_Socket, NULL, NULL);
424 #if defined(LINUX)
425 pPipe->m_bIsAccepting = sal_False;
426 #endif
428 if (s < 0)
430 OSL_TRACE("osl_acceptPipe : accept error '%s'", strerror(errno));
431 return NULL;
434 #if defined(LINUX)
435 if ( pPipe->m_bIsInShutdown )
437 close(s);
438 return NULL;
440 #endif /* LINUX */
441 else
443 /* alloc memory */
444 pAcceptedPipe= __osl_createPipeImpl();
446 OSL_ASSERT(pAcceptedPipe);
447 if(pAcceptedPipe==NULL)
449 close(s);
450 return NULL;
453 /* set close-on-exec flag */
454 if (!((flags = fcntl(s, F_GETFD, 0)) < 0))
456 flags |= FD_CLOEXEC;
457 if (fcntl(s, F_SETFD, flags) < 0)
459 OSL_TRACE("osl_acceptPipe: error changing socket flags. "
460 "Errno: %d; %s",errno,strerror(errno));
464 pAcceptedPipe->m_Socket = s;
467 return pAcceptedPipe;
470 /*****************************************************************************/
471 /* osl_receivePipe */
472 /*****************************************************************************/
473 sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe,
474 void* pBuffer,
475 sal_Int32 BytesToRead)
477 int nRet = 0;
479 OSL_ASSERT(pPipe);
481 if ( pPipe == 0 )
483 OSL_TRACE("osl_receivePipe : Invalid socket");
484 errno=EINVAL;
485 return -1;
488 nRet = recv(pPipe->m_Socket,
489 (sal_Char*)pBuffer,
490 BytesToRead, 0);
492 if ( nRet <= 0 )
494 OSL_TRACE("osl_receivePipe failed : %i '%s'",nRet,strerror(errno));
497 return nRet;
501 /*****************************************************************************/
502 /* osl_sendPipe */
503 /*****************************************************************************/
504 sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe,
505 const void* pBuffer,
506 sal_Int32 BytesToSend)
508 int nRet=0;
510 OSL_ASSERT(pPipe);
512 if ( pPipe == 0 )
514 OSL_TRACE("osl_sendPipe : Invalid socket");
515 errno=EINVAL;
516 return -1;
519 nRet = send(pPipe->m_Socket,
520 (sal_Char*)pBuffer,
521 BytesToSend, 0);
524 if ( nRet <= 0 )
526 OSL_TRACE("osl_sendPipe failed : %i '%s'",nRet,strerror(errno));
529 return nRet;
533 /*****************************************************************************/
534 /* osl_getLastPipeError */
535 /*****************************************************************************/
536 oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe)
538 (void) pPipe; /* unused */
539 return ERROR_FROM_NATIVE(errno);
543 sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n )
545 /* loop until all desired bytes were send or an error occured */
546 sal_Int32 BytesSend= 0;
547 sal_Int32 BytesToSend= n;
549 OSL_ASSERT(pPipe);
550 while (BytesToSend > 0)
552 sal_Int32 RetVal;
554 RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend);
556 /* error occured? */
557 if(RetVal <= 0)
559 break;
562 BytesToSend -= RetVal;
563 BytesSend += RetVal;
564 pBuffer= (sal_Char*)pBuffer + RetVal;
567 return BytesSend;
570 sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n )
572 /* loop until all desired bytes were read or an error occured */
573 sal_Int32 BytesRead= 0;
574 sal_Int32 BytesToRead= n;
576 OSL_ASSERT( pPipe );
577 while (BytesToRead > 0)
579 sal_Int32 RetVal;
580 RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead);
582 /* error occured? */
583 if(RetVal <= 0)
585 break;
588 BytesToRead -= RetVal;
589 BytesRead += RetVal;
590 pBuffer= (sal_Char*)pBuffer + RetVal;
592 return BytesRead;