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