1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
32 #include <osl/diagnose.h>
33 /*#include <osl/signal.h>*/
34 #include <osl/thread.h>
35 #include <osl/interlck.h>
39 #define PIPEDEFAULTPATH "/tmp"
40 #define PIPEALTERNATEPATH "/var/tmp"
42 #define PIPENAMEMASK "OSL_PIPE_%s"
43 #define SECPIPENAMEMASK "OSL_PIPE_%s_%s"
45 sal_Bool SAL_CALL
osl_psz_getUserIdent(oslSecurity Security
, sal_Char
*pszIdent
, sal_uInt32 nMax
);
46 oslPipe SAL_CALL
osl_psz_createPipe(const sal_Char
*pszPipeName
, oslPipeOptions Options
, oslSecurity Security
);
48 /*#define DEBUG_OSL_PIPE*/
49 /*#define TRACE_OSL_PIPE*/
52 /*****************************************************************************/
53 /* enum oslPipeError */
54 /*****************************************************************************/
61 { 0, osl_Pipe_E_None
}, /* no error */
62 { EPROTOTYPE
, osl_Pipe_E_NoProtocol
}, /* Protocol wrong type for socket */
63 { ENOPROTOOPT
, osl_Pipe_E_NoProtocol
}, /* Protocol not available */
64 { EPROTONOSUPPORT
, osl_Pipe_E_NoProtocol
}, /* Protocol not supported */
65 { ESOCKTNOSUPPORT
, osl_Pipe_E_NoProtocol
}, /* Socket type not supported */
66 { EPFNOSUPPORT
, osl_Pipe_E_NoProtocol
}, /* Protocol family not supported */
67 { EAFNOSUPPORT
, osl_Pipe_E_NoProtocol
}, /* Address family not supported by */
69 { ENETRESET
, osl_Pipe_E_NetworkReset
}, /* Network dropped connection because */
71 { ECONNABORTED
, osl_Pipe_E_ConnectionAbort
}, /* Software caused connection abort */
72 { ECONNRESET
, osl_Pipe_E_ConnectionReset
}, /* Connection reset by peer */
73 { ENOBUFS
, osl_Pipe_E_NoBufferSpace
}, /* No buffer space available */
74 { ETIMEDOUT
, osl_Pipe_E_TimedOut
}, /* Connection timed out */
75 { ECONNREFUSED
, osl_Pipe_E_ConnectionRefused
}, /* Connection refused */
76 { -1, osl_Pipe_E_invalidError
}
82 static int osl_NativeFromPipeError(oslPipeError errorCode)
86 while ((PipeError[i].error != osl_Pipe_E_invalidError) &&
87 (PipeError[i].error != errorCode)) i++;
89 return PipeError[i].errcode;
95 static oslPipeError
osl_PipeErrorFromNative(int nativeType
)
99 while ((PipeError
[i
].error
!= osl_Pipe_E_invalidError
) &&
100 (PipeError
[i
].errcode
!= nativeType
)) i
++;
102 return PipeError
[i
].error
;
107 #define ERROR_TO_NATIVE(x) osl_NativeFromPipeError(x)
108 #define ERROR_FROM_NATIVE(y) osl_PipeErrorFromNative(y)
111 /*****************************************************************************/
112 /* osl_create/destroy-PipeImpl */
113 /*****************************************************************************/
115 oslPipe
__osl_createPipeImpl()
119 pPipeImpl
= (oslPipe
)calloc(1, sizeof(struct oslPipeImpl
));
120 pPipeImpl
->m_nRefCount
=1;
121 pPipeImpl
->m_bClosed
= sal_False
;
123 pPipeImpl
->m_bIsInShutdown
= sal_False
;
124 pPipeImpl
->m_bIsAccepting
= sal_False
;
129 void __osl_destroyPipeImpl(oslPipe pImpl
)
136 /*****************************************************************************/
138 /*****************************************************************************/
139 oslPipe SAL_CALL
osl_createPipe(rtl_uString
*ustrPipeName
, oslPipeOptions Options
, oslSecurity Security
)
142 rtl_String
* strPipeName
=0;
143 sal_Char
* pszPipeName
=0;
145 if ( ustrPipeName
!= 0 )
147 rtl_uString2String( &strPipeName
,
148 rtl_uString_getStr(ustrPipeName
),
149 rtl_uString_getLength(ustrPipeName
),
150 osl_getThreadTextEncoding(),
151 OUSTRING_TO_OSTRING_CVTFLAGS
);
152 pszPipeName
= rtl_string_getStr(strPipeName
);
153 pPipe
= osl_psz_createPipe(pszPipeName
, Options
, Security
);
155 if ( strPipeName
!= 0 )
157 rtl_string_release(strPipeName
);
165 oslPipe SAL_CALL
osl_psz_createPipe(const sal_Char
*pszPipeName
, oslPipeOptions Options
,
166 oslSecurity Security
)
170 struct sockaddr_un addr
;
172 sal_Char name
[PATH_MAX
+ 1];
175 if (access(PIPEDEFAULTPATH
, R_OK
|W_OK
) == 0)
177 strncpy(name
, PIPEDEFAULTPATH
, sizeof(name
));
181 strncpy(name
, PIPEALTERNATEPATH
, sizeof(name
));
185 strncat(name
, "/", sizeof(name
));
193 OSL_VERIFY(osl_psz_getUserIdent(Security
, Ident
, sizeof(Ident
)));
195 snprintf(&name
[strlen(name
)], sizeof(name
), SECPIPENAMEMASK
, Ident
, pszPipeName
);
199 snprintf(&name
[strlen(name
)], sizeof(name
), PIPENAMEMASK
, pszPipeName
);
204 pPipe
= __osl_createPipeImpl();
207 pPipe
->m_Socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
208 if ( pPipe
->m_Socket
< 0 )
210 OSL_TRACE("osl_createPipe socket failed. Errno: %d; %s\n",errno
, strerror(errno
));
211 __osl_destroyPipeImpl(pPipe
);
215 /* OSL_TRACE("osl_createPipe : new Pipe on fd %i\n",pPipe->m_Socket);*/
217 /* set close-on-exec flag */
218 if ((Flags
= fcntl(pPipe
->m_Socket
, F_GETFD
, 0)) != -1)
221 if (fcntl(pPipe
->m_Socket
, F_SETFD
, Flags
) == -1)
223 OSL_TRACE("osl_createPipe failed changing socket flags. Errno: %d; %s\n",errno
,strerror(errno
));
227 memset(&addr
, 0, sizeof(addr
));
229 OSL_TRACE("osl_createPipe : Pipe Name '%s'",name
);
231 addr
.sun_family
= AF_UNIX
;
232 strncpy(addr
.sun_path
, name
, sizeof(addr
.sun_path
));
234 len
= SUN_LEN(&addr
);
239 if ( Options
& osl_Pipe_CREATE
)
243 /* check if there exists an orphan filesystem entry */
244 if ( ( stat(name
, &status
) == 0) &&
245 ( S_ISSOCK(status
.st_mode
) || S_ISFIFO(status
.st_mode
) ) )
247 if ( connect(pPipe
->m_Socket
,(struct sockaddr
*)&addr
,len
) >= 0 )
249 OSL_TRACE("osl_createPipe : Pipe already in use. Errno: %d; %s\n",errno
,strerror(errno
));
250 close (pPipe
->m_Socket
);
251 __osl_destroyPipeImpl(pPipe
);
259 if ( bind(pPipe
->m_Socket
, (struct sockaddr
*)&addr
, len
) < 0 )
261 OSL_TRACE("osl_createPipe : failed to bind socket. Errno: %d; %s\n",errno
,strerror(errno
));
262 close (pPipe
->m_Socket
);
263 __osl_destroyPipeImpl(pPipe
);
267 /* Only give access to all if no security handle was specified, otherwise security
271 chmod(name
,S_IRWXU
| S_IRWXG
|S_IRWXO
);
274 strncpy(pPipe
->m_Name
, name
, sizeof(pPipe
->m_Name
));
276 if ( listen(pPipe
->m_Socket
, 5) < 0 )
278 OSL_TRACE("osl_createPipe failed to listen. Errno: %d; %s\n",errno
,strerror(errno
));
279 unlink(name
); /* remove filesystem entry */
280 close (pPipe
->m_Socket
);
281 __osl_destroyPipeImpl(pPipe
);
288 { /* osl_pipe_OPEN */
289 if ( access(name
, F_OK
) != -1 )
291 if ( connect( pPipe
->m_Socket
, (struct sockaddr
*)&addr
, len
) >= 0 )
296 OSL_TRACE("osl_createPipe failed to connect. Errno: %d; %s\n",errno
,strerror(errno
));
299 close (pPipe
->m_Socket
);
300 __osl_destroyPipeImpl(pPipe
);
305 void SAL_CALL
osl_acquirePipe( oslPipe pPipe
)
307 osl_incrementInterlockedCount( &(pPipe
->m_nRefCount
) );
310 void SAL_CALL
osl_releasePipe( oslPipe pPipe
)
316 if( 0 == osl_decrementInterlockedCount( &(pPipe
->m_nRefCount
) ) )
318 if( ! pPipe
->m_bClosed
)
319 osl_closePipe( pPipe
);
321 __osl_destroyPipeImpl( pPipe
);
325 void SAL_CALL
osl_closePipe( oslPipe pPipe
)
330 struct sockaddr_un addr
;
340 if( pPipe
->m_bClosed
)
345 ConnFD
= pPipe
->m_Socket
;
348 Thread does not return from accept on linux, so
349 connect to the accepting pipe
352 if ( pPipe
->m_bIsAccepting
)
354 pPipe
->m_bIsInShutdown
= sal_True
;
355 pPipe
->m_Socket
= -1;
356 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
357 memset(&addr
, 0, sizeof(addr
));
359 OSL_TRACE("osl_destroyPipe : Pipe Name '%s'",pPipe
->m_Name
);
361 addr
.sun_family
= AF_UNIX
;
362 strncpy(addr
.sun_path
, pPipe
->m_Name
, sizeof(addr
.sun_path
));
365 nRet
= connect( fd
, (struct sockaddr
*)&addr
, len
);
366 #if OSL_DEBUG_LEVEL > 1
369 perror("connect in osl_destroyPipe");
371 #endif /* OSL_DEBUG_LEVEL */
377 nRet
= shutdown(ConnFD
, 2);
380 OSL_TRACE("shutdown in destroyPipe failed : '%s'\n",strerror(errno
));
383 nRet
= close(ConnFD
);
386 OSL_TRACE("close in destroyPipe failed : '%s'\n",strerror(errno
));
388 /* remove filesystem entry */
389 if ( strlen(pPipe
->m_Name
) > 0 )
391 unlink(pPipe
->m_Name
);
393 pPipe
->m_bClosed
= sal_True
;
395 /* OSL_TRACE("Out osl_destroyPipe"); */
399 /*****************************************************************************/
401 /*****************************************************************************/
402 oslPipe SAL_CALL
osl_acceptPipe(oslPipe pPipe
)
405 oslPipe pAcceptedPipe
;
413 OSL_ASSERT(strlen(pPipe
->m_Name
) > 0);
416 pPipe
->m_bIsAccepting
= sal_True
;
419 s
= accept(pPipe
->m_Socket
, NULL
, NULL
);
422 pPipe
->m_bIsAccepting
= sal_False
;
427 OSL_TRACE("osl_acceptPipe : accept error '%s'", strerror(errno
));
432 if ( pPipe
->m_bIsInShutdown
)
441 pAcceptedPipe
= __osl_createPipeImpl();
443 OSL_ASSERT(pAcceptedPipe
);
444 if(pAcceptedPipe
==NULL
)
450 /* set close-on-exec flag */
451 if (!((flags
= fcntl(s
, F_GETFD
, 0)) < 0))
454 if (fcntl(s
, F_SETFD
, flags
) < 0)
456 OSL_TRACE("osl_acceptPipe: error changing socket flags. "
457 "Errno: %d; %s",errno
,strerror(errno
));
461 pAcceptedPipe
->m_Socket
= s
;
464 return pAcceptedPipe
;
467 /*****************************************************************************/
468 /* osl_receivePipe */
469 /*****************************************************************************/
470 sal_Int32 SAL_CALL
osl_receivePipe(oslPipe pPipe
,
472 sal_Int32 BytesToRead
)
480 OSL_TRACE("osl_receivePipe : Invalid socket");
485 nRet
= recv(pPipe
->m_Socket
,
491 OSL_TRACE("osl_receivePipe failed : %i '%s'",nRet
,strerror(errno
));
498 /*****************************************************************************/
500 /*****************************************************************************/
501 sal_Int32 SAL_CALL
osl_sendPipe(oslPipe pPipe
,
503 sal_Int32 BytesToSend
)
511 OSL_TRACE("osl_sendPipe : Invalid socket");
516 nRet
= send(pPipe
->m_Socket
,
523 OSL_TRACE("osl_sendPipe failed : %i '%s'",nRet
,strerror(errno
));
530 /*****************************************************************************/
531 /* osl_getLastPipeError */
532 /*****************************************************************************/
533 oslPipeError SAL_CALL
osl_getLastPipeError(oslPipe pPipe
)
535 (void) pPipe
; /* unused */
536 return ERROR_FROM_NATIVE(errno
);
540 sal_Int32 SAL_CALL
osl_writePipe( oslPipe pPipe
, const void *pBuffer
, sal_Int32 n
)
542 /* loop until all desired bytes were send or an error occured */
543 sal_Int32 BytesSend
= 0;
544 sal_Int32 BytesToSend
= n
;
547 while (BytesToSend
> 0)
551 RetVal
= osl_sendPipe(pPipe
, pBuffer
, BytesToSend
);
559 BytesToSend
-= RetVal
;
561 pBuffer
= (sal_Char
*)pBuffer
+ RetVal
;
567 sal_Int32 SAL_CALL
osl_readPipe( oslPipe pPipe
, void *pBuffer
, sal_Int32 n
)
569 /* loop until all desired bytes were read or an error occured */
570 sal_Int32 BytesRead
= 0;
571 sal_Int32 BytesToRead
= n
;
574 while (BytesToRead
> 0)
577 RetVal
= osl_receivePipe(pPipe
, pBuffer
, BytesToRead
);
585 BytesToRead
-= RetVal
;
587 pBuffer
= (sal_Char
*)pBuffer
+ RetVal
;