LCOV - code coverage report
Current view: top level - sal/osl/unx - process.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 212 399 53.1 %
Date: 2014-04-11 Functions: 9 17 52.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10