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