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