xref: /trunk/main/sal/osl/unx/process.c (revision 4772a777d4d7463276afbb9669636e78e1126302)
1647f063dSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3647f063dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4647f063dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5647f063dSAndrew Rist  * distributed with this work for additional information
6647f063dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7647f063dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8647f063dSAndrew Rist  * "License"); you may not use this file except in compliance
9647f063dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11647f063dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13647f063dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14647f063dSAndrew Rist  * software distributed under the License is distributed on an
15647f063dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16647f063dSAndrew Rist  * KIND, either express or implied.  See the License for the
17647f063dSAndrew Rist  * specific language governing permissions and limitations
18647f063dSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20647f063dSAndrew Rist  *************************************************************/
21647f063dSAndrew Rist 
22647f063dSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir /*
25cdf0e10cSrcweir  *   ToDo:
26cdf0e10cSrcweir  *      - cleanup of process status things
27cdf0e10cSrcweir  *      - cleanup of process spawning
28cdf0e10cSrcweir  *      - cleanup of resource transfer
29cdf0e10cSrcweir  */
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #if defined(SOLARIS)
32cdf0e10cSrcweir // The procfs may only be used without LFS in 32bits.
33cdf0e10cSrcweir # ifdef _FILE_OFFSET_BITS
34cdf0e10cSrcweir #   undef   _FILE_OFFSET_BITS
35cdf0e10cSrcweir # endif
36cdf0e10cSrcweir #endif
37cdf0e10cSrcweir 
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #ifdef FREEBSD
40cdf0e10cSrcweir #include <machine/param.h>
41cdf0e10cSrcweir #endif
42cdf0e10cSrcweir 
43cdf0e10cSrcweir #include "system.h"
44cdf0e10cSrcweir #if defined(SOLARIS)
45cdf0e10cSrcweir # include <sys/procfs.h>
46cdf0e10cSrcweir #endif
47cdf0e10cSrcweir #include <osl/diagnose.h>
48cdf0e10cSrcweir #include <osl/mutex.h>
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #ifndef _OSL_CONDITN_H_
51cdf0e10cSrcweir #include <osl/conditn.h>
52cdf0e10cSrcweir #endif
53cdf0e10cSrcweir #include <osl/thread.h>
54cdf0e10cSrcweir #include <osl/file.h>
55cdf0e10cSrcweir #include <osl/signal.h>
56cdf0e10cSrcweir #include <rtl/alloc.h>
57cdf0e10cSrcweir 
58cdf0e10cSrcweir #include <grp.h>
59cdf0e10cSrcweir 
60cdf0e10cSrcweir #include "procimpl.h"
61cdf0e10cSrcweir #include "sockimpl.h"
62cdf0e10cSrcweir #include "secimpl.h"
63cdf0e10cSrcweir 
64cdf0e10cSrcweir 
65cdf0e10cSrcweir #define MAX_ARGS        255
66cdf0e10cSrcweir #define MAX_ENVS        255
67cdf0e10cSrcweir 
68cdf0e10cSrcweir #if defined(MACOSX) || defined(IORESOURCE_TRANSFER_BSD)
69cdf0e10cSrcweir #define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(int))
70cdf0e10cSrcweir #endif
71cdf0e10cSrcweir 
72cdf0e10cSrcweir /* implemented in file.c */
73cdf0e10cSrcweir extern oslFileError FileURLToPath( char *, size_t, rtl_uString* );
74cdf0e10cSrcweir extern oslFileHandle osl_createFileHandleFromFD( int fd );
75cdf0e10cSrcweir 
76cdf0e10cSrcweir /******************************************************************************
77cdf0e10cSrcweir  *
78cdf0e10cSrcweir  * Data Type Definition
79cdf0e10cSrcweir  *
80cdf0e10cSrcweir  ******************************************************************************/
81cdf0e10cSrcweir 
82cdf0e10cSrcweir typedef struct {
83cdf0e10cSrcweir     int  m_hPipe;
84cdf0e10cSrcweir     int  m_hConn;
85cdf0e10cSrcweir     sal_Char m_Name[PATH_MAX + 1];
86cdf0e10cSrcweir } Pipe;
87cdf0e10cSrcweir 
88cdf0e10cSrcweir typedef struct {
89cdf0e10cSrcweir     const sal_Char*  m_pszArgs[MAX_ARGS + 1];
90cdf0e10cSrcweir     oslProcessOption m_options;
91cdf0e10cSrcweir     const sal_Char*  m_pszDir;
92cdf0e10cSrcweir     sal_Char*        m_pszEnv[MAX_ENVS + 1];
93cdf0e10cSrcweir     uid_t            m_uid;
94cdf0e10cSrcweir     gid_t            m_gid;
95cdf0e10cSrcweir     sal_Char*        m_name;
96cdf0e10cSrcweir     oslCondition     m_started;
97cdf0e10cSrcweir     oslProcessImpl*  m_pProcImpl;
98cdf0e10cSrcweir     oslFileHandle    *m_pInputWrite;
99cdf0e10cSrcweir     oslFileHandle    *m_pOutputRead;
100cdf0e10cSrcweir     oslFileHandle    *m_pErrorRead;
101cdf0e10cSrcweir } ProcessData;
102cdf0e10cSrcweir 
103cdf0e10cSrcweir typedef struct _oslPipeImpl {
104cdf0e10cSrcweir     int      m_Socket;
105cdf0e10cSrcweir     sal_Char m_Name[PATH_MAX + 1];
106cdf0e10cSrcweir } oslPipeImpl;
107cdf0e10cSrcweir 
108cdf0e10cSrcweir 
109cdf0e10cSrcweir /******************************************************************************
110cdf0e10cSrcweir  *
111cdf0e10cSrcweir  * Function Declarations
112cdf0e10cSrcweir  *
113cdf0e10cSrcweir  *****************************************************************************/
114cdf0e10cSrcweir 
115cdf0e10cSrcweir oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
116cdf0e10cSrcweir                                                 sal_Char *pszArguments[],
117cdf0e10cSrcweir                                                 oslProcessOption Options,
118cdf0e10cSrcweir                                                 oslSecurity Security,
119cdf0e10cSrcweir                                                 sal_Char *pszDirectory,
120cdf0e10cSrcweir                                                 sal_Char *pszEnvironments[],
121cdf0e10cSrcweir                                                 oslProcess *pProcess,
122cdf0e10cSrcweir                                                 oslFileHandle *pInputWrite,
123cdf0e10cSrcweir                                                 oslFileHandle *pOutputRead,
124cdf0e10cSrcweir                                                 oslFileHandle *pErrorRead );
125cdf0e10cSrcweir 
126cdf0e10cSrcweir 
127cdf0e10cSrcweir oslProcessError SAL_CALL osl_searchPath_impl(
128cdf0e10cSrcweir     const sal_Char* pszName,
129cdf0e10cSrcweir     const sal_Char* pszPath,
130cdf0e10cSrcweir     sal_Char Separator,
131cdf0e10cSrcweir     sal_Char *pszBuffer,
132cdf0e10cSrcweir     sal_uInt32 Max);
133cdf0e10cSrcweir 
134cdf0e10cSrcweir 
135cdf0e10cSrcweir sal_Bool osl_getFullPath(const sal_Char* pszFilename, sal_Char* pszPath, sal_uInt32 MaxLen);
136cdf0e10cSrcweir 
137cdf0e10cSrcweir static oslProcessImpl* ChildList;
138cdf0e10cSrcweir static oslMutex        ChildListMutex;
139cdf0e10cSrcweir 
140cdf0e10cSrcweir /******************************************************************************
141cdf0e10cSrcweir  Deprecated
142cdf0e10cSrcweir  Old and buggy implementation of osl_searchPath used only by
143cdf0e10cSrcweir  osl_psz_executeProcess.
144*4772a777SJohn Bampton  A new implementation is in file_path_helper.cxx
145cdf0e10cSrcweir  *****************************************************************************/
146cdf0e10cSrcweir 
osl_searchPath_impl(const sal_Char * pszName,const sal_Char * pszPath,sal_Char Separator,sal_Char * pszBuffer,sal_uInt32 Max)147cdf0e10cSrcweir oslProcessError SAL_CALL osl_searchPath_impl(const sal_Char* pszName, const sal_Char* pszPath,
148cdf0e10cSrcweir                    sal_Char Separator, sal_Char *pszBuffer, sal_uInt32 Max)
149cdf0e10cSrcweir {
150cdf0e10cSrcweir     sal_Char path[PATH_MAX + 1];
151cdf0e10cSrcweir     sal_Char *pchr;
152cdf0e10cSrcweir 
153cdf0e10cSrcweir     path[0] = '\0';
154cdf0e10cSrcweir 
155cdf0e10cSrcweir     OSL_ASSERT(pszName != NULL);
156cdf0e10cSrcweir 
157509a48ffSpfg     if ( pszName == NULL )
158cdf0e10cSrcweir     {
159cdf0e10cSrcweir         return osl_Process_E_NotFound;
160cdf0e10cSrcweir     }
161cdf0e10cSrcweir 
162cdf0e10cSrcweir     if (pszPath == NULL)
163cdf0e10cSrcweir         pszPath = "PATH";
164cdf0e10cSrcweir 
165cdf0e10cSrcweir     if (Separator == '\0')
166cdf0e10cSrcweir         Separator = ':';
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 
169509a48ffSpfg     if ( (pchr = getenv(pszPath)) != NULL )
170cdf0e10cSrcweir     {
171cdf0e10cSrcweir         sal_Char *pstr;
172cdf0e10cSrcweir 
173cdf0e10cSrcweir         while (*pchr != '\0')
174cdf0e10cSrcweir         {
175cdf0e10cSrcweir             pstr = path;
176cdf0e10cSrcweir 
177cdf0e10cSrcweir             while ((*pchr != '\0') && (*pchr != Separator))
178cdf0e10cSrcweir                 *pstr++ = *pchr++;
179cdf0e10cSrcweir 
180cdf0e10cSrcweir             if ((pstr > path) && ((*(pstr - 1) != '/')))
181cdf0e10cSrcweir                 *pstr++ = '/';
182cdf0e10cSrcweir 
183cdf0e10cSrcweir             *pstr = '\0';
184cdf0e10cSrcweir 
185cdf0e10cSrcweir             strcat(path, pszName);
186cdf0e10cSrcweir 
187cdf0e10cSrcweir             if (access(path, 0) == 0)
188cdf0e10cSrcweir             {
189cdf0e10cSrcweir                 char szRealPathBuf[PATH_MAX] = "";
190cdf0e10cSrcweir 
191cdf0e10cSrcweir                 if( NULL == realpath(path, szRealPathBuf) || (strlen(szRealPathBuf) >= (sal_uInt32)Max))
192cdf0e10cSrcweir                     return osl_Process_E_Unknown;
193cdf0e10cSrcweir 
194cdf0e10cSrcweir                 strcpy(pszBuffer, path);
195cdf0e10cSrcweir 
196cdf0e10cSrcweir                 return osl_Process_E_None;
197cdf0e10cSrcweir             }
198cdf0e10cSrcweir 
199cdf0e10cSrcweir             if (*pchr == Separator)
200cdf0e10cSrcweir                 pchr++;
201cdf0e10cSrcweir         }
202cdf0e10cSrcweir     }
203cdf0e10cSrcweir 
204cdf0e10cSrcweir     return osl_Process_E_NotFound;
205cdf0e10cSrcweir }
206cdf0e10cSrcweir 
207cdf0e10cSrcweir /******************************************************************************
208cdf0e10cSrcweir  *
209cdf0e10cSrcweir  * New io resource transfer functions
210cdf0e10cSrcweir  *
211cdf0e10cSrcweir  *****************************************************************************/
212cdf0e10cSrcweir 
213cdf0e10cSrcweir 
214cdf0e10cSrcweir /**********************************************
215cdf0e10cSrcweir  sendFdPipe
216cdf0e10cSrcweir  *********************************************/
217cdf0e10cSrcweir 
sendFdPipe(int PipeFD,int SocketFD)218cdf0e10cSrcweir static sal_Bool sendFdPipe(int PipeFD, int SocketFD)
219cdf0e10cSrcweir {
220cdf0e10cSrcweir     sal_Bool bRet = sal_False;
221cdf0e10cSrcweir 
222cdf0e10cSrcweir     struct iovec    iov[1];
223cdf0e10cSrcweir     struct msghdr   msg;
224cdf0e10cSrcweir     char            buf[2]; /* send_fd()/recv_fd() 2-byte protocol */
225cdf0e10cSrcweir     int nSend;
226cdf0e10cSrcweir     int RetCode=0;
227cdf0e10cSrcweir 
228cdf0e10cSrcweir #if defined(IOCHANNEL_TRANSFER_BSD)
229cdf0e10cSrcweir 
230cdf0e10cSrcweir     OSL_TRACE("IOCHANNEL_TRANSFER_BSD send");
231cdf0e10cSrcweir /*  OSL_TRACE("sending fd %i\n",SocketFD); */
232cdf0e10cSrcweir 
233cdf0e10cSrcweir     iov[0].iov_base = buf;
234cdf0e10cSrcweir     iov[0].iov_len  = sizeof(buf);
235cdf0e10cSrcweir     msg.msg_iov     = iov;
236cdf0e10cSrcweir     msg.msg_iovlen  = 1;
237cdf0e10cSrcweir     msg.msg_name    = NULL;
238cdf0e10cSrcweir     msg.msg_namelen = 0;
239cdf0e10cSrcweir 
240cdf0e10cSrcweir     msg.msg_accrights    = (caddr_t) &SocketFD; /* addr of descriptor */
241cdf0e10cSrcweir     msg.msg_accrightslen = sizeof(int);     /* pass 1 descriptor */
242cdf0e10cSrcweir     buf[1] = 0;                             /* zero status means OK */
243cdf0e10cSrcweir     buf[0] = 0;                             /* null byte flag to recv_fd() */
244cdf0e10cSrcweir 
245cdf0e10cSrcweir #else
246cdf0e10cSrcweir 
247cdf0e10cSrcweir     struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CONTROLLEN);
248cdf0e10cSrcweir 
249cdf0e10cSrcweir     OSL_TRACE("!!!!!! IOCHANNEL_TRANSFER_BSD_RENO send");
250cdf0e10cSrcweir /*  OSL_TRACE("sending fd %i\n",SocketFD); */
251cdf0e10cSrcweir 
252cdf0e10cSrcweir     iov[0].iov_base = buf;
253cdf0e10cSrcweir     iov[0].iov_len = sizeof(buf);
254cdf0e10cSrcweir     msg.msg_iov = iov;
255cdf0e10cSrcweir     msg.msg_iovlen = 1;
256cdf0e10cSrcweir     msg.msg_name = NULL;
257cdf0e10cSrcweir     msg.msg_namelen = 0;
258cdf0e10cSrcweir     msg.msg_control = (caddr_t) cmptr;
259cdf0e10cSrcweir     msg.msg_controllen = CONTROLLEN;
260cdf0e10cSrcweir 
261cdf0e10cSrcweir     cmptr->cmsg_level = SOL_SOCKET;
262cdf0e10cSrcweir     cmptr->cmsg_type = SCM_RIGHTS;
263cdf0e10cSrcweir     cmptr->cmsg_len = CONTROLLEN;
264cdf0e10cSrcweir     memcpy(CMSG_DATA(cmptr), &SocketFD, sizeof(int));
265cdf0e10cSrcweir 
266cdf0e10cSrcweir #endif
267cdf0e10cSrcweir 
268cdf0e10cSrcweir     if ( ( nSend = sendmsg(PipeFD, &msg, 0) ) > 0 )
269cdf0e10cSrcweir     {
270cdf0e10cSrcweir         bRet = sal_True;
271cdf0e10cSrcweir         OSL_TRACE("sendFdPipe : send '%i' bytes\n",nSend);
272cdf0e10cSrcweir 
273cdf0e10cSrcweir     }
274cdf0e10cSrcweir     else
275cdf0e10cSrcweir     {
276cdf0e10cSrcweir         OSL_TRACE("sendFdPipe : sending failed (%s)",strerror(errno));
277cdf0e10cSrcweir     }
278cdf0e10cSrcweir 
279cdf0e10cSrcweir     nSend=read(PipeFD,&RetCode,sizeof(RetCode));
280cdf0e10cSrcweir 
281cdf0e10cSrcweir     if ( nSend > 0 && RetCode == 1 )
282cdf0e10cSrcweir     {
283cdf0e10cSrcweir         OSL_TRACE("sendFdPipe : resource was received\n");
284cdf0e10cSrcweir     }
285cdf0e10cSrcweir     else
286cdf0e10cSrcweir     {
287cdf0e10cSrcweir         OSL_TRACE("sendFdPipe : resource wasn't received\n");
288cdf0e10cSrcweir     }
289cdf0e10cSrcweir 
290cdf0e10cSrcweir #if defined(IOCHANNEL_TRANSFER_BSD_RENO)
291cdf0e10cSrcweir     free(cmptr);
292cdf0e10cSrcweir #endif
293cdf0e10cSrcweir 
294cdf0e10cSrcweir     return bRet;
295cdf0e10cSrcweir }
296cdf0e10cSrcweir 
297cdf0e10cSrcweir /**********************************************
298cdf0e10cSrcweir  receiveFdPipe
299cdf0e10cSrcweir  *********************************************/
300cdf0e10cSrcweir 
receiveFdPipe(int PipeFD)301cdf0e10cSrcweir static oslSocket receiveFdPipe(int PipeFD)
302cdf0e10cSrcweir {
303cdf0e10cSrcweir     oslSocket pSocket = 0;
304cdf0e10cSrcweir     struct msghdr msghdr;
305cdf0e10cSrcweir     struct iovec iov[1];
306cdf0e10cSrcweir     char buffer[2];
307cdf0e10cSrcweir     sal_Int32 nRead;
308cdf0e10cSrcweir     int newfd=-1;
309cdf0e10cSrcweir     int nRetCode=0;
310cdf0e10cSrcweir /*  char *ptr; */
311cdf0e10cSrcweir 
312cdf0e10cSrcweir #if defined(IOCHANNEL_TRANSFER_BSD)
313cdf0e10cSrcweir 
314cdf0e10cSrcweir     OSL_TRACE("IOCHANNEL_TRANSFER_BSD receive\n");
315cdf0e10cSrcweir 
316cdf0e10cSrcweir     iov[0].iov_base = buffer;
317cdf0e10cSrcweir     iov[0].iov_len = sizeof(buffer);
318cdf0e10cSrcweir     msghdr.msg_name = NULL;
319cdf0e10cSrcweir     msghdr.msg_namelen = 0;
320cdf0e10cSrcweir     msghdr.msg_iov = iov;
321cdf0e10cSrcweir     msghdr.msg_iovlen = 1;
322cdf0e10cSrcweir     msghdr.msg_accrights = (caddr_t) &newfd; /* addr of descriptor */
323cdf0e10cSrcweir     msghdr.msg_accrightslen = sizeof(int);   /* receive 1 descriptor */
324cdf0e10cSrcweir 
325cdf0e10cSrcweir #else
326cdf0e10cSrcweir     struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CONTROLLEN);
327cdf0e10cSrcweir 
328cdf0e10cSrcweir     OSL_TRACE(" !!!! IOCHANNEL_TRANSFER_BSD_RENO receive");
329cdf0e10cSrcweir 
330cdf0e10cSrcweir     iov[0].iov_base = buffer;
331cdf0e10cSrcweir     iov[0].iov_len = sizeof(buffer);
332cdf0e10cSrcweir     msghdr.msg_name = NULL;
333cdf0e10cSrcweir     msghdr.msg_namelen = 0;
334cdf0e10cSrcweir     msghdr.msg_iov = iov;
335cdf0e10cSrcweir     msghdr.msg_iovlen = 1;
336cdf0e10cSrcweir 
337cdf0e10cSrcweir     msghdr.msg_control = (caddr_t) cmptr;
338cdf0e10cSrcweir     msghdr.msg_controllen = CONTROLLEN;
339cdf0e10cSrcweir 
340cdf0e10cSrcweir #endif
341cdf0e10cSrcweir 
342cdf0e10cSrcweir 
343cdf0e10cSrcweir #if defined(IOCHANNEL_TRANSFER_BSD)
344cdf0e10cSrcweir 
345cdf0e10cSrcweir     if ( ( nRead = recvmsg(PipeFD, &msghdr, 0) ) > 0 )
346cdf0e10cSrcweir     {
347cdf0e10cSrcweir         OSL_TRACE("receiveFdPipe : received '%i' bytes\n",nRead);
348cdf0e10cSrcweir     }
349cdf0e10cSrcweir #else
350cdf0e10cSrcweir 
351cdf0e10cSrcweir     if ( ( ( nRead = recvmsg(PipeFD, &msghdr, 0) ) > 0 ) &&
352cdf0e10cSrcweir         ( msghdr.msg_controllen == CONTROLLEN ) )
353cdf0e10cSrcweir     {
354cdf0e10cSrcweir         OSL_TRACE("receiveFdPipe : received '%i' bytes\n",nRead);
355cdf0e10cSrcweir         memcpy(&newfd, CMSG_DATA(cmptr), sizeof(int));
356cdf0e10cSrcweir     }
357cdf0e10cSrcweir #endif
358cdf0e10cSrcweir     else
359cdf0e10cSrcweir     {
360cdf0e10cSrcweir         OSL_TRACE("receiveFdPipe : receiving failed (%s)",strerror(errno));
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     if ( newfd >= 0 )
364cdf0e10cSrcweir     {
365cdf0e10cSrcweir         pSocket = __osl_createSocketImpl(newfd);
366cdf0e10cSrcweir         nRetCode=1;
367cdf0e10cSrcweir         OSL_TRACE("received fd %i\n",newfd);
368cdf0e10cSrcweir     }
369cdf0e10cSrcweir 
370cdf0e10cSrcweir     OSL_TRACE("receiveFdPipe : writing back %i",nRetCode);
371cdf0e10cSrcweir     nRead=write(PipeFD,&nRetCode,sizeof(nRetCode));
372cdf0e10cSrcweir 
373cdf0e10cSrcweir #if defined(IOCHANNEL_TRANSFER_BSD_RENO)
374cdf0e10cSrcweir     free(cmptr);
375cdf0e10cSrcweir #endif
376cdf0e10cSrcweir 
377cdf0e10cSrcweir     return pSocket;
378cdf0e10cSrcweir }
379cdf0e10cSrcweir 
380cdf0e10cSrcweir /**********************************************
381cdf0e10cSrcweir  osl_sendResourcePipe
382cdf0e10cSrcweir  *********************************************/
383cdf0e10cSrcweir 
osl_sendResourcePipe(oslPipe pPipe,oslSocket pSocket)384cdf0e10cSrcweir sal_Bool osl_sendResourcePipe(oslPipe pPipe, oslSocket pSocket)
385cdf0e10cSrcweir {
386cdf0e10cSrcweir     sal_Bool bRet = sal_False;
387cdf0e10cSrcweir 
388cdf0e10cSrcweir     if ( pSocket == 0 || pPipe == 0 )
389cdf0e10cSrcweir     {
390cdf0e10cSrcweir         return sal_False;
391cdf0e10cSrcweir     }
392cdf0e10cSrcweir 
393cdf0e10cSrcweir     bRet = sendFdPipe(pPipe->m_Socket,pSocket->m_Socket);
394cdf0e10cSrcweir 
395cdf0e10cSrcweir     return bRet;
396cdf0e10cSrcweir }
397cdf0e10cSrcweir 
398cdf0e10cSrcweir /**********************************************
399cdf0e10cSrcweir  osl_receiveResourcePipe
400cdf0e10cSrcweir  *********************************************/
401cdf0e10cSrcweir 
osl_receiveResourcePipe(oslPipe pPipe)402cdf0e10cSrcweir oslSocket osl_receiveResourcePipe(oslPipe pPipe)
403cdf0e10cSrcweir {
404cdf0e10cSrcweir     oslSocket pSocket=0;
405cdf0e10cSrcweir 
406cdf0e10cSrcweir     if ( pPipe == 0 )
407cdf0e10cSrcweir     {
408cdf0e10cSrcweir         return 0;
409cdf0e10cSrcweir     }
410cdf0e10cSrcweir 
411cdf0e10cSrcweir     pSocket = receiveFdPipe(pPipe->m_Socket);
412cdf0e10cSrcweir 
413cdf0e10cSrcweir     return (oslSocket) pSocket;
414cdf0e10cSrcweir }
415cdf0e10cSrcweir 
416cdf0e10cSrcweir 
417cdf0e10cSrcweir 
418cdf0e10cSrcweir /******************************************************************************
419cdf0e10cSrcweir  *
420cdf0e10cSrcweir  * Functions for starting a process
421cdf0e10cSrcweir  *
422cdf0e10cSrcweir  *****************************************************************************/
423cdf0e10cSrcweir 
ChildStatusProc(void * pData)424cdf0e10cSrcweir static void ChildStatusProc(void *pData)
425cdf0e10cSrcweir {
426cdf0e10cSrcweir     pid_t pid = -1;
427cdf0e10cSrcweir     int   status = 0;
428cdf0e10cSrcweir     int   channel[2];
429cdf0e10cSrcweir     ProcessData  data;
430cdf0e10cSrcweir     ProcessData *pdata;
431cdf0e10cSrcweir     int     stdOutput[2] = { -1, -1 }, stdInput[2] = { -1, -1 }, stdError[2] = { -1, -1 };
432cdf0e10cSrcweir 
433cdf0e10cSrcweir     pdata = (ProcessData *)pData;
434cdf0e10cSrcweir 
435cdf0e10cSrcweir     /* make a copy of our data, because forking will only copy
436cdf0e10cSrcweir        our local stack of the thread, so the process data will not be accessible
437cdf0e10cSrcweir        in our child process */
438cdf0e10cSrcweir     memcpy(&data, pData, sizeof(data));
439cdf0e10cSrcweir 
440cdf0e10cSrcweir     if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel) == -1)
441cdf0e10cSrcweir         status = errno;
442cdf0e10cSrcweir 
443cdf0e10cSrcweir     fcntl(channel[0], F_SETFD, FD_CLOEXEC);
444cdf0e10cSrcweir     fcntl(channel[1], F_SETFD, FD_CLOEXEC);
445cdf0e10cSrcweir 
446cdf0e10cSrcweir     /* Create redirected IO pipes */
447cdf0e10cSrcweir     if ( status == 0 && data.m_pInputWrite )
448cdf0e10cSrcweir         if (pipe( stdInput ) == -1)
449cdf0e10cSrcweir             status = errno;
450cdf0e10cSrcweir 
451cdf0e10cSrcweir     if ( status == 0 && data.m_pOutputRead )
452cdf0e10cSrcweir         if (pipe( stdOutput ) == -1)
453cdf0e10cSrcweir             status = errno;
454cdf0e10cSrcweir 
455cdf0e10cSrcweir     if ( status == 0 && data.m_pErrorRead )
456cdf0e10cSrcweir         if (pipe( stdError ) == -1)
457cdf0e10cSrcweir             status = errno;
458cdf0e10cSrcweir 
459cdf0e10cSrcweir     if ( (status == 0) && ((pid = fork()) == 0) )
460cdf0e10cSrcweir     {
461cdf0e10cSrcweir         /* Child */
462cdf0e10cSrcweir         int chstatus = 0;
463cdf0e10cSrcweir         sal_Int32 nWrote;
464cdf0e10cSrcweir 
465cdf0e10cSrcweir         if (channel[0] != -1) close(channel[0]);
466cdf0e10cSrcweir 
467cdf0e10cSrcweir         if ((data.m_uid != (uid_t)-1) && ((data.m_uid != getuid()) || (data.m_gid != getgid())))
468cdf0e10cSrcweir         {
469cdf0e10cSrcweir             OSL_ASSERT(geteuid() == 0);     /* must be root */
470cdf0e10cSrcweir 
471cdf0e10cSrcweir             if (! INIT_GROUPS(data.m_name, data.m_gid) || (setuid(data.m_uid) != 0))
472cdf0e10cSrcweir                 OSL_TRACE("Failed to change uid and guid, errno=%d (%s)\n", errno, strerror(errno));
473cdf0e10cSrcweir #if defined(LINUX) || defined (FREEBSD)
474cdf0e10cSrcweir             unsetenv("HOME");
475cdf0e10cSrcweir #else
476cdf0e10cSrcweir             putenv("HOME=");
477cdf0e10cSrcweir #endif
478cdf0e10cSrcweir         }
479cdf0e10cSrcweir 
480cdf0e10cSrcweir         if (data.m_pszDir)
481cdf0e10cSrcweir             chstatus = chdir(data.m_pszDir);
482cdf0e10cSrcweir 
483cdf0e10cSrcweir         if (chstatus == 0 && ((data.m_uid == (uid_t)-1) || ((data.m_uid == getuid()) && (data.m_gid == getgid()))))
484cdf0e10cSrcweir         {
485cdf0e10cSrcweir             int i;
486cdf0e10cSrcweir             for (i = 0; data.m_pszEnv[i] != NULL; i++)
487cdf0e10cSrcweir             {
488cdf0e10cSrcweir                 if (strchr(data.m_pszEnv[i], '=') == NULL)
489cdf0e10cSrcweir                 {
490cdf0e10cSrcweir                     unsetenv(data.m_pszEnv[i]); /*TODO: check error return*/
491cdf0e10cSrcweir                 }
492cdf0e10cSrcweir                 else
493cdf0e10cSrcweir                 {
494cdf0e10cSrcweir                     putenv(data.m_pszEnv[i]); /*TODO: check error return*/
495cdf0e10cSrcweir                 }
496cdf0e10cSrcweir             }
497cdf0e10cSrcweir 
498cdf0e10cSrcweir             OSL_TRACE("ChildStatusProc : starting '%s'",data.m_pszArgs[0]);
499cdf0e10cSrcweir 
500cdf0e10cSrcweir             /* Connect std IO to pipe ends */
501cdf0e10cSrcweir 
502cdf0e10cSrcweir             /* Write end of stdInput not used in child process */
503cdf0e10cSrcweir             if (stdInput[1] != -1) close( stdInput[1] );
504cdf0e10cSrcweir 
505cdf0e10cSrcweir             /* Read end of stdOutput not used in child process */
506cdf0e10cSrcweir             if (stdOutput[0] != -1) close( stdOutput[0] );
507cdf0e10cSrcweir 
508cdf0e10cSrcweir             /* Read end of stdError not used in child process */
509cdf0e10cSrcweir             if (stdError[0] != -1) close( stdError[0] );
510cdf0e10cSrcweir 
511cdf0e10cSrcweir             /* Redirect pipe ends to std IO */
512cdf0e10cSrcweir 
513cdf0e10cSrcweir             if ( stdInput[0] != STDIN_FILENO )
514cdf0e10cSrcweir             {
515cdf0e10cSrcweir                 dup2( stdInput[0], STDIN_FILENO );
516cdf0e10cSrcweir                 if (stdInput[0] != -1) close( stdInput[0] );
517cdf0e10cSrcweir             }
518cdf0e10cSrcweir 
519cdf0e10cSrcweir             if ( stdOutput[1] != STDOUT_FILENO )
520cdf0e10cSrcweir             {
521cdf0e10cSrcweir                 dup2( stdOutput[1], STDOUT_FILENO );
522cdf0e10cSrcweir                 if (stdOutput[1] != -1) close( stdOutput[1] );
523cdf0e10cSrcweir             }
524cdf0e10cSrcweir 
525cdf0e10cSrcweir             if ( stdError[1] != STDERR_FILENO )
526cdf0e10cSrcweir             {
527cdf0e10cSrcweir                 dup2( stdError[1], STDERR_FILENO );
528cdf0e10cSrcweir                 if (stdError[1] != -1) close( stdError[1] );
529cdf0e10cSrcweir             }
530cdf0e10cSrcweir 
531cdf0e10cSrcweir             pid=execv(data.m_pszArgs[0], (sal_Char **)data.m_pszArgs);
532cdf0e10cSrcweir 
533cdf0e10cSrcweir         }
534cdf0e10cSrcweir 
535cdf0e10cSrcweir         OSL_TRACE("Failed to exec, errno=%d (%s)\n", errno, strerror(errno));
536cdf0e10cSrcweir 
537cdf0e10cSrcweir         OSL_TRACE("ChildStatusProc : starting '%s' failed",data.m_pszArgs[0]);
538cdf0e10cSrcweir 
539cdf0e10cSrcweir         /* if we reach here, something went wrong */
540cdf0e10cSrcweir         nWrote = write(channel[1], &errno, sizeof(errno));
541cdf0e10cSrcweir         if (nWrote != sizeof(errno))
542cdf0e10cSrcweir             OSL_TRACE("sendFdPipe : sending failed (%s)",strerror(errno));
543cdf0e10cSrcweir 
544cdf0e10cSrcweir         if (channel[1] != -1) close(channel[1]);
545cdf0e10cSrcweir 
546cdf0e10cSrcweir         _exit(255);
547cdf0e10cSrcweir     }
548cdf0e10cSrcweir     else
549cdf0e10cSrcweir     { /* Parent */
550cdf0e10cSrcweir         int i = -1;
551cdf0e10cSrcweir         if (channel[1] != -1) close(channel[1]);
552cdf0e10cSrcweir 
553cdf0e10cSrcweir         /* Close unused pipe ends */
554cdf0e10cSrcweir         if (stdInput[0] != -1) close( stdInput[0] );
555cdf0e10cSrcweir         if (stdOutput[1] != -1) close( stdOutput[1] );
556cdf0e10cSrcweir         if (stdError[1] != -1) close( stdError[1] );
557cdf0e10cSrcweir 
558cdf0e10cSrcweir         if (pid > 0)
559cdf0e10cSrcweir         {
560cdf0e10cSrcweir             while (((i = read(channel[0], &status, sizeof(status))) < 0))
561cdf0e10cSrcweir             {
562cdf0e10cSrcweir                 if (errno != EINTR)
563cdf0e10cSrcweir                     break;
564cdf0e10cSrcweir             }
565cdf0e10cSrcweir         }
566cdf0e10cSrcweir 
567cdf0e10cSrcweir         if (channel[0] != -1) close(channel[0]);
568cdf0e10cSrcweir 
569cdf0e10cSrcweir         if ((pid > 0) && (i == 0))
570cdf0e10cSrcweir         {
571cdf0e10cSrcweir             pid_t   child_pid;
572cdf0e10cSrcweir             osl_acquireMutex(ChildListMutex);
573cdf0e10cSrcweir 
574cdf0e10cSrcweir             pdata->m_pProcImpl->m_pid = pid;
575cdf0e10cSrcweir             pdata->m_pProcImpl->m_pnext = ChildList;
576cdf0e10cSrcweir             ChildList = pdata->m_pProcImpl;
577cdf0e10cSrcweir 
578cdf0e10cSrcweir             /* Store used pipe ends in data structure */
579cdf0e10cSrcweir 
580cdf0e10cSrcweir             if ( pdata->m_pInputWrite )
581cdf0e10cSrcweir                 *(pdata->m_pInputWrite) = osl_createFileHandleFromFD( stdInput[1] );
582cdf0e10cSrcweir 
583cdf0e10cSrcweir             if ( pdata->m_pOutputRead )
584cdf0e10cSrcweir                 *(pdata->m_pOutputRead) = osl_createFileHandleFromFD( stdOutput[0] );
585cdf0e10cSrcweir 
586cdf0e10cSrcweir             if ( pdata->m_pErrorRead )
587cdf0e10cSrcweir                 *(pdata->m_pErrorRead) = osl_createFileHandleFromFD( stdError[0] );
588cdf0e10cSrcweir 
589cdf0e10cSrcweir             osl_releaseMutex(ChildListMutex);
590cdf0e10cSrcweir 
591cdf0e10cSrcweir             osl_setCondition(pdata->m_started);
592cdf0e10cSrcweir 
593cdf0e10cSrcweir             do
594cdf0e10cSrcweir             {
595cdf0e10cSrcweir                 child_pid = waitpid(pid, &status, 0);
596cdf0e10cSrcweir             } while ( 0 > child_pid && EINTR == errno );
597cdf0e10cSrcweir 
598cdf0e10cSrcweir             if ( child_pid < 0)
599cdf0e10cSrcweir             {
600cdf0e10cSrcweir                 OSL_TRACE("Failed to wait for child process, errno=%d (%s)\n", errno, strerror(errno));
601cdf0e10cSrcweir 
602cdf0e10cSrcweir                 /*
603cdf0e10cSrcweir                 We got an other error than EINTR. Anyway we have to wake up the
604cdf0e10cSrcweir                 waiting thread under any circumstances */
605cdf0e10cSrcweir 
606cdf0e10cSrcweir                 child_pid = pid;
607cdf0e10cSrcweir             }
608cdf0e10cSrcweir 
609cdf0e10cSrcweir 
610cdf0e10cSrcweir             if ( child_pid > 0 )
611cdf0e10cSrcweir             {
612cdf0e10cSrcweir                 oslProcessImpl* pChild;
613cdf0e10cSrcweir 
614cdf0e10cSrcweir                 osl_acquireMutex(ChildListMutex);
615cdf0e10cSrcweir 
616cdf0e10cSrcweir                 pChild = ChildList;
617cdf0e10cSrcweir 
618cdf0e10cSrcweir                 /* check if it is one of our child processes */
619cdf0e10cSrcweir                 while (pChild != NULL)
620cdf0e10cSrcweir                 {
621cdf0e10cSrcweir                     if (pChild->m_pid == child_pid)
622cdf0e10cSrcweir                     {
623cdf0e10cSrcweir                         if (WIFEXITED(status))
624cdf0e10cSrcweir                             pChild->m_status = WEXITSTATUS(status);
625cdf0e10cSrcweir                         else
626cdf0e10cSrcweir                             pChild->m_status = -1;
627cdf0e10cSrcweir 
628cdf0e10cSrcweir                         osl_setCondition(pChild->m_terminated);
629cdf0e10cSrcweir                     }
630cdf0e10cSrcweir 
631cdf0e10cSrcweir                     pChild = pChild->m_pnext;
632cdf0e10cSrcweir                 }
633cdf0e10cSrcweir 
634cdf0e10cSrcweir                 osl_releaseMutex(ChildListMutex);
635cdf0e10cSrcweir             }
636cdf0e10cSrcweir         }
637cdf0e10cSrcweir         else
638cdf0e10cSrcweir         {
639cdf0e10cSrcweir             OSL_TRACE("ChildStatusProc : starting '%s' failed",data.m_pszArgs[0]);
640cdf0e10cSrcweir             OSL_TRACE("Failed to launch child process, child reports errno=%d (%s)\n", status, strerror(status));
641cdf0e10cSrcweir 
642cdf0e10cSrcweir             /* Close pipe ends */
643cdf0e10cSrcweir             if ( pdata->m_pInputWrite )
644cdf0e10cSrcweir                 *pdata->m_pInputWrite = NULL;
645cdf0e10cSrcweir 
646cdf0e10cSrcweir             if ( pdata->m_pOutputRead )
647cdf0e10cSrcweir                 *pdata->m_pOutputRead = NULL;
648cdf0e10cSrcweir 
649cdf0e10cSrcweir             if ( pdata->m_pErrorRead )
650cdf0e10cSrcweir                 *pdata->m_pErrorRead = NULL;
651cdf0e10cSrcweir 
652cdf0e10cSrcweir             if (stdInput[1] != -1) close( stdInput[1] );
653cdf0e10cSrcweir             if (stdOutput[0] != -1) close( stdOutput[0] );
654cdf0e10cSrcweir             if (stdError[0] != -1) close( stdError[0] );
655cdf0e10cSrcweir 
656cdf0e10cSrcweir             //if pid > 0 then a process was created, even if it later failed
657cdf0e10cSrcweir             //e.g. bash searching for a command to execute, and we still
658cdf0e10cSrcweir             //need to clean it up to avoid "defunct" processes
659cdf0e10cSrcweir             if (pid > 0)
660cdf0e10cSrcweir             {
661cdf0e10cSrcweir                 pid_t child_pid;
662cdf0e10cSrcweir                 do
663cdf0e10cSrcweir                 {
664cdf0e10cSrcweir                     child_pid = waitpid(pid, &status, 0);
665cdf0e10cSrcweir                 } while ( 0 > child_pid && EINTR == errno );
666cdf0e10cSrcweir             }
667cdf0e10cSrcweir 
668cdf0e10cSrcweir             /* notify (and unblock) parent thread */
669cdf0e10cSrcweir             osl_setCondition(pdata->m_started);
670cdf0e10cSrcweir         }
671cdf0e10cSrcweir     }
672cdf0e10cSrcweir }
673cdf0e10cSrcweir 
674cdf0e10cSrcweir /**********************************************
675cdf0e10cSrcweir  osl_executeProcess_WithRedirectedIO
676cdf0e10cSrcweir  *********************************************/
677cdf0e10cSrcweir 
osl_executeProcess_WithRedirectedIO(rtl_uString * ustrImageName,rtl_uString * ustrArguments[],sal_uInt32 nArguments,oslProcessOption Options,oslSecurity Security,rtl_uString * ustrWorkDir,rtl_uString * ustrEnvironment[],sal_uInt32 nEnvironmentVars,oslProcess * pProcess,oslFileHandle * pInputWrite,oslFileHandle * pOutputRead,oslFileHandle * pErrorRead)678cdf0e10cSrcweir oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO(
679cdf0e10cSrcweir                                             rtl_uString *ustrImageName,
680cdf0e10cSrcweir                                             rtl_uString *ustrArguments[],
681cdf0e10cSrcweir                                             sal_uInt32   nArguments,
682cdf0e10cSrcweir                                             oslProcessOption Options,
683cdf0e10cSrcweir                                             oslSecurity Security,
684cdf0e10cSrcweir                                             rtl_uString *ustrWorkDir,
685cdf0e10cSrcweir                                             rtl_uString *ustrEnvironment[],
686cdf0e10cSrcweir                                             sal_uInt32   nEnvironmentVars,
687cdf0e10cSrcweir                                             oslProcess *pProcess,
688cdf0e10cSrcweir                                             oslFileHandle   *pInputWrite,
689cdf0e10cSrcweir                                             oslFileHandle   *pOutputRead,
690cdf0e10cSrcweir                                             oslFileHandle   *pErrorRead
691cdf0e10cSrcweir                                             )
692cdf0e10cSrcweir {
693cdf0e10cSrcweir 
694cdf0e10cSrcweir     oslProcessError Error;
695509a48ffSpfg     sal_Char* pszWorkDir=NULL;
696509a48ffSpfg     sal_Char** pArguments=NULL;
697509a48ffSpfg     sal_Char** pEnvironment=NULL;
698cdf0e10cSrcweir     unsigned int idx;
699cdf0e10cSrcweir 
700cdf0e10cSrcweir     char szImagePath[PATH_MAX] = "";
701cdf0e10cSrcweir     char szWorkDir[PATH_MAX] = "";
702cdf0e10cSrcweir 
703cdf0e10cSrcweir     if ( ustrImageName && ustrImageName->length )
704cdf0e10cSrcweir     {
705cdf0e10cSrcweir         FileURLToPath( szImagePath, PATH_MAX, ustrImageName );
706cdf0e10cSrcweir     }
707cdf0e10cSrcweir 
708509a48ffSpfg     if ( ustrWorkDir != NULL && ustrWorkDir->length )
709cdf0e10cSrcweir     {
710cdf0e10cSrcweir         FileURLToPath( szWorkDir, PATH_MAX, ustrWorkDir );
711cdf0e10cSrcweir         pszWorkDir = szWorkDir;
712cdf0e10cSrcweir     }
713cdf0e10cSrcweir 
714509a48ffSpfg     if ( pArguments == NULL && nArguments > 0 )
715cdf0e10cSrcweir     {
716cdf0e10cSrcweir         pArguments = (sal_Char**) malloc( ( nArguments + 2 ) * sizeof(sal_Char*) );
717cdf0e10cSrcweir     }
718cdf0e10cSrcweir 
719cdf0e10cSrcweir 
720cdf0e10cSrcweir     for ( idx = 0 ; idx < nArguments ; ++idx )
721cdf0e10cSrcweir     {
722509a48ffSpfg         rtl_String* strArg =NULL;
723cdf0e10cSrcweir 
724cdf0e10cSrcweir 
725cdf0e10cSrcweir         rtl_uString2String( &strArg,
726cdf0e10cSrcweir                             rtl_uString_getStr(ustrArguments[idx]),
727cdf0e10cSrcweir                             rtl_uString_getLength(ustrArguments[idx]),
728cdf0e10cSrcweir                             osl_getThreadTextEncoding(),
729cdf0e10cSrcweir                             OUSTRING_TO_OSTRING_CVTFLAGS );
730cdf0e10cSrcweir 
731cdf0e10cSrcweir         pArguments[idx]=strdup(rtl_string_getStr(strArg));
732cdf0e10cSrcweir         rtl_string_release(strArg);
733509a48ffSpfg         pArguments[idx+1]=NULL;
734cdf0e10cSrcweir     }
735cdf0e10cSrcweir 
736cdf0e10cSrcweir     for ( idx = 0 ; idx < nEnvironmentVars ; ++idx )
737cdf0e10cSrcweir     {
738509a48ffSpfg         rtl_String* strEnv=NULL;
739cdf0e10cSrcweir 
740509a48ffSpfg         if ( pEnvironment == NULL )
741cdf0e10cSrcweir         {
742cdf0e10cSrcweir             pEnvironment = (sal_Char**) malloc( ( nEnvironmentVars + 2 ) * sizeof(sal_Char*) );
743cdf0e10cSrcweir         }
744cdf0e10cSrcweir 
745cdf0e10cSrcweir         rtl_uString2String( &strEnv,
746cdf0e10cSrcweir                             rtl_uString_getStr(ustrEnvironment[idx]),
747cdf0e10cSrcweir                             rtl_uString_getLength(ustrEnvironment[idx]),
748cdf0e10cSrcweir                             osl_getThreadTextEncoding(),
749cdf0e10cSrcweir                             OUSTRING_TO_OSTRING_CVTFLAGS );
750cdf0e10cSrcweir 
751cdf0e10cSrcweir         pEnvironment[idx]=strdup(rtl_string_getStr(strEnv));
752cdf0e10cSrcweir         rtl_string_release(strEnv);
753509a48ffSpfg         pEnvironment[idx+1]=NULL;
754cdf0e10cSrcweir     }
755cdf0e10cSrcweir 
756cdf0e10cSrcweir 
757cdf0e10cSrcweir     Error = osl_psz_executeProcess(szImagePath,
758cdf0e10cSrcweir                                    pArguments,
759cdf0e10cSrcweir                                    Options,
760cdf0e10cSrcweir                                    Security,
761cdf0e10cSrcweir                                    pszWorkDir,
762cdf0e10cSrcweir                                    pEnvironment,
763cdf0e10cSrcweir                                    pProcess,
764cdf0e10cSrcweir                                    pInputWrite,
765cdf0e10cSrcweir                                    pOutputRead,
766cdf0e10cSrcweir                                    pErrorRead
767cdf0e10cSrcweir                                    );
768cdf0e10cSrcweir 
769509a48ffSpfg     if ( pArguments != NULL )
770cdf0e10cSrcweir     {
771cdf0e10cSrcweir         for ( idx = 0 ; idx < nArguments ; ++idx )
772cdf0e10cSrcweir         {
773509a48ffSpfg             if ( pArguments[idx] != NULL )
774cdf0e10cSrcweir             {
775cdf0e10cSrcweir                 free(pArguments[idx]);
776cdf0e10cSrcweir             }
777cdf0e10cSrcweir         }
778cdf0e10cSrcweir         free(pArguments);
779cdf0e10cSrcweir     }
780cdf0e10cSrcweir 
781509a48ffSpfg     if ( pEnvironment != NULL )
782cdf0e10cSrcweir     {
783cdf0e10cSrcweir         for ( idx = 0 ; idx < nEnvironmentVars ; ++idx )
784cdf0e10cSrcweir         {
785509a48ffSpfg             if ( pEnvironment[idx] != NULL )
786cdf0e10cSrcweir             {
787cdf0e10cSrcweir                 free(pEnvironment[idx]);
788cdf0e10cSrcweir             }
789cdf0e10cSrcweir         }
790cdf0e10cSrcweir         free(pEnvironment);
791cdf0e10cSrcweir     }
792cdf0e10cSrcweir 
793cdf0e10cSrcweir     return Error;
794cdf0e10cSrcweir }
795cdf0e10cSrcweir 
796cdf0e10cSrcweir /**********************************************
797cdf0e10cSrcweir  osl_executeProcess
798cdf0e10cSrcweir  *********************************************/
799cdf0e10cSrcweir 
osl_executeProcess(rtl_uString * ustrImageName,rtl_uString * ustrArguments[],sal_uInt32 nArguments,oslProcessOption Options,oslSecurity Security,rtl_uString * ustrWorkDir,rtl_uString * ustrEnvironment[],sal_uInt32 nEnvironmentVars,oslProcess * pProcess)800cdf0e10cSrcweir oslProcessError SAL_CALL osl_executeProcess(
801cdf0e10cSrcweir                                             rtl_uString *ustrImageName,
802cdf0e10cSrcweir                                             rtl_uString *ustrArguments[],
803cdf0e10cSrcweir                                             sal_uInt32   nArguments,
804cdf0e10cSrcweir                                             oslProcessOption Options,
805cdf0e10cSrcweir                                             oslSecurity Security,
806cdf0e10cSrcweir                                             rtl_uString *ustrWorkDir,
807cdf0e10cSrcweir                                             rtl_uString *ustrEnvironment[],
808cdf0e10cSrcweir                                             sal_uInt32   nEnvironmentVars,
809cdf0e10cSrcweir                                             oslProcess *pProcess
810cdf0e10cSrcweir                                             )
811cdf0e10cSrcweir {
812cdf0e10cSrcweir     return osl_executeProcess_WithRedirectedIO(
813cdf0e10cSrcweir         ustrImageName,
814cdf0e10cSrcweir         ustrArguments,
815cdf0e10cSrcweir         nArguments,
816cdf0e10cSrcweir         Options,
817cdf0e10cSrcweir         Security,
818cdf0e10cSrcweir         ustrWorkDir,
819cdf0e10cSrcweir         ustrEnvironment,
820cdf0e10cSrcweir         nEnvironmentVars,
821cdf0e10cSrcweir         pProcess,
822cdf0e10cSrcweir         NULL,
823cdf0e10cSrcweir         NULL,
824cdf0e10cSrcweir         NULL
825cdf0e10cSrcweir         );
826cdf0e10cSrcweir }
827cdf0e10cSrcweir 
828cdf0e10cSrcweir /**********************************************
829cdf0e10cSrcweir  osl_psz_executeProcess
830cdf0e10cSrcweir  *********************************************/
831cdf0e10cSrcweir 
osl_psz_executeProcess(sal_Char * pszImageName,sal_Char * pszArguments[],oslProcessOption Options,oslSecurity Security,sal_Char * pszDirectory,sal_Char * pszEnvironments[],oslProcess * pProcess,oslFileHandle * pInputWrite,oslFileHandle * pOutputRead,oslFileHandle * pErrorRead)832cdf0e10cSrcweir oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
833cdf0e10cSrcweir                                                 sal_Char *pszArguments[],
834cdf0e10cSrcweir                                                 oslProcessOption Options,
835cdf0e10cSrcweir                                                 oslSecurity Security,
836cdf0e10cSrcweir                                                 sal_Char *pszDirectory,
837cdf0e10cSrcweir                                                 sal_Char *pszEnvironments[],
838cdf0e10cSrcweir                                                 oslProcess *pProcess,
839cdf0e10cSrcweir                                                 oslFileHandle   *pInputWrite,
840cdf0e10cSrcweir                                                 oslFileHandle   *pOutputRead,
841cdf0e10cSrcweir                                                 oslFileHandle   *pErrorRead
842cdf0e10cSrcweir                                                 )
843cdf0e10cSrcweir {
844cdf0e10cSrcweir     int     i;
845cdf0e10cSrcweir     sal_Char    path[PATH_MAX + 1];
846cdf0e10cSrcweir     ProcessData Data;
847cdf0e10cSrcweir     oslThread hThread;
848cdf0e10cSrcweir 
849cdf0e10cSrcweir     path[0] = '\0';
850cdf0e10cSrcweir 
851cdf0e10cSrcweir     memset(&Data,0,sizeof(ProcessData));
852cdf0e10cSrcweir     Data.m_pInputWrite = pInputWrite;
853cdf0e10cSrcweir     Data.m_pOutputRead = pOutputRead;
854cdf0e10cSrcweir     Data.m_pErrorRead = pErrorRead;
855cdf0e10cSrcweir 
856cdf0e10cSrcweir     if (pszImageName == NULL)
857cdf0e10cSrcweir         pszImageName = pszArguments[0];
858cdf0e10cSrcweir 
859cdf0e10cSrcweir     OSL_ASSERT(pszImageName != NULL);
860cdf0e10cSrcweir 
861509a48ffSpfg     if ( pszImageName == NULL )
862cdf0e10cSrcweir     {
863cdf0e10cSrcweir         return osl_Process_E_NotFound;
864cdf0e10cSrcweir     }
865cdf0e10cSrcweir 
866cdf0e10cSrcweir     if ((Options & osl_Process_SEARCHPATH) &&
867cdf0e10cSrcweir         (osl_searchPath_impl(pszImageName, NULL, '\0', path, sizeof(path)) == osl_Process_E_None))
868cdf0e10cSrcweir         pszImageName = path;
869cdf0e10cSrcweir 
870cdf0e10cSrcweir     Data.m_pszArgs[0] = strdup(pszImageName);
871509a48ffSpfg     Data.m_pszArgs[1] = NULL;
872cdf0e10cSrcweir 
873cdf0e10cSrcweir     if ( pszArguments != 0 )
874cdf0e10cSrcweir     {
875cdf0e10cSrcweir         for (i = 0; ((i + 2) < MAX_ARGS) && (pszArguments[i] != NULL); i++)
876cdf0e10cSrcweir             Data.m_pszArgs[i+1] = strdup(pszArguments[i]);
877cdf0e10cSrcweir         Data.m_pszArgs[i+2] = NULL;
878cdf0e10cSrcweir     }
879cdf0e10cSrcweir 
880cdf0e10cSrcweir     Data.m_options = Options;
881cdf0e10cSrcweir     Data.m_pszDir  = (pszDirectory != NULL) ? strdup(pszDirectory) : NULL;
882cdf0e10cSrcweir 
883cdf0e10cSrcweir     if (pszEnvironments != NULL)
884cdf0e10cSrcweir     {
885cdf0e10cSrcweir         for (i = 0; ((i + 1) < MAX_ENVS) && (pszEnvironments[i] != NULL); i++)
886cdf0e10cSrcweir             Data.m_pszEnv[i] = strdup(pszEnvironments[i]);
887cdf0e10cSrcweir         Data.m_pszEnv[i+1] = NULL;
888cdf0e10cSrcweir     }
889cdf0e10cSrcweir     else
890cdf0e10cSrcweir         Data.m_pszEnv[0] = NULL;
891cdf0e10cSrcweir 
892cdf0e10cSrcweir     if (Security != NULL)
893cdf0e10cSrcweir     {
894cdf0e10cSrcweir         Data.m_uid  = ((oslSecurityImpl*)Security)->m_pPasswd.pw_uid;
895cdf0e10cSrcweir         Data.m_gid  = ((oslSecurityImpl*)Security)->m_pPasswd.pw_gid;
896cdf0e10cSrcweir         Data.m_name = ((oslSecurityImpl*)Security)->m_pPasswd.pw_name;
897cdf0e10cSrcweir     }
898cdf0e10cSrcweir     else
899cdf0e10cSrcweir         Data.m_uid = (uid_t)-1;
900cdf0e10cSrcweir 
901cdf0e10cSrcweir     Data.m_pProcImpl = (oslProcessImpl*) malloc(sizeof(oslProcessImpl));
902cdf0e10cSrcweir     Data.m_pProcImpl->m_pid = 0;
903cdf0e10cSrcweir     Data.m_pProcImpl->m_terminated = osl_createCondition();
904cdf0e10cSrcweir     Data.m_pProcImpl->m_pnext = NULL;
905cdf0e10cSrcweir 
906cdf0e10cSrcweir     if (ChildListMutex == NULL)
907cdf0e10cSrcweir         ChildListMutex = osl_createMutex();
908cdf0e10cSrcweir 
909cdf0e10cSrcweir     Data.m_started = osl_createCondition();
910cdf0e10cSrcweir 
911cdf0e10cSrcweir     hThread = osl_createThread(ChildStatusProc, &Data);
912cdf0e10cSrcweir 
913cdf0e10cSrcweir     osl_waitCondition(Data.m_started, NULL);
914cdf0e10cSrcweir     osl_destroyCondition(Data.m_started);
915cdf0e10cSrcweir 
916cdf0e10cSrcweir     for (i = 0; Data.m_pszArgs[i] != NULL; i++)
917cdf0e10cSrcweir           free((void *)Data.m_pszArgs[i]);
918cdf0e10cSrcweir 
919cdf0e10cSrcweir     for (i = 0; Data.m_pszEnv[i] != NULL; i++)
920cdf0e10cSrcweir           free((void *)Data.m_pszEnv[i]);
921cdf0e10cSrcweir 
922509a48ffSpfg     if ( Data.m_pszDir != NULL )
923cdf0e10cSrcweir     {
924cdf0e10cSrcweir         free((void *)Data.m_pszDir);
925cdf0e10cSrcweir     }
926cdf0e10cSrcweir 
927cdf0e10cSrcweir     osl_destroyThread(hThread);
928cdf0e10cSrcweir 
929cdf0e10cSrcweir     if (Data.m_pProcImpl->m_pid != 0)
930cdf0e10cSrcweir     {
931cdf0e10cSrcweir         *pProcess = Data.m_pProcImpl;
932cdf0e10cSrcweir 
933cdf0e10cSrcweir         if (Options & osl_Process_WAIT)
934cdf0e10cSrcweir             osl_joinProcess(*pProcess);
935cdf0e10cSrcweir 
936cdf0e10cSrcweir         return osl_Process_E_None;
937cdf0e10cSrcweir     }
938cdf0e10cSrcweir 
939cdf0e10cSrcweir     osl_destroyCondition(Data.m_pProcImpl->m_terminated);
940cdf0e10cSrcweir     free(Data.m_pProcImpl);
941cdf0e10cSrcweir 
942cdf0e10cSrcweir     return osl_Process_E_Unknown;
943cdf0e10cSrcweir }
944cdf0e10cSrcweir 
945cdf0e10cSrcweir 
946cdf0e10cSrcweir /******************************************************************************
947cdf0e10cSrcweir  *
948cdf0e10cSrcweir  * Functions for processes
949cdf0e10cSrcweir  *
950cdf0e10cSrcweir  *****************************************************************************/
951cdf0e10cSrcweir 
952cdf0e10cSrcweir 
953cdf0e10cSrcweir /**********************************************
954cdf0e10cSrcweir  osl_terminateProcess
955cdf0e10cSrcweir  *********************************************/
956cdf0e10cSrcweir 
osl_terminateProcess(oslProcess Process)957cdf0e10cSrcweir oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
958cdf0e10cSrcweir {
959cdf0e10cSrcweir     if (Process == NULL)
960cdf0e10cSrcweir         return osl_Process_E_Unknown;
961cdf0e10cSrcweir 
962cdf0e10cSrcweir     if (kill(((oslProcessImpl*)Process)->m_pid, SIGKILL) != 0)
963cdf0e10cSrcweir     {
964cdf0e10cSrcweir         switch (errno)
965cdf0e10cSrcweir         {
966cdf0e10cSrcweir             case EPERM:
967cdf0e10cSrcweir                 return osl_Process_E_NoPermission;
968cdf0e10cSrcweir 
969cdf0e10cSrcweir             case ESRCH:
970cdf0e10cSrcweir                 return osl_Process_E_NotFound;
971cdf0e10cSrcweir 
972cdf0e10cSrcweir             default:
973cdf0e10cSrcweir                 return osl_Process_E_Unknown;
974cdf0e10cSrcweir         }
975cdf0e10cSrcweir     }
976cdf0e10cSrcweir 
977cdf0e10cSrcweir     return osl_Process_E_None;
978cdf0e10cSrcweir }
979cdf0e10cSrcweir 
980cdf0e10cSrcweir /**********************************************
981cdf0e10cSrcweir  osl_getProcess
982cdf0e10cSrcweir  *********************************************/
983cdf0e10cSrcweir 
osl_getProcess(oslProcessIdentifier Ident)984cdf0e10cSrcweir oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident)
985cdf0e10cSrcweir {
986cdf0e10cSrcweir     oslProcessImpl *pProcImpl;
987cdf0e10cSrcweir 
988cdf0e10cSrcweir     if (kill(Ident, 0) != -1)
989cdf0e10cSrcweir     {
990cdf0e10cSrcweir         oslProcessImpl* pChild;
991cdf0e10cSrcweir 
992cdf0e10cSrcweir         if (ChildListMutex == NULL)
993cdf0e10cSrcweir             ChildListMutex = osl_createMutex();
994cdf0e10cSrcweir 
995cdf0e10cSrcweir         osl_acquireMutex(ChildListMutex);
996cdf0e10cSrcweir 
997cdf0e10cSrcweir         pChild = ChildList;
998cdf0e10cSrcweir 
999cdf0e10cSrcweir         /* check if it is one of our child processes */
1000cdf0e10cSrcweir         while (pChild != NULL)
1001cdf0e10cSrcweir         {
1002cdf0e10cSrcweir             if (Ident == (sal_uInt32) pChild->m_pid)
1003cdf0e10cSrcweir                 break;
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir             pChild = pChild->m_pnext;
1006cdf0e10cSrcweir         }
1007cdf0e10cSrcweir 
1008cdf0e10cSrcweir         pProcImpl = (oslProcessImpl*) malloc(sizeof(oslProcessImpl));
1009cdf0e10cSrcweir         pProcImpl->m_pid        = Ident;
1010cdf0e10cSrcweir         pProcImpl->m_terminated = osl_createCondition();
1011cdf0e10cSrcweir 
1012cdf0e10cSrcweir         if (pChild != NULL)
1013cdf0e10cSrcweir         {
1014cdf0e10cSrcweir             /* process is a child so insert into list */
1015cdf0e10cSrcweir             pProcImpl->m_pnext = pChild->m_pnext;
1016cdf0e10cSrcweir             pChild->m_pnext = pProcImpl;
1017cdf0e10cSrcweir 
1018cdf0e10cSrcweir             pProcImpl->m_status = pChild->m_status;
1019cdf0e10cSrcweir 
1020cdf0e10cSrcweir             if (osl_checkCondition(pChild->m_terminated))
1021cdf0e10cSrcweir                 osl_setCondition(pProcImpl->m_terminated);
1022cdf0e10cSrcweir         }
1023cdf0e10cSrcweir         else
1024cdf0e10cSrcweir             pProcImpl->m_pnext = NULL;
1025cdf0e10cSrcweir 
1026cdf0e10cSrcweir         osl_releaseMutex(ChildListMutex);
1027cdf0e10cSrcweir     }
1028cdf0e10cSrcweir     else
1029cdf0e10cSrcweir         pProcImpl = NULL;
1030cdf0e10cSrcweir 
1031cdf0e10cSrcweir     return (pProcImpl);
1032cdf0e10cSrcweir }
1033cdf0e10cSrcweir 
1034cdf0e10cSrcweir /**********************************************
1035cdf0e10cSrcweir  osl_freeProcessHandle
1036cdf0e10cSrcweir  *********************************************/
1037cdf0e10cSrcweir 
osl_freeProcessHandle(oslProcess Process)1038cdf0e10cSrcweir void SAL_CALL osl_freeProcessHandle(oslProcess Process)
1039cdf0e10cSrcweir {
1040cdf0e10cSrcweir     if (Process != NULL)
1041cdf0e10cSrcweir     {
1042cdf0e10cSrcweir         oslProcessImpl *pChild, *pPrev = NULL;
1043cdf0e10cSrcweir 
1044cdf0e10cSrcweir         OSL_ASSERT(ChildListMutex != NULL);
1045cdf0e10cSrcweir 
1046cdf0e10cSrcweir         if ( ChildListMutex == 0 )
1047cdf0e10cSrcweir         {
1048cdf0e10cSrcweir             return;
1049cdf0e10cSrcweir         }
1050cdf0e10cSrcweir 
1051cdf0e10cSrcweir         osl_acquireMutex(ChildListMutex);
1052cdf0e10cSrcweir 
1053cdf0e10cSrcweir         pChild = ChildList;
1054cdf0e10cSrcweir 
1055cdf0e10cSrcweir         /* remove process from child list */
1056cdf0e10cSrcweir         while (pChild != NULL)
1057cdf0e10cSrcweir         {
1058cdf0e10cSrcweir             if (pChild == (oslProcessImpl*)Process)
1059cdf0e10cSrcweir             {
1060cdf0e10cSrcweir                 if (pPrev != NULL)
1061cdf0e10cSrcweir                     pPrev->m_pnext = pChild->m_pnext;
1062cdf0e10cSrcweir                 else
1063cdf0e10cSrcweir                     ChildList = pChild->m_pnext;
1064cdf0e10cSrcweir 
1065cdf0e10cSrcweir                 break;
1066cdf0e10cSrcweir             }
1067cdf0e10cSrcweir 
1068cdf0e10cSrcweir             pPrev  = pChild;
1069cdf0e10cSrcweir             pChild = pChild->m_pnext;
1070cdf0e10cSrcweir         }
1071cdf0e10cSrcweir 
1072cdf0e10cSrcweir         osl_releaseMutex(ChildListMutex);
1073cdf0e10cSrcweir 
1074cdf0e10cSrcweir         osl_destroyCondition(((oslProcessImpl*)Process)->m_terminated);
1075cdf0e10cSrcweir 
1076cdf0e10cSrcweir         free(Process);
1077cdf0e10cSrcweir     }
1078cdf0e10cSrcweir }
1079cdf0e10cSrcweir 
1080cdf0e10cSrcweir #if defined(LINUX)
1081cdf0e10cSrcweir struct osl_procStat
1082cdf0e10cSrcweir {
1083cdf0e10cSrcweir     /* from 'stat' */
1084cdf0e10cSrcweir     pid_t pid;                /* pid */
1085cdf0e10cSrcweir     char command[16];         /* 'argv[0]' */ /* mfe: it all right char comm[16] in kernel! */
1086cdf0e10cSrcweir     char state;               /* state (running, stopped, ...) */
1087cdf0e10cSrcweir     pid_t ppid;               /* parent pid */
1088cdf0e10cSrcweir     pid_t pgrp;               /* parent group */
1089cdf0e10cSrcweir     int session;              /* session ID */
1090cdf0e10cSrcweir     int tty;                  /* no of tty */
1091cdf0e10cSrcweir     pid_t tpgid;              /* group of process owning the tty */
1092cdf0e10cSrcweir     unsigned long flags;      /* flags dunno */
1093cdf0e10cSrcweir     unsigned long minflt;     /* minor page faults */
1094cdf0e10cSrcweir     unsigned long cminflt;    /* minor page faults with children */
1095cdf0e10cSrcweir     unsigned long majflt;     /* major page faults */
1096cdf0e10cSrcweir     unsigned long cmajflt;    /* major page faults with children */
1097cdf0e10cSrcweir     unsigned long utime;      /* no of jiffies in user mode */
1098cdf0e10cSrcweir     unsigned long stime;      /* no of jiffies in kernel mode */
1099cdf0e10cSrcweir     unsigned long cutime;     /* no of jiffies in user mode with children */
1100cdf0e10cSrcweir     unsigned long cstime;     /* no of jiffies in kernel mode with children */
1101cdf0e10cSrcweir     unsigned long priority;   /* nice value + 15 (kernel scheduling prio)*/
1102cdf0e10cSrcweir     long nice;                /* nice value */
1103cdf0e10cSrcweir     long timeout;             /* no of jiffies of next process timeout */
1104cdf0e10cSrcweir     long itrealvalue;         /* no jiffies before next SIGALRM */
1105cdf0e10cSrcweir     unsigned long starttime;  /* process started this no of jiffies after boot */
1106cdf0e10cSrcweir     unsigned long vsize;      /* virtual memory size (in bytes) */
1107cdf0e10cSrcweir     long rss;                 /* resident set size (in pages) */
1108cdf0e10cSrcweir     unsigned long rss_rlim;   /* rss limit (in bytes) */
1109cdf0e10cSrcweir     unsigned long startcode;  /* address above program text can run */
1110cdf0e10cSrcweir     unsigned long endcode;    /* address below program text can run */
1111cdf0e10cSrcweir     unsigned long startstack; /* address of start of stack */
1112cdf0e10cSrcweir     unsigned long kstkesp;    /* current value of 'esp' (stack pointer) */
1113cdf0e10cSrcweir     unsigned long kstkeip;    /* current value of 'eip' (instruction pointer) */
1114cdf0e10cSrcweir     /* mfe: Linux > 2.1.7x have more signals (88) */
1115cdf0e10cSrcweir /*#ifdef LINUX */
1116cdf0e10cSrcweir     char signal[24];          /* pending signals */
1117cdf0e10cSrcweir     char blocked[24];         /* blocked signals */
1118cdf0e10cSrcweir     char sigignore[24];       /* ignored signals */
1119cdf0e10cSrcweir     char sigcatch[24];        /* catched signals */
1120cdf0e10cSrcweir /*#else*/
1121cdf0e10cSrcweir /*  long long signal;*/
1122cdf0e10cSrcweir /*  long long blocked;*/
1123cdf0e10cSrcweir /*  long long sigignore;*/
1124cdf0e10cSrcweir /*  long long sigcatch;*/
1125cdf0e10cSrcweir /*#endif */
1126cdf0e10cSrcweir     unsigned long wchan;      /* 'channel' the process is waiting in */
1127cdf0e10cSrcweir     unsigned long nswap;      /* ? */
1128cdf0e10cSrcweir     unsigned long cnswap;     /* ? */
1129cdf0e10cSrcweir 
1130cdf0e10cSrcweir     /* from 'status' */
1131cdf0e10cSrcweir     int ruid;                 /* real uid */
1132cdf0e10cSrcweir     int euid;                 /* effective uid */
1133cdf0e10cSrcweir     int suid;                 /* saved uid */
1134cdf0e10cSrcweir     int fuid;                 /* file access uid */
1135cdf0e10cSrcweir     int rgid;                 /* real gid */
1136cdf0e10cSrcweir     int egid;                 /* effective gid */
1137cdf0e10cSrcweir     int sgid;                 /* saved gid */
1138cdf0e10cSrcweir     int fgid;                 /* file access gid */
1139cdf0e10cSrcweir     unsigned long vm_size;    /* like vsize but on kb */
1140cdf0e10cSrcweir     unsigned long vm_lock;    /* locked pages in kb */
1141cdf0e10cSrcweir     unsigned long vm_rss;     /* like rss but in kb */
1142cdf0e10cSrcweir     unsigned long vm_data;    /* data size */
1143cdf0e10cSrcweir     unsigned long vm_stack;   /* stack size */
1144cdf0e10cSrcweir     unsigned long vm_exe;     /* executable size */
1145cdf0e10cSrcweir     unsigned long vm_lib;     /* library size */
1146cdf0e10cSrcweir };
1147cdf0e10cSrcweir 
1148cdf0e10cSrcweir /**********************************************
1149cdf0e10cSrcweir  osl_getProcStat
1150cdf0e10cSrcweir  *********************************************/
1151cdf0e10cSrcweir 
osl_getProcStat(pid_t pid,struct osl_procStat * procstat)1152cdf0e10cSrcweir sal_Bool osl_getProcStat(pid_t pid, struct osl_procStat* procstat)
1153cdf0e10cSrcweir {
1154cdf0e10cSrcweir     int fd = 0;
1155cdf0e10cSrcweir     sal_Bool bRet = sal_False;
1156cdf0e10cSrcweir     char name[PATH_MAX + 1];
1157cdf0e10cSrcweir     snprintf(name, sizeof(name), "/proc/%u/stat", pid);
1158cdf0e10cSrcweir 
1159cdf0e10cSrcweir     if ((fd = open(name,O_RDONLY)) >=0 )
1160cdf0e10cSrcweir     {
1161509a48ffSpfg         char* tmp=NULL;
1162cdf0e10cSrcweir         char prstatbuf[512];
1163cdf0e10cSrcweir         memset(prstatbuf,0,512);
1164cdf0e10cSrcweir         bRet = read(fd,prstatbuf,511) == 511;
1165cdf0e10cSrcweir 
1166cdf0e10cSrcweir         close(fd);
1167cdf0e10cSrcweir         /*printf("%s\n\n",prstatbuf);*/
1168cdf0e10cSrcweir 
1169cdf0e10cSrcweir         if (!bRet)
1170cdf0e10cSrcweir             return sal_False;
1171cdf0e10cSrcweir 
1172cdf0e10cSrcweir         tmp = strrchr(prstatbuf, ')');
1173cdf0e10cSrcweir         *tmp = '\0';
1174cdf0e10cSrcweir         memset(procstat->command, 0, sizeof(procstat->command));
1175cdf0e10cSrcweir 
1176cdf0e10cSrcweir         sscanf(prstatbuf, "%d (%15c", &procstat->pid, procstat->command);
1177cdf0e10cSrcweir         sscanf(tmp + 2,
1178cdf0e10cSrcweir                "%c"
1179cdf0e10cSrcweir                "%i %i %i %i %i"
1180cdf0e10cSrcweir                "%lu %lu %lu %lu %lu"
1181cdf0e10cSrcweir                "%lu %lu %lu %lu"
1182cdf0e10cSrcweir                "%lu %li %li %li"
1183cdf0e10cSrcweir                "%lu %lu %li %lu"
1184cdf0e10cSrcweir                "%lu %lu %lu %lu %lu"
1185cdf0e10cSrcweir                "%s %s %s %s"
1186cdf0e10cSrcweir                "%lu %lu %lu",
1187cdf0e10cSrcweir                &procstat->state,
1188cdf0e10cSrcweir                &procstat->ppid,      &procstat->pgrp,    &procstat->session,    &procstat->tty,         &procstat->tpgid,
1189cdf0e10cSrcweir                &procstat->flags,     &procstat->minflt,  &procstat->cminflt,    &procstat->majflt,      &procstat->cmajflt,
1190cdf0e10cSrcweir                &procstat->utime,     &procstat->stime,   &procstat->cutime,     &procstat->cstime,
1191cdf0e10cSrcweir                &procstat->priority,  &procstat->nice,    &procstat->timeout,    &procstat->itrealvalue,
1192cdf0e10cSrcweir                &procstat->starttime, &procstat->vsize,   &procstat->rss,        &procstat->rss_rlim,
1193cdf0e10cSrcweir                &procstat->startcode, &procstat->endcode, &procstat->startstack, &procstat->kstkesp,     &procstat->kstkeip,
1194cdf0e10cSrcweir                procstat->signal,     procstat->blocked,  procstat->sigignore,   procstat->sigcatch,
1195cdf0e10cSrcweir                &procstat->wchan,     &procstat->nswap,   &procstat->cnswap
1196cdf0e10cSrcweir             );
1197cdf0e10cSrcweir     }
1198cdf0e10cSrcweir     return bRet;
1199cdf0e10cSrcweir }
1200cdf0e10cSrcweir 
1201cdf0e10cSrcweir /**********************************************
1202cdf0e10cSrcweir  osl_getProcStatus
1203cdf0e10cSrcweir  *********************************************/
1204cdf0e10cSrcweir 
osl_getProcStatus(pid_t pid,struct osl_procStat * procstat)1205cdf0e10cSrcweir sal_Bool osl_getProcStatus(pid_t pid, struct osl_procStat* procstat)
1206cdf0e10cSrcweir {
1207cdf0e10cSrcweir     int fd = 0;
1208cdf0e10cSrcweir     char name[PATH_MAX + 1];
1209cdf0e10cSrcweir     snprintf(name, sizeof(name), "/proc/%u/status", pid);
1210cdf0e10cSrcweir 
1211cdf0e10cSrcweir     sal_Bool bRet = sal_False;
1212cdf0e10cSrcweir 
1213cdf0e10cSrcweir     if ((fd = open(name,O_RDONLY)) >=0 )
1214cdf0e10cSrcweir     {
1215509a48ffSpfg         char* tmp=NULL;
1216cdf0e10cSrcweir         char prstatusbuf[512];
1217cdf0e10cSrcweir         memset(prstatusbuf,0,512);
1218cdf0e10cSrcweir         bRet = read(fd,prstatusbuf,511) == 511;
1219cdf0e10cSrcweir 
1220cdf0e10cSrcweir         close(fd);
1221cdf0e10cSrcweir 
1222cdf0e10cSrcweir         /*      printf("\n\n%s\n\n",prstatusbuf);*/
1223cdf0e10cSrcweir 
1224cdf0e10cSrcweir         if (!bRet)
1225cdf0e10cSrcweir             return sal_False;
1226cdf0e10cSrcweir 
1227cdf0e10cSrcweir         tmp = strstr(prstatusbuf,"Uid:");
1228cdf0e10cSrcweir         if(tmp)
1229cdf0e10cSrcweir         {
1230cdf0e10cSrcweir             sscanf(tmp,"Uid:\t%d\t%d\t%d\t%d",
1231cdf0e10cSrcweir                    &procstat->ruid, &procstat->euid, &procstat->suid, &procstat->fuid
1232cdf0e10cSrcweir                 );
1233cdf0e10cSrcweir         }
1234cdf0e10cSrcweir 
1235cdf0e10cSrcweir 
1236cdf0e10cSrcweir         tmp = strstr(prstatusbuf,"Gid:");
1237cdf0e10cSrcweir         if(tmp)
1238cdf0e10cSrcweir         {
1239cdf0e10cSrcweir             sscanf(tmp,"Gid:\t%d\t%d\t%d\t%d",
1240cdf0e10cSrcweir                    &procstat->rgid, &procstat->egid, &procstat->sgid, &procstat->fgid
1241cdf0e10cSrcweir                 );
1242cdf0e10cSrcweir         }
1243cdf0e10cSrcweir 
1244cdf0e10cSrcweir         tmp = strstr(prstatusbuf,"VmSize:");
1245cdf0e10cSrcweir         if(tmp)
1246cdf0e10cSrcweir         {
1247cdf0e10cSrcweir             sscanf(tmp,
1248cdf0e10cSrcweir                    "VmSize: %lu kB\n"
1249cdf0e10cSrcweir                    "VmLck: %lu kB\n"
1250cdf0e10cSrcweir                    "VmRSS: %lu kB\n"
1251cdf0e10cSrcweir                    "VmData: %lu kB\n"
1252cdf0e10cSrcweir                    "VmStk: %lu kB\n"
1253cdf0e10cSrcweir                    "VmExe: %lu kB\n"
1254cdf0e10cSrcweir                    "VmLib: %lu kB\n",
1255cdf0e10cSrcweir                    &procstat->vm_size, &procstat->vm_lock, &procstat->vm_rss, &procstat->vm_data,
1256cdf0e10cSrcweir                    &procstat->vm_stack, &procstat->vm_exe, &procstat->vm_lib
1257cdf0e10cSrcweir                 );
1258cdf0e10cSrcweir         }
1259cdf0e10cSrcweir 
1260cdf0e10cSrcweir         tmp = strstr(prstatusbuf,"SigPnd:");
1261cdf0e10cSrcweir         if(tmp)
1262cdf0e10cSrcweir         {
1263cdf0e10cSrcweir             sscanf(tmp, "SigPnd: %s SigBlk: %s SigIgn: %s %*s %s",
1264cdf0e10cSrcweir                    procstat->signal, procstat->blocked, procstat->sigignore, procstat->sigcatch
1265cdf0e10cSrcweir                 );
1266cdf0e10cSrcweir         }
1267cdf0e10cSrcweir     }
1268cdf0e10cSrcweir     return bRet;
1269cdf0e10cSrcweir }
1270cdf0e10cSrcweir 
1271cdf0e10cSrcweir #endif
1272cdf0e10cSrcweir 
1273cdf0e10cSrcweir /**********************************************
1274cdf0e10cSrcweir  osl_getProcessInfo
1275cdf0e10cSrcweir  *********************************************/
1276cdf0e10cSrcweir 
osl_getProcessInfo(oslProcess Process,oslProcessData Fields,oslProcessInfo * pInfo)1277cdf0e10cSrcweir oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields, oslProcessInfo* pInfo)
1278cdf0e10cSrcweir {
1279cdf0e10cSrcweir     pid_t   pid;
1280cdf0e10cSrcweir 
1281cdf0e10cSrcweir     if (Process == NULL)
1282cdf0e10cSrcweir         pid = getpid();
1283cdf0e10cSrcweir     else
1284cdf0e10cSrcweir         pid = ((oslProcessImpl*)Process)->m_pid;
1285cdf0e10cSrcweir 
1286cdf0e10cSrcweir     if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo)))
1287cdf0e10cSrcweir         return osl_Process_E_Unknown;
1288cdf0e10cSrcweir 
1289cdf0e10cSrcweir     pInfo->Fields = 0;
1290cdf0e10cSrcweir 
1291cdf0e10cSrcweir     if (Fields & osl_Process_IDENTIFIER)
1292cdf0e10cSrcweir     {
1293cdf0e10cSrcweir         pInfo->Ident  = pid;
1294cdf0e10cSrcweir         pInfo->Fields |= osl_Process_IDENTIFIER;
1295cdf0e10cSrcweir     }
1296cdf0e10cSrcweir 
1297cdf0e10cSrcweir     if (Fields & osl_Process_EXITCODE)
1298cdf0e10cSrcweir     {
1299cdf0e10cSrcweir         if ((Process != NULL) &&
1300cdf0e10cSrcweir             osl_checkCondition(((oslProcessImpl*)Process)->m_terminated))
1301cdf0e10cSrcweir         {
1302cdf0e10cSrcweir             pInfo->Code = ((oslProcessImpl*)Process)->m_status;
1303cdf0e10cSrcweir             pInfo->Fields |= osl_Process_EXITCODE;
1304cdf0e10cSrcweir         }
1305cdf0e10cSrcweir     }
1306cdf0e10cSrcweir 
1307cdf0e10cSrcweir     if (Fields & (osl_Process_HEAPUSAGE | osl_Process_CPUTIMES))
1308cdf0e10cSrcweir     {
1309cdf0e10cSrcweir 
1310cdf0e10cSrcweir #if defined(SOLARIS)
1311cdf0e10cSrcweir 
1312cdf0e10cSrcweir         int  fd;
1313cdf0e10cSrcweir         sal_Char name[PATH_MAX + 1];
1314cdf0e10cSrcweir 
1315cdf0e10cSrcweir         snprintf(name, sizeof(name), "/proc/%u", pid);
1316cdf0e10cSrcweir 
1317cdf0e10cSrcweir         if ((fd = open(name, O_RDONLY)) >= 0)
1318cdf0e10cSrcweir         {
1319cdf0e10cSrcweir             prstatus_t prstatus;
1320cdf0e10cSrcweir 
1321cdf0e10cSrcweir             if (ioctl(fd, PIOCSTATUS, &prstatus) >= 0)
1322cdf0e10cSrcweir             {
1323cdf0e10cSrcweir                 if (Fields & osl_Process_CPUTIMES)
1324cdf0e10cSrcweir                 {
1325cdf0e10cSrcweir                     pInfo->UserTime.Seconds   = prstatus.pr_utime.tv_sec;
1326cdf0e10cSrcweir                     pInfo->UserTime.Nanosec   = prstatus.pr_utime.tv_nsec;
1327cdf0e10cSrcweir                     pInfo->SystemTime.Seconds = prstatus.pr_stime.tv_sec;
1328cdf0e10cSrcweir                     pInfo->SystemTime.Nanosec = prstatus.pr_stime.tv_nsec;
1329cdf0e10cSrcweir 
1330cdf0e10cSrcweir                     pInfo->Fields |= osl_Process_CPUTIMES;
1331cdf0e10cSrcweir                 }
1332cdf0e10cSrcweir 
1333cdf0e10cSrcweir                 if (Fields & osl_Process_HEAPUSAGE)
1334cdf0e10cSrcweir                 {
1335cdf0e10cSrcweir                     pInfo->HeapUsage = prstatus.pr_brksize;
1336cdf0e10cSrcweir 
1337cdf0e10cSrcweir                     pInfo->Fields |= osl_Process_HEAPUSAGE;
1338cdf0e10cSrcweir                 }
1339cdf0e10cSrcweir 
1340cdf0e10cSrcweir                 close(fd);
1341cdf0e10cSrcweir 
1342cdf0e10cSrcweir                 return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
1343cdf0e10cSrcweir             }
1344cdf0e10cSrcweir             else
1345cdf0e10cSrcweir                 close(fd);
1346cdf0e10cSrcweir         }
1347cdf0e10cSrcweir 
1348cdf0e10cSrcweir #elif defined(HPUX)
1349cdf0e10cSrcweir 
1350cdf0e10cSrcweir         struct pst_status prstatus;
1351cdf0e10cSrcweir 
1352cdf0e10cSrcweir         if (pstat_getproc(&prstatus, sizeof(prstatus), (size_t)0, pid) == 1)
1353cdf0e10cSrcweir         {
1354cdf0e10cSrcweir             if (Fields & osl_Process_CPUTIMES)
1355cdf0e10cSrcweir             {
1356cdf0e10cSrcweir                 pInfo->UserTime.Seconds   = prstatus.pst_utime;
1357cdf0e10cSrcweir                 pInfo->UserTime.Nanosec   = 500000L;
1358cdf0e10cSrcweir                 pInfo->SystemTime.Seconds = prstatus.pst_stime;
1359cdf0e10cSrcweir                 pInfo->SystemTime.Nanosec = 500000L;
1360cdf0e10cSrcweir 
1361cdf0e10cSrcweir                 pInfo->Fields |= osl_Process_CPUTIMES;
1362cdf0e10cSrcweir             }
1363cdf0e10cSrcweir 
1364cdf0e10cSrcweir             if (Fields & osl_Process_HEAPUSAGE)
1365cdf0e10cSrcweir             {
1366cdf0e10cSrcweir                 pInfo->HeapUsage = prstatus.pst_vdsize*PAGESIZE;
1367cdf0e10cSrcweir 
1368cdf0e10cSrcweir                 pInfo->Fields |= osl_Process_HEAPUSAGE;
1369cdf0e10cSrcweir             }
1370cdf0e10cSrcweir 
1371cdf0e10cSrcweir             return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
1372cdf0e10cSrcweir         }
1373cdf0e10cSrcweir 
1374cdf0e10cSrcweir #elif defined(LINUX)
1375cdf0e10cSrcweir 
1376cdf0e10cSrcweir         if ( (Fields & osl_Process_CPUTIMES) || (Fields & osl_Process_HEAPUSAGE) )
1377cdf0e10cSrcweir         {
1378cdf0e10cSrcweir             struct osl_procStat procstat;
1379cdf0e10cSrcweir             memset(&procstat,0,sizeof(procstat));
1380cdf0e10cSrcweir 
1381cdf0e10cSrcweir             if ( (Fields & osl_Process_CPUTIMES) && osl_getProcStat(pid, &procstat) )
1382cdf0e10cSrcweir             {
1383cdf0e10cSrcweir                 /*
1384cdf0e10cSrcweir                  *  mfe:
1385cdf0e10cSrcweir                  *  We calculate only time of the process proper.
1386cdf0e10cSrcweir                  *  Threads are processes, we do not consider their time here!
1387cdf0e10cSrcweir                  *  (For this, cutime and cstime should be used, it seems not
1388cdf0e10cSrcweir                  *   to work in 2.0.36)
1389cdf0e10cSrcweir                  */
1390cdf0e10cSrcweir 
1391cdf0e10cSrcweir                 long clktck;
1392cdf0e10cSrcweir                 unsigned long hz;
1393cdf0e10cSrcweir                 unsigned long userseconds;
1394cdf0e10cSrcweir                 unsigned long systemseconds;
1395cdf0e10cSrcweir 
1396cdf0e10cSrcweir                 clktck = sysconf(_SC_CLK_TCK);
1397cdf0e10cSrcweir                 if (clktck < 0) {
1398cdf0e10cSrcweir                     return osl_Process_E_Unknown;
1399cdf0e10cSrcweir                 }
1400cdf0e10cSrcweir                 hz = (unsigned long) clktck;
1401cdf0e10cSrcweir 
1402cdf0e10cSrcweir                 userseconds = procstat.utime/hz;
1403cdf0e10cSrcweir                 systemseconds = procstat.stime/hz;
1404cdf0e10cSrcweir 
1405cdf0e10cSrcweir                 pInfo->UserTime.Seconds   = userseconds;
1406cdf0e10cSrcweir                 pInfo->UserTime.Nanosec   = procstat.utime - (userseconds * hz);
1407cdf0e10cSrcweir                 pInfo->SystemTime.Seconds = systemseconds;
1408cdf0e10cSrcweir                 pInfo->SystemTime.Nanosec = procstat.stime - (systemseconds * hz);
1409cdf0e10cSrcweir 
1410cdf0e10cSrcweir                 pInfo->Fields |= osl_Process_CPUTIMES;
1411cdf0e10cSrcweir             }
1412cdf0e10cSrcweir 
1413cdf0e10cSrcweir             if ( (Fields & osl_Process_HEAPUSAGE) && osl_getProcStatus(pid, &procstat) )
1414cdf0e10cSrcweir             {
1415cdf0e10cSrcweir                 /*
1416cdf0e10cSrcweir                  *  mfe:
1417cdf0e10cSrcweir                  *  vm_data (found in status) shows the size of the data segment
1418cdf0e10cSrcweir                  *  it a rough approximation of the core heap size
1419cdf0e10cSrcweir                  */
1420cdf0e10cSrcweir                 pInfo->HeapUsage = procstat.vm_data*1024;
1421cdf0e10cSrcweir 
1422cdf0e10cSrcweir                 pInfo->Fields |= osl_Process_HEAPUSAGE;
1423cdf0e10cSrcweir             }
1424cdf0e10cSrcweir         }
1425cdf0e10cSrcweir 
1426cdf0e10cSrcweir         return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
1427cdf0e10cSrcweir #endif
1428cdf0e10cSrcweir 
1429cdf0e10cSrcweir     }
1430cdf0e10cSrcweir 
1431cdf0e10cSrcweir     return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
1432cdf0e10cSrcweir }
1433cdf0e10cSrcweir 
1434cdf0e10cSrcweir 
1435cdf0e10cSrcweir /***********************************************
1436cdf0e10cSrcweir  helper function for osl_joinProcessWithTimeout
1437cdf0e10cSrcweir  **********************************************/
1438cdf0e10cSrcweir 
is_timeout(const struct timeval * tend)1439cdf0e10cSrcweir static int is_timeout(const struct timeval* tend)
1440cdf0e10cSrcweir {
1441cdf0e10cSrcweir     struct timeval tcurrent;
1442cdf0e10cSrcweir     gettimeofday(&tcurrent, NULL);
1443cdf0e10cSrcweir     return (tcurrent.tv_sec >= tend->tv_sec);
1444cdf0e10cSrcweir }
1445cdf0e10cSrcweir 
1446cdf0e10cSrcweir /**********************************************
144786e1cf34SPedro Giffuni  kill(pid, 0) is useful for checking if a
1448cdf0e10cSrcweir  process is still alive, but remember that
1449cdf0e10cSrcweir  kill even returns 0 if the process is already
1450cdf0e10cSrcweir  a zombie.
1451cdf0e10cSrcweir  *********************************************/
1452cdf0e10cSrcweir 
is_process_dead(pid_t pid)1453cdf0e10cSrcweir static int is_process_dead(pid_t pid)
1454cdf0e10cSrcweir {
1455cdf0e10cSrcweir     return ((-1 == kill(pid, 0)) && (ESRCH == errno));
1456cdf0e10cSrcweir }
1457cdf0e10cSrcweir 
1458cdf0e10cSrcweir /**********************************************
1459cdf0e10cSrcweir  osl_joinProcessWithTimeout
1460cdf0e10cSrcweir  *********************************************/
1461cdf0e10cSrcweir 
osl_joinProcessWithTimeout(oslProcess Process,const TimeValue * pTimeout)1462cdf0e10cSrcweir oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout)
1463cdf0e10cSrcweir {
1464cdf0e10cSrcweir     oslProcessImpl* pChild    = ChildList;
1465cdf0e10cSrcweir     oslProcessError osl_error = osl_Process_E_None;
1466cdf0e10cSrcweir 
1467cdf0e10cSrcweir     OSL_PRECOND(Process, "osl_joinProcess: Invalid parameter");
1468cdf0e10cSrcweir     OSL_ASSERT(ChildListMutex);
1469cdf0e10cSrcweir 
1470cdf0e10cSrcweir     if (NULL == Process || 0 == ChildListMutex)
1471cdf0e10cSrcweir         return osl_Process_E_Unknown;
1472cdf0e10cSrcweir 
1473cdf0e10cSrcweir     osl_acquireMutex(ChildListMutex);
1474cdf0e10cSrcweir 
1475cdf0e10cSrcweir     /* check if process is a child of ours */
1476cdf0e10cSrcweir     while (pChild != NULL)
1477cdf0e10cSrcweir     {
1478cdf0e10cSrcweir         if (pChild == (oslProcessImpl*)Process)
1479cdf0e10cSrcweir             break;
1480cdf0e10cSrcweir 
1481cdf0e10cSrcweir         pChild = pChild->m_pnext;
1482cdf0e10cSrcweir     }
1483cdf0e10cSrcweir 
1484cdf0e10cSrcweir     osl_releaseMutex(ChildListMutex);
1485cdf0e10cSrcweir 
1486cdf0e10cSrcweir     if (pChild != NULL)
1487cdf0e10cSrcweir     {
1488cdf0e10cSrcweir         oslConditionResult cond_res = osl_waitCondition(pChild->m_terminated, pTimeout);
1489cdf0e10cSrcweir 
1490cdf0e10cSrcweir         if (osl_cond_result_timeout == cond_res)
1491cdf0e10cSrcweir             osl_error = osl_Process_E_TimedOut;
1492cdf0e10cSrcweir         else if (osl_cond_result_ok != cond_res)
1493cdf0e10cSrcweir             osl_error = osl_Process_E_Unknown;
1494cdf0e10cSrcweir     }
1495cdf0e10cSrcweir     else /* alien process; StatusThread will not be able
1496cdf0e10cSrcweir             to set the condition terminated */
1497cdf0e10cSrcweir     {
1498cdf0e10cSrcweir         pid_t pid = ((oslProcessImpl*)Process)->m_pid;
1499cdf0e10cSrcweir 
1500cdf0e10cSrcweir         if (pTimeout)
1501cdf0e10cSrcweir         {
1502cdf0e10cSrcweir             int timeout = 0;
1503cdf0e10cSrcweir             struct timeval tend;
1504cdf0e10cSrcweir 
1505cdf0e10cSrcweir             gettimeofday(&tend, NULL);
1506cdf0e10cSrcweir 
1507cdf0e10cSrcweir             tend.tv_sec += pTimeout->Seconds;
1508cdf0e10cSrcweir 
1509cdf0e10cSrcweir             while (!is_process_dead(pid) && ((timeout = is_timeout(&tend)) == 0))
1510cdf0e10cSrcweir                 sleep(1);
1511cdf0e10cSrcweir 
1512cdf0e10cSrcweir             if (timeout)
1513cdf0e10cSrcweir                 osl_error = osl_Process_E_TimedOut;
1514cdf0e10cSrcweir         }
1515cdf0e10cSrcweir         else /* infinite */
1516cdf0e10cSrcweir         {
1517cdf0e10cSrcweir             while (!is_process_dead(pid))
1518cdf0e10cSrcweir                 sleep(1);
1519cdf0e10cSrcweir         }
1520cdf0e10cSrcweir     }
1521cdf0e10cSrcweir     return osl_error;
1522cdf0e10cSrcweir }
1523cdf0e10cSrcweir 
1524cdf0e10cSrcweir /**********************************************
1525cdf0e10cSrcweir  osl_joinProcess
1526cdf0e10cSrcweir  *********************************************/
1527cdf0e10cSrcweir 
osl_joinProcess(oslProcess Process)1528cdf0e10cSrcweir oslProcessError SAL_CALL osl_joinProcess(oslProcess Process)
1529cdf0e10cSrcweir {
1530cdf0e10cSrcweir     return osl_joinProcessWithTimeout(Process, NULL);
1531cdf0e10cSrcweir }
1532