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

Generated by: LCOV version 1.10