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

Generated by: LCOV version 1.10