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

Generated by: LCOV version 1.11