LCOV - code coverage report
Current view: top level - sal/osl/unx - process.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 218 402 54.2 %
Date: 2012-08-25 Functions: 9 17 52.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 181 481 37.6 %

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

Generated by: LCOV version 1.10