LCOV - code coverage report
Current view: top level - desktop/unx/source - start.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 182 390 46.7 %
Date: 2012-08-25 Functions: 13 22 59.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 36 135 26.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * Version: MPL 1.1 / GPLv3+ / LGPLv3+
       4                 :            :  *
       5                 :            :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :            :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :            :  * the License. You may obtain a copy of the License at
       8                 :            :  * http://www.mozilla.org/MPL/
       9                 :            :  *
      10                 :            :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :            :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :            :  * for the specific language governing rights and limitations under the
      13                 :            :  * License.
      14                 :            :  *
      15                 :            :  * The Initial Developer of the Original Code is
      16                 :            :  *               Novell, Inc.
      17                 :            :  * Portions created by the Initial Developer are Copyright (C) 2010 the
      18                 :            :  * Initial Developer. All Rights Reserved.
      19                 :            :  *
      20                 :            :  * Contributor(s): Jan Holesovsky <kendy@novell.com>
      21                 :            :  *
      22                 :            :  * Alternatively, the contents of this file may be used under the terms of
      23                 :            :  * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
      24                 :            :  * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
      25                 :            :  * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
      26                 :            :  * instead of those above.
      27                 :            :  */
      28                 :            : #include <signal.h>
      29                 :            : #include <unistd.h>
      30                 :            : #include <limits.h>
      31                 :            : #include <stdlib.h>
      32                 :            : #include <sys/types.h>
      33                 :            : #include <sys/stat.h>
      34                 :            : #include <sys/socket.h>
      35                 :            : #include <arpa/inet.h>
      36                 :            : #include <sys/un.h>
      37                 :            : #include <sys/poll.h>
      38                 :            : #include <fcntl.h>
      39                 :            : #include <stdio.h>
      40                 :            : #include <libgen.h>
      41                 :            : #include <string.h>
      42                 :            : #include <errno.h>
      43                 :            : 
      44                 :            : #include <osl/process.h>
      45                 :            : #include <osl/thread.h>
      46                 :            : #include <rtl/bootstrap.h>
      47                 :            : #include <rtl/digest.h>
      48                 :            : #include <rtl/ustrbuf.h>
      49                 :            : #include <sal/main.h>
      50                 :            : 
      51                 :            : #include "args.h"
      52                 :            : #include "splashx.h"
      53                 :            : 
      54                 :            : #define PIPEDEFAULTPATH      "/tmp"
      55                 :            : #define PIPEALTERNATEPATH    "/var/tmp"
      56                 :            : 
      57                 :            : /* Easier conversions: rtl_uString to rtl_String */
      58                 :            : static rtl_String *
      59                 :         99 : ustr_to_str( rtl_uString *pStr )
      60                 :            : {
      61                 :         99 :     rtl_String *pOut = NULL;
      62                 :            : 
      63                 :         99 :     rtl_uString2String( &pOut, rtl_uString_getStr( pStr ),
      64                 :         99 :             rtl_uString_getLength( pStr ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
      65                 :            : 
      66                 :         99 :     return pOut;
      67                 :            : }
      68                 :            : 
      69                 :            : /* Easier conversions: char * to rtl_uString */
      70                 :            : static rtl_uString *
      71                 :         99 : charp_to_ustr( const char *pStr )
      72                 :            : {
      73                 :         99 :     rtl_uString *pOut = NULL;
      74                 :            : 
      75                 :         99 :     rtl_string2UString( &pOut, pStr, strlen( pStr ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
      76                 :            : 
      77                 :         99 :     return pOut;
      78                 :            : }
      79                 :            : 
      80                 :            : /* Easier debugging of rtl_uString values. */
      81                 :            : #if OSL_DEBUG_LEVEL > 1
      82                 :            : static void
      83                 :            : ustr_debug( const char *pMessage, rtl_uString *pStr )
      84                 :            : {
      85                 :            :     rtl_String *pOut = ustr_to_str( pStr );
      86                 :            : 
      87                 :            :     fprintf( stderr, "%s: %s\n", pMessage, rtl_string_getStr( pOut ) );
      88                 :            : 
      89                 :            :     rtl_string_release( pOut );
      90                 :            :     return;
      91                 :            : }
      92                 :            : #else
      93                 :            : #define ustr_debug( a, b ) {}
      94                 :            : #endif
      95                 :            : 
      96                 :            : typedef struct {
      97                 :            :     int        status_fd;
      98                 :            :     oslProcess child;
      99                 :            : } ChildInfo;
     100                 :            : 
     101                 :            : static int
     102                 :          0 : child_info_get_status_fd (ChildInfo *info)
     103                 :            : {
     104                 :          0 :     return info->status_fd;
     105                 :            : }
     106                 :            : 
     107                 :            : static void
     108                 :        161 : child_info_destroy (ChildInfo *info)
     109                 :            : {
     110                 :        161 :     close (info->status_fd);
     111                 :        161 :     osl_freeProcessHandle (info->child);
     112                 :        161 :     free (info);
     113                 :        161 : }
     114                 :            : 
     115                 :            : static ChildInfo *
     116                 :        161 : child_spawn ( Args *args, sal_Bool bAllArgs, sal_Bool bWithStatus )
     117                 :            : {
     118                 :        161 :     rtl_uString *pApp = NULL, *pTmp = NULL;
     119                 :            :     rtl_uString **ppArgs;
     120                 :            :     sal_uInt32 nArgs, i;
     121                 :            :     char buffer[64];
     122                 :            :     ChildInfo *info;
     123                 :            :     int status_pipe[2];
     124                 :            :     oslProcessError nError;
     125                 :            : 
     126                 :        161 :     info = calloc (1, sizeof (ChildInfo));
     127                 :            : 
     128                 :            :     /* create pipe */
     129         [ -  + ]:        161 :     if ( pipe( status_pipe ) < 0 )
     130                 :            :     {
     131                 :          0 :         fprintf( stderr, "ERROR: no file handles\n");
     132                 :          0 :         exit( 1 );
     133                 :            :     }
     134                 :        161 :     info->status_fd = status_pipe[0];
     135                 :            : 
     136                 :            :     /* application name */
     137                 :        161 :     rtl_uString_newFromAscii( &pApp, "file://" );
     138                 :        161 :     rtl_uString_newConcat( &pApp, pApp, args->pAppPath );
     139                 :        161 :     rtl_uString_newFromAscii( &pTmp, "soffice.bin" );
     140                 :        161 :     rtl_uString_newConcat( &pApp, pApp, pTmp );
     141                 :        161 :     rtl_uString_release( pTmp );
     142                 :        161 :     pTmp = NULL;
     143                 :            : 
     144                 :            :     /* copy args */
     145         [ +  - ]:        161 :     nArgs = bAllArgs ? args->nArgsTotal : args->nArgsEnv;
     146                 :        161 :     ppArgs = (rtl_uString **)calloc( nArgs + 1, sizeof( rtl_uString* ) );
     147         [ +  + ]:       1453 :     for ( i = 0; i < nArgs; ++i )
     148                 :       1292 :         ppArgs[i] = args->ppArgs[i];
     149                 :            : 
     150         [ -  + ]:        161 :     if( bWithStatus )
     151                 :            :     {
     152                 :            :         /* add the pipe arg */
     153                 :          0 :         snprintf (buffer, 63, "--splash-pipe=%d", status_pipe[1]);
     154                 :          0 :         rtl_uString_newFromAscii( &pTmp, buffer );
     155                 :          0 :         ppArgs[nArgs] = pTmp;
     156                 :          0 :         ++nArgs;
     157                 :            :     }
     158                 :            : 
     159                 :            :     /* start the main process */
     160                 :        161 :     nError = osl_executeProcess( pApp, ppArgs, nArgs,
     161                 :            :                                  osl_Process_NORMAL,
     162                 :            :                                  NULL,
     163                 :            :                                  NULL,
     164                 :            :                                  NULL, 0,
     165                 :            :                                  &info->child );
     166                 :            : 
     167         [ -  + ]:        161 :     if (pTmp)
     168                 :          0 :         rtl_uString_release( pTmp );
     169                 :        161 :     free (ppArgs);
     170                 :            : 
     171         [ -  + ]:        161 :     if ( nError != osl_Process_E_None )
     172                 :            :     {
     173                 :          0 :         fprintf( stderr, "ERROR %d forking process", nError );
     174                 :            :         ustr_debug( "", pApp );
     175                 :          0 :         rtl_uString_release( pApp );
     176                 :          0 :         _exit (1);
     177                 :            :     }
     178                 :            : 
     179                 :        161 :     rtl_uString_release( pApp );
     180                 :        161 :     close( status_pipe[1] );
     181                 :            : 
     182                 :        161 :     return info;
     183                 :            : }
     184                 :            : 
     185                 :            : static sal_Bool
     186                 :        161 : child_exited_wait (ChildInfo *info, sal_Bool bShortWait)
     187                 :            : {
     188                 :        161 :     TimeValue t = { 0, 250 /* ms */ * 1000 * 1000 };
     189         [ +  - ]:        161 :     if (!bShortWait)
     190                 :        161 :         t.Seconds = 1024;
     191                 :        161 :     return osl_joinProcessWithTimeout (info->child, &t) != osl_Process_E_TimedOut;
     192                 :            : }
     193                 :            : 
     194                 :            : static int
     195                 :        161 : child_get_exit_code (ChildInfo *info)
     196                 :            : {
     197                 :            :     oslProcessInfo inf;
     198                 :            : 
     199                 :        161 :     inf.Code = -1;
     200                 :        161 :     inf.Size = sizeof (inf);
     201         [ -  + ]:        161 :     if (osl_getProcessInfo (info->child, osl_Process_EXITCODE, &inf) != osl_Process_E_None)
     202                 :            :     {
     203                 :          0 :         fprintf (stderr, "Warning: failed to fetch libreoffice exit status\n");
     204                 :          0 :         return -1;
     205                 :            :     }
     206                 :        161 :     return inf.Code;
     207                 :            : }
     208                 :            : 
     209                 :            : typedef enum { ProgressContinue, ProgressRestart, ProgressExit } ProgressStatus;
     210                 :            : 
     211                 :            : /* Path of the application, with trailing slash. */
     212                 :            : static rtl_uString *
     213                 :         99 : get_app_path( const char *pAppExec )
     214                 :            : {
     215                 :            :     char pRealPath[PATH_MAX];
     216                 :            :     rtl_uString *pResult;
     217                 :            :     sal_Int32 len;
     218                 :            :     char* dummy;
     219                 :            : 
     220                 :         99 :     char *pOrigPath = strdup( pAppExec );
     221                 :         99 :     char *pPath = dirname( pOrigPath );
     222                 :            : 
     223                 :         99 :     dummy = realpath( pPath, pRealPath );
     224                 :            :     (void)dummy;
     225                 :         99 :     pResult = charp_to_ustr( pRealPath );
     226                 :         99 :     free( pOrigPath );
     227                 :            : 
     228                 :         99 :     len = rtl_uString_getLength(pResult);
     229 [ +  - ][ +  - ]:         99 :     if (len > 0 && rtl_uString_getStr(pResult)[len - 1] != '/')
     230                 :            :     {
     231                 :         99 :         rtl_uString *pSlash = NULL;
     232                 :         99 :         rtl_uString_newFromAscii(&pSlash, "/");
     233                 :         99 :         rtl_uString_newConcat(&pResult, pResult, pSlash);
     234                 :         99 :         rtl_uString_release(pSlash);
     235                 :            :     }
     236                 :            : 
     237                 :         99 :     return pResult;
     238                 :            : }
     239                 :            : 
     240                 :            : /* Compute the OOo md5 hash from 'pText' */
     241                 :            : static rtl_uString *
     242                 :         99 : get_md5hash( rtl_uString *pText )
     243                 :            : {
     244                 :         99 :     rtl_uString *pResult = NULL;
     245                 :         99 :     sal_Int32 nCapacity = 100;
     246                 :         99 :     unsigned char *pData = NULL;
     247                 :         99 :     sal_uInt32 nSize = 0;
     248                 :            :     rtlDigest digest;
     249                 :         99 :     sal_uInt32 md5_key_len = 0;
     250                 :         99 :     sal_uInt8* md5_buf = NULL;
     251                 :         99 :     sal_uInt32 i = 0;
     252                 :            : #if OSL_DEBUG_LEVEL > 1
     253                 :            :     rtl_String *pOut;
     254                 :            : #endif
     255                 :            : 
     256         [ -  + ]:         99 :     if ( !pText )
     257                 :          0 :         return NULL;
     258                 :            : 
     259                 :            : #if OSL_DEBUG_LEVEL > 1
     260                 :            :     pOut = ustr_to_str( pText );
     261                 :            :     fprintf (stderr, "Generate pipe md5 for '%s'\n", pOut->buffer);
     262                 :            :     rtl_string_release( pOut );
     263                 :            : #endif
     264                 :            : 
     265                 :         99 :     pData = (unsigned char *)rtl_uString_getStr( pText );
     266                 :         99 :     nSize = rtl_uString_getLength( pText ) * sizeof( sal_Unicode );
     267         [ -  + ]:         99 :     if ( !pData )
     268                 :          0 :         return NULL;
     269                 :            : 
     270                 :         99 :     digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
     271         [ -  + ]:         99 :     if ( digest == 0 )
     272                 :          0 :         return NULL;
     273                 :            : 
     274                 :         99 :     md5_key_len = rtl_digest_queryLength( digest );
     275                 :         99 :     md5_buf = (sal_uInt8 *)calloc( md5_key_len, sizeof( sal_uInt8 ) );
     276                 :            : 
     277                 :         99 :     rtl_digest_init( digest, pData , nSize );
     278                 :         99 :     rtl_digest_update( digest, pData, nSize );
     279                 :         99 :     rtl_digest_get( digest, md5_buf, md5_key_len );
     280                 :         99 :     rtl_digest_destroy( digest );
     281                 :            : 
     282                 :            :     /* create hex-value string from the MD5 value to keep
     283                 :            :        the string size minimal */
     284                 :         99 :     rtl_uString_new_WithLength( &pResult, nCapacity );
     285         [ +  + ]:       1683 :     for ( ; i < md5_key_len; ++i )
     286                 :            :     {
     287                 :            :         char val[3];
     288                 :       1584 :         snprintf( val, 3, "%x", md5_buf[i] ); /* sic! we ignore some of the 0's */
     289                 :            : 
     290                 :       1584 :         rtl_uStringbuffer_insert_ascii( &pResult, &nCapacity, rtl_uString_getLength( pResult ),
     291                 :       1584 :                 val, strlen( val ) );
     292                 :            :     }
     293                 :            : 
     294                 :            :     /* cleanup */
     295                 :         99 :     free( md5_buf );
     296                 :            : 
     297                 :         99 :     return pResult;
     298                 :            : }
     299                 :            : 
     300                 :            : /* Construct the pipe name */
     301                 :            : static rtl_uString *
     302                 :         99 : get_pipe_path( rtl_uString *pAppPath )
     303                 :            : {
     304                 :         99 :     rtl_uString *pPath = NULL, *pTmp = NULL, *pUserInstallation = NULL;
     305                 :         99 :     rtl_uString *pResult = NULL, *pBasePath = NULL, *pAbsUserInstallation = NULL;
     306                 :            :     rtlBootstrapHandle handle;
     307                 :         99 :     rtl_uString *pMd5hash = NULL;
     308                 :            :     sal_Unicode pUnicode[RTL_USTR_MAX_VALUEOFINT32];
     309                 :            : 
     310                 :            :     /* setup bootstrap filename */
     311                 :         99 :     rtl_uString_newFromAscii( &pPath, "file://" );
     312                 :         99 :     rtl_uString_newConcat( &pPath, pPath, pAppPath );
     313                 :         99 :     rtl_uString_newConcat( &pPath, pPath, pTmp );
     314                 :         99 :     rtl_uString_newFromAscii( &pTmp, SAL_CONFIGFILE( "bootstrap" ) );
     315                 :         99 :     rtl_uString_newConcat( &pPath, pPath, pTmp );
     316                 :            : 
     317                 :            :     ustr_debug( "bootstap", pPath );
     318                 :            : 
     319                 :            :     /* read userinstallation value */
     320                 :         99 :     handle = rtl_bootstrap_args_open( pPath );
     321                 :            : 
     322                 :         99 :     rtl_uString_newFromAscii( &pTmp, "UserInstallation" );
     323                 :         99 :     rtl_bootstrap_get_from_handle( handle, pTmp, &pUserInstallation, NULL );
     324                 :            : 
     325                 :         99 :     rtl_bootstrap_args_close( handle );
     326                 :            : 
     327                 :            :     /* turn it into an absolute path - unwinding symlinks etc. */
     328   [ +  -  -  + ]:        198 :     if ( osl_getProcessWorkingDir (&pBasePath) ||
     329                 :         99 :          osl_getAbsoluteFileURL( pBasePath, pUserInstallation, &pAbsUserInstallation ) )
     330                 :          0 :         rtl_uString_newFromString (&pAbsUserInstallation, pUserInstallation);
     331                 :            : 
     332                 :            :     /* create the pipe name */
     333                 :            :     ustr_debug( "user installation", pAbsUserInstallation );
     334                 :         99 :     pMd5hash = get_md5hash( pAbsUserInstallation );
     335         [ -  + ]:         99 :     if ( !pMd5hash )
     336                 :          0 :         rtl_uString_new( &pMd5hash );
     337                 :            : 
     338         [ +  - ]:         99 :     if ( access( PIPEDEFAULTPATH, R_OK|W_OK ) == 0 )
     339                 :         99 :         rtl_uString_newFromAscii( &pResult, PIPEDEFAULTPATH );
     340                 :            :     else
     341                 :          0 :         rtl_uString_newFromAscii( &pResult, PIPEALTERNATEPATH );
     342                 :            : 
     343                 :         99 :     rtl_uString_newFromAscii( &pTmp, "/OSL_PIPE_" );
     344                 :         99 :     rtl_uString_newConcat( &pResult, pResult, pTmp );
     345                 :            : 
     346                 :         99 :     rtl_ustr_valueOfInt32( pUnicode, (int)getuid(), 10 );
     347                 :         99 :     rtl_uString_newFromStr( &pTmp, pUnicode );
     348                 :         99 :     rtl_uString_newConcat( &pResult, pResult, pTmp );
     349                 :            : 
     350                 :         99 :     rtl_uString_newFromAscii( &pTmp, "_SingleOfficeIPC_" );
     351                 :         99 :     rtl_uString_newConcat( &pResult, pResult, pTmp );
     352                 :            : 
     353                 :         99 :     rtl_uString_newConcat( &pResult, pResult, pMd5hash );
     354                 :            : 
     355                 :            :     ustr_debug( "result", pResult );
     356                 :            : 
     357                 :            :     /* cleanup */
     358                 :         99 :     rtl_uString_release( pMd5hash );
     359                 :         99 :     rtl_uString_release( pPath );
     360                 :         99 :     rtl_uString_release( pTmp );
     361         [ +  - ]:         99 :     if ( pBasePath )
     362                 :            :     {
     363                 :         99 :         rtl_uString_release( pBasePath );
     364                 :            :     }
     365                 :         99 :     rtl_uString_release( pUserInstallation );
     366                 :         99 :     rtl_uString_release( pAbsUserInstallation );
     367                 :            : 
     368                 :         99 :     return pResult;
     369                 :            : }
     370                 :            : 
     371                 :            : /* Get fd of the pipe of the already running OOo. */
     372                 :            : static int
     373                 :         99 : connect_pipe( rtl_uString *pPipePath )
     374                 :            : {
     375                 :            :     int fd;
     376                 :            :     size_t len;
     377                 :            :     struct sockaddr_un addr;
     378                 :            : 
     379                 :         99 :     rtl_String *pPipeStr = ustr_to_str( pPipePath );
     380                 :            : 
     381                 :         99 :     memset( &addr, 0, sizeof( addr ) );
     382                 :            : 
     383         [ -  + ]:         99 :     if ( ( fd = socket( AF_UNIX, SOCK_STREAM, 0 ) ) < 0 )
     384                 :          0 :         return fd;
     385                 :            : 
     386                 :         99 :     fcntl( fd, F_SETFD, FD_CLOEXEC );
     387                 :            : 
     388                 :         99 :     addr.sun_family = AF_UNIX;
     389                 :         99 :     strncpy( addr.sun_path, rtl_string_getStr( pPipeStr ), sizeof( addr.sun_path ) - 1 );
     390                 :         99 :     rtl_string_release( pPipeStr );
     391                 :            : 
     392                 :            : /* cut / paste from osl's pipe.c */
     393                 :            : #if defined(FREEBSD)
     394                 :            :     len = SUN_LEN( &addr );
     395                 :            : #else
     396                 :         99 :     len = sizeof( addr );
     397                 :            : #endif
     398                 :            : 
     399         [ +  - ]:         99 :     if ( connect( fd, (struct sockaddr *)&addr, len ) < 0 )
     400                 :         99 :         return -1;
     401                 :            : 
     402                 :         99 :     return fd;
     403                 :            : }
     404                 :            : 
     405                 :            : /* Escape: "," -> "\\,", "\0" -> "\\0", "\\" -> "\\\\" */
     406                 :            : static rtl_uString *
     407                 :          0 : escape_path( rtl_uString *pToEscape )
     408                 :            : {
     409                 :          0 :     rtl_uString *pBuffer = NULL;
     410                 :          0 :     sal_Int32 nCapacity = 1000;
     411                 :          0 :     sal_Int32 i = 0;
     412                 :          0 :     sal_Int32 nEscapeLength = rtl_uString_getLength( pToEscape );
     413                 :            : 
     414                 :          0 :     rtl_uString_new_WithLength( &pBuffer, nCapacity );
     415                 :            : 
     416         [ #  # ]:          0 :     for ( ; i < nEscapeLength; ++i )
     417                 :            :     {
     418                 :          0 :         sal_Unicode c = pToEscape->buffer[i];
     419   [ #  #  #  # ]:          0 :         switch ( c )
     420                 :            :         {
     421                 :            :             case (sal_Unicode)'\0':
     422                 :          0 :                 rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
     423                 :            :                         rtl_uString_getLength( pBuffer ),
     424                 :            :                         RTL_CONSTASCII_STRINGPARAM( "\\0" ) );
     425                 :          0 :                 break;
     426                 :            :             case (sal_Unicode)',':
     427                 :          0 :                 rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
     428                 :            :                         rtl_uString_getLength( pBuffer ),
     429                 :            :                         RTL_CONSTASCII_STRINGPARAM( "\\," ) );
     430                 :          0 :                 break;
     431                 :            :             case (sal_Unicode)'\\':
     432                 :          0 :                 rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
     433                 :            :                         rtl_uString_getLength( pBuffer ),
     434                 :            :                         RTL_CONSTASCII_STRINGPARAM( "\\\\" ) );
     435                 :          0 :                 break;
     436                 :            :             default:
     437                 :          0 :                 rtl_uStringbuffer_insert( &pBuffer, &nCapacity,
     438                 :            :                         rtl_uString_getLength( pBuffer ),
     439                 :            :                         &c, 1 );
     440                 :            :         }
     441                 :            :     }
     442                 :            : 
     443                 :          0 :     return pBuffer;
     444                 :            : }
     445                 :            : 
     446                 :            : /* Send args to the OOo instance (using the 'fd' file descriptor) */
     447                 :            : static sal_Bool
     448                 :          0 : send_args( int fd, rtl_uString *pCwdPath )
     449                 :            : {
     450                 :          0 :     rtl_uString *pBuffer = NULL, *pTmp = NULL;
     451                 :          0 :     sal_Int32 nCapacity = 1000;
     452                 :          0 :     rtl_String *pOut = NULL;
     453                 :            :     sal_Bool bResult;
     454                 :            :     size_t nLen;
     455                 :          0 :     rtl_uString *pEscapedCwdPath = escape_path( pCwdPath );
     456                 :          0 :     sal_uInt32 nArg = 0;
     457                 :          0 :     sal_uInt32 nArgCount = osl_getCommandArgCount();
     458                 :            : 
     459                 :          0 :     rtl_uString_new_WithLength( &pBuffer, nCapacity );
     460                 :          0 :     rtl_uString_new( &pTmp );
     461                 :            : 
     462                 :          0 :     rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
     463                 :            :             rtl_uString_getLength( pBuffer ),
     464                 :            :             RTL_CONSTASCII_STRINGPARAM( "InternalIPC::Arguments" ) );
     465                 :            : 
     466         [ #  # ]:          0 :     if ( rtl_uString_getLength( pEscapedCwdPath ) )
     467                 :            :     {
     468                 :          0 :     rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
     469                 :            :         rtl_uString_getLength( pBuffer ),
     470                 :            :         RTL_CONSTASCII_STRINGPARAM( "1" ) );
     471                 :          0 :     rtl_uStringbuffer_insert( &pBuffer, &nCapacity,
     472                 :            :                 rtl_uString_getLength( pBuffer ),
     473                 :          0 :                 rtl_uString_getStr( pEscapedCwdPath ),
     474                 :            :                 rtl_uString_getLength( pEscapedCwdPath ) );
     475                 :            :     }
     476                 :            :     else
     477                 :          0 :     rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
     478                 :            :         rtl_uString_getLength( pBuffer ),
     479                 :            :         RTL_CONSTASCII_STRINGPARAM( "0" ) );
     480                 :            : 
     481         [ #  # ]:          0 :     for ( nArg = 0; nArg < nArgCount; ++nArg )
     482                 :            :     {
     483                 :          0 :         rtl_uString *pEscapedTmp = NULL;
     484                 :          0 :         rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
     485                 :            :                 rtl_uString_getLength( pBuffer ),
     486                 :            :                 ",", 1 );
     487                 :            : 
     488                 :          0 :         osl_getCommandArg( nArg, &pTmp );
     489                 :            : 
     490                 :          0 :         pEscapedTmp = escape_path( pTmp );
     491                 :            : 
     492                 :          0 :         rtl_uStringbuffer_insert( &pBuffer, &nCapacity,
     493                 :            :                 rtl_uString_getLength( pBuffer ),
     494                 :          0 :                 rtl_uString_getStr( pEscapedTmp ),
     495                 :            :                 rtl_uString_getLength( pEscapedTmp ) );
     496                 :            : 
     497                 :          0 :         rtl_uString_release( pEscapedTmp );
     498                 :            :     }
     499                 :            : 
     500                 :            :     ustr_debug( "Pass args", pBuffer );
     501                 :            : 
     502         [ #  # ]:          0 :     if ( !rtl_convertUStringToString(
     503                 :          0 :              &pOut, rtl_uString_getStr( pBuffer ),
     504                 :            :              rtl_uString_getLength( pBuffer ), RTL_TEXTENCODING_UTF8,
     505                 :            :              ( RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
     506                 :            :                | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR ) ) )
     507                 :            :     {
     508                 :          0 :         fprintf( stderr, "ERROR: cannot convert arguments to UTF-8" );
     509                 :          0 :         exit( 1 );
     510                 :            :     }
     511                 :            : 
     512                 :          0 :     nLen = rtl_string_getLength( pOut ) + 1;
     513                 :          0 :     bResult = ( write( fd, rtl_string_getStr( pOut ), nLen ) == (ssize_t) nLen );
     514                 :            : 
     515                 :            :     /* cleanup */
     516                 :          0 :     rtl_uString_release( pEscapedCwdPath );
     517                 :          0 :     rtl_uString_release( pBuffer );
     518                 :          0 :     rtl_uString_release( pTmp );
     519                 :          0 :     rtl_string_release( pOut );
     520                 :            : 
     521                 :          0 :     return bResult;
     522                 :            : }
     523                 :            : 
     524                 :            : 
     525                 :            : #define BUFFER_LEN 255
     526                 :            : 
     527                 :            : /* Read the percent to show in splash. */
     528                 :            : static ProgressStatus
     529                 :          0 : read_percent( ChildInfo *info, int *pPercent )
     530                 :            : {
     531                 :            :     static char pBuffer[BUFFER_LEN + 1];
     532                 :            :     static char *pNext = pBuffer;
     533                 :            :     static ssize_t nRead = 0;
     534                 :            : 
     535                 :            :     char *pBegin;
     536                 :            :     char *pIter;
     537                 :            :     char c;
     538                 :            : 
     539                 :            :     /* from the last call */
     540                 :          0 :     int nNotProcessed = nRead - ( pNext - pBuffer );
     541         [ #  # ]:          0 :     if ( nNotProcessed >= BUFFER_LEN )
     542                 :          0 :         return sal_False;
     543                 :            : 
     544                 :          0 :     memmove( pBuffer, pNext, nNotProcessed );
     545                 :            : 
     546                 :            :     /* read data */
     547                 :          0 :     nRead = read( child_info_get_status_fd (info),
     548                 :          0 :                   pBuffer + nNotProcessed, BUFFER_LEN - nNotProcessed );
     549         [ #  # ]:          0 :     if ( nRead < 0 ) {
     550         [ #  # ]:          0 :         if (errno == EINTR)
     551                 :          0 :             return ProgressContinue;
     552                 :          0 :         return ProgressExit;
     553                 :            :     }
     554                 :            : 
     555                 :          0 :     nRead += nNotProcessed;
     556                 :          0 :     pBuffer[nRead] = '\0';
     557                 :            : 
     558                 :            :     /* skip old data */
     559                 :          0 :     pBegin = pBuffer;
     560                 :          0 :     pNext = pBuffer;
     561         [ #  # ]:          0 :     for ( pIter = pBuffer; *pIter; ++pIter )
     562                 :            :     {
     563         [ #  # ]:          0 :         if ( *pIter == '\n' )
     564                 :            :         {
     565                 :          0 :             pBegin = pNext;
     566                 :          0 :             pNext = pIter + 1;
     567                 :            :         }
     568                 :            :     }
     569                 :            : 
     570                 :            : #if OSL_DEBUG_LEVEL > 1
     571                 :            :     fprintf( stderr, "Got status: %s\n", pBegin );
     572                 :            : #endif
     573         [ #  # ]:          0 :     if ( !strncasecmp( pBegin, "end", 3 ) )
     574                 :          0 :         return ProgressExit;
     575         [ #  # ]:          0 :     else if ( !strncasecmp( pBegin, "restart", 7 ) )
     576                 :          0 :         return ProgressRestart;
     577 [ #  # ][ #  # ]:          0 :     else if ( sscanf( pBegin, "%d%c", pPercent, &c ) == 2 && c == '%' )
     578                 :          0 :         return ProgressContinue;
     579                 :            : 
     580                 :            :     /* unexpected - let's exit the splash to be safe */
     581                 :          0 :     return ProgressExit;
     582                 :            : }
     583                 :            : 
     584                 :            : /* Simple system check. */
     585                 :            : static void
     586                 :         99 : system_checks( void )
     587                 :            : {
     588                 :            : #ifdef LINUX
     589                 :            :     struct stat buf;
     590                 :            : 
     591                 :            :     /* check proc is mounted - lots of things fail otherwise */
     592         [ -  + ]:         99 :     if ( stat( "/proc/version", &buf ) != 0 )
     593                 :            :     {
     594                 :          0 :         fprintf( stderr, "ERROR: /proc not mounted - LibreOffice is unlikely to work well if at all" );
     595                 :          0 :         exit( 1 );
     596                 :            :     }
     597                 :            : #endif
     598                 :         99 : }
     599                 :            : 
     600                 :            : /* re-use the pagein code */
     601                 :            : extern int pagein_execute (int argc, char **argv);
     602                 :            : 
     603                 :          0 : static char *build_pagein_path (Args *args, const char *pagein_name)
     604                 :            : {
     605                 :            :     char *path;
     606                 :            :     rtl_String *app_path;
     607                 :            : 
     608                 :          0 :     app_path = ustr_to_str (args->pAppPath);
     609                 :          0 :     path = malloc (
     610                 :          0 :         RTL_CONSTASCII_LENGTH("@") + app_path->length + strlen (pagein_name) +
     611                 :            :         1);
     612                 :          0 :     strcpy (path, "@");
     613                 :          0 :     strcpy (path + 1, rtl_string_getStr (app_path));
     614                 :          0 :     strcat (path, pagein_name);
     615                 :            : 
     616                 :          0 :     rtl_string_release( app_path );
     617                 :            : 
     618                 :          0 :     return path;
     619                 :            : }
     620                 :            : 
     621                 :            : void
     622                 :          0 : exec_pagein (Args *args)
     623                 :            : {
     624                 :            :     char *argv[3];
     625                 :            : 
     626                 :            :     /* don't use -L - since that does a chdir that breaks relative paths */
     627                 :          0 :     argv[0] = "dummy-pagein";
     628                 :          0 :     argv[1] = build_pagein_path (args, "pagein-common");
     629         [ #  # ]:          0 :     if (args->pPageinType) {
     630                 :          0 :         argv[2] = build_pagein_path (args, args->pPageinType);
     631                 :            :     } else
     632                 :          0 :         argv[2] = NULL;
     633                 :            : 
     634         [ #  # ]:          0 :     pagein_execute (args->pPageinType ? 3 : 2, argv);
     635                 :            : 
     636         [ #  # ]:          0 :     if (argv[2])
     637                 :          0 :         free (argv[2]);
     638                 :          0 :     free (argv[1]);
     639                 :          0 : }
     640                 :            : 
     641                 :            : #if defined SOLAR_JAVA
     642                 :            : 
     643                 :          0 : static void extend_library_path (const char *new_element)
     644                 :            : {
     645                 :          0 :     rtl_uString *pEnvName=NULL, *pOrigEnvVar=NULL, *pNewEnvVar=NULL;
     646                 :            :     const char *pathname;
     647                 :            : #ifdef AIX
     648                 :            :     pathname = "LIBPATH";
     649                 :            : #else
     650                 :          0 :     pathname = "LD_LIBRARY_PATH";
     651                 :            : #endif
     652                 :            : 
     653                 :          0 :     rtl_uString_newFromAscii( &pEnvName, pathname );
     654                 :          0 :     rtl_uString_newFromAscii( &pNewEnvVar, new_element );
     655                 :            : 
     656                 :          0 :     osl_getEnvironment( pEnvName, &pOrigEnvVar );
     657 [ #  # ][ #  # ]:          0 :     if (pOrigEnvVar && pOrigEnvVar->length)
     658                 :            :     {
     659                 :          0 :         rtl_uString *pDelim = NULL;
     660                 :          0 :         rtl_uString_newFromAscii( &pDelim, ":" );
     661                 :          0 :         rtl_uString_newConcat( &pNewEnvVar, pNewEnvVar, pDelim );
     662                 :          0 :         rtl_uString_newConcat( &pNewEnvVar, pNewEnvVar, pOrigEnvVar );
     663                 :          0 :         rtl_uString_release( pDelim );
     664                 :            :     }
     665                 :            : 
     666                 :          0 :     osl_setEnvironment( pEnvName, pNewEnvVar );
     667                 :            : 
     668         [ #  # ]:          0 :     if (pOrigEnvVar)
     669                 :          0 :         rtl_uString_release( pOrigEnvVar );
     670                 :          0 :     rtl_uString_release( pNewEnvVar );
     671                 :          0 :     rtl_uString_release( pEnvName );
     672                 :          0 : }
     673                 :            : 
     674                 :            : static void
     675                 :          0 : exec_javaldx (Args *args)
     676                 :            : {
     677                 :            :     char newpath[4096];
     678                 :            :     sal_uInt32 nArgs;
     679                 :            :     rtl_uString *pApp;
     680                 :            :     rtl_uString **ppArgs;
     681                 :            :     rtl_uString *pTmp, *pTmp2;
     682                 :            : 
     683                 :          0 :     oslProcess javaldx = NULL;
     684                 :          0 :     oslFileHandle fileOut= 0;
     685                 :            :     oslProcessError err;
     686                 :            : 
     687                 :          0 :     ppArgs = (rtl_uString **)calloc( args->nArgsEnv + 2, sizeof( rtl_uString* ) );
     688                 :            : 
     689         [ #  # ]:          0 :     for ( nArgs = 0; nArgs < args->nArgsEnv; ++nArgs )
     690                 :          0 :         ppArgs[nArgs] = args->ppArgs[nArgs];
     691                 :            : 
     692                 :            :     /* Use absolute path to redirectrc */
     693                 :          0 :     pTmp = NULL;
     694                 :          0 :     rtl_uString_newFromAscii( &pTmp, "-env:INIFILENAME=vnd.sun.star.pathname:" );
     695                 :          0 :     rtl_uString_newConcat( &pTmp, pTmp, args->pAppPath );
     696                 :          0 :     pTmp2 = NULL;
     697                 :          0 :     rtl_uString_newFromAscii( &pTmp2, "redirectrc" );
     698                 :          0 :     rtl_uString_newConcat( &pTmp, pTmp, pTmp2 );
     699                 :          0 :     ppArgs[nArgs] = pTmp;
     700                 :          0 :     rtl_uString_release (pTmp2);
     701                 :          0 :     nArgs++;
     702                 :            : 
     703                 :            :     /* And also to javaldx */
     704                 :          0 :     pApp = NULL;
     705                 :          0 :     rtl_uString_newFromAscii( &pApp, "file://" );
     706                 :          0 :     rtl_uString_newConcat( &pApp, pApp, args->pAppPath );
     707                 :          0 :     pTmp = NULL;
     708                 :          0 :     rtl_uString_newFromAscii( &pTmp, "../ure-link/bin/javaldx" );
     709                 :          0 :     rtl_uString_newConcat( &pApp, pApp, pTmp );
     710                 :          0 :     rtl_uString_release( pTmp );
     711                 :            : 
     712                 :          0 :     err = osl_executeProcess_WithRedirectedIO( pApp, ppArgs, nArgs,
     713                 :            :                                                osl_Process_NORMAL,
     714                 :            :                                                NULL, // security
     715                 :            :                                                NULL, // work dir
     716                 :            :                                                NULL, 0,
     717                 :            :                                                &javaldx, // process handle
     718                 :            :                                                NULL,
     719                 :            :                                                &fileOut,
     720                 :            :                                                NULL);
     721                 :            : 
     722                 :          0 :     rtl_uString_release( ppArgs[nArgs-1] );
     723                 :          0 :     rtl_uString_release( pApp );
     724                 :          0 :     free( ppArgs );
     725                 :            : 
     726         [ #  # ]:          0 :     if( err != osl_Process_E_None)
     727                 :            :     {
     728                 :          0 :         fprintf (stderr, "Warning: failed to launch javaldx - java may not fuction correctly\n");
     729         [ #  # ]:          0 :         if (javaldx)
     730                 :          0 :             osl_freeProcessHandle(javaldx);
     731         [ #  # ]:          0 :         if (fileOut)
     732                 :          0 :             osl_closeFile(fileOut);
     733                 :            :         return;
     734                 :            :     } else {
     735                 :            :         char *chomp;
     736                 :            :         sal_uInt64 bytes_read;
     737                 :            : 
     738                 :            :         /* Magically osl_readLine doesn't work with pipes with E_SPIPE - so be this lame instead: */
     739         [ #  # ]:          0 :         while (osl_readFile (fileOut, newpath, SAL_N_ELEMENTS (newpath), &bytes_read) == osl_File_E_INTR);
     740                 :            : 
     741         [ #  # ]:          0 :         if (bytes_read <= 0) {
     742                 :          0 :             fprintf (stderr, "Warning: failed to read path from javaldx\n");
     743         [ #  # ]:          0 :             if (javaldx)
     744                 :          0 :                 osl_freeProcessHandle(javaldx);
     745         [ #  # ]:          0 :             if (fileOut)
     746                 :          0 :                 osl_closeFile(fileOut);
     747                 :            :             return;
     748                 :            :         }
     749                 :          0 :         newpath[bytes_read] = '\0';
     750                 :            : 
     751         [ #  # ]:          0 :         if ((chomp = strstr (newpath, "\n")))
     752                 :          0 :             *chomp = '\0';
     753                 :            :     }
     754                 :            : 
     755                 :            : #if OSL_DEBUG_LEVEL > 1
     756                 :            :     fprintf (stderr, "Adding javaldx path of '%s'\n", newpath);
     757                 :            : #endif
     758                 :          0 :     extend_library_path (newpath);
     759                 :            : 
     760         [ #  # ]:          0 :     if (javaldx)
     761                 :          0 :         osl_freeProcessHandle(javaldx);
     762         [ #  # ]:          0 :     if (fileOut)
     763                 :          0 :         osl_closeFile(fileOut);
     764                 :            : }
     765                 :            : 
     766                 :            : #endif
     767                 :            : 
     768                 :            : // has to be a global :(
     769                 :            : oslProcess * volatile g_pProcess = 0;
     770                 :            : 
     771                 :          0 : void sigterm_handler(int ignored)
     772                 :            : {
     773                 :            :     (void) ignored;
     774         [ #  # ]:          0 :     if (g_pProcess)
     775                 :            :     {
     776                 :            :         // forward signal to soffice.bin
     777                 :          0 :         osl_terminateProcess(g_pProcess);
     778                 :            :     }
     779                 :          0 :     _exit(255);
     780                 :            : }
     781                 :            : 
     782                 :            : 
     783                 :         99 : SAL_IMPLEMENT_MAIN_WITH_ARGS( argc, argv )
     784                 :            : {
     785                 :         99 :     int fd = 0;
     786                 :         99 :     sal_Bool bSentArgs = sal_False;
     787                 :            :     const char* pUsePlugin;
     788                 :         99 :     rtl_uString *pPipePath = NULL;
     789                 :            :     Args *args;
     790                 :         99 :     int status = 0;
     791                 :         99 :     struct splash* splash = NULL;
     792                 :            :     struct sigaction sigpipe_action;
     793                 :            :     struct sigaction sigterm_action;
     794                 :            : 
     795                 :            :     /* turn SIGPIPE into an error */
     796                 :         99 :     memset(&sigpipe_action, 0, sizeof(struct sigaction));
     797                 :         99 :     sigpipe_action.sa_handler = SIG_IGN;
     798                 :         99 :     sigemptyset(&sigpipe_action.sa_mask);
     799                 :         99 :     sigaction(SIGPIPE, &sigpipe_action, 0);
     800                 :         99 :     memset(&sigterm_action, 0, sizeof(struct sigaction));
     801                 :         99 :     sigterm_action.sa_handler = &sigterm_handler;
     802                 :         99 :     sigemptyset(&sigterm_action.sa_mask);
     803                 :         99 :     sigaction(SIGTERM, &sigterm_action, 0);
     804                 :            : 
     805                 :         99 :     args = args_parse ();
     806                 :         99 :     args->pAppPath = get_app_path( argv[0] );
     807         [ -  + ]:         99 :     if ( !args->pAppPath )
     808                 :            :     {
     809                 :          0 :         fprintf( stderr, "ERROR: Can't read app link\n" );
     810                 :          0 :         exit( 1 );
     811                 :            :     }
     812                 :            :     ustr_debug( "App path", args->pAppPath );
     813                 :            : 
     814                 :            : #ifndef ENABLE_QUICKSTART_LIBPNG
     815                 :            :     /* we can't load and render it anyway */
     816                 :            :     args->bInhibitSplash = sal_True;
     817                 :            : #endif
     818                 :            : 
     819                 :         99 :     pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" );
     820 [ #  # ][ -  + ]:         99 :     if ( pUsePlugin && !strcmp(pUsePlugin, "svp") )
     821                 :          0 :         args->bInhibitSplash = sal_True;
     822                 :            : 
     823                 :         99 :     pPipePath = get_pipe_path( args->pAppPath );
     824                 :            : 
     825         [ -  + ]:         99 :     if ( ( fd = connect_pipe( pPipePath ) ) >= 0 )
     826                 :            :     {
     827                 :          0 :         rtl_uString *pCwdPath = NULL;
     828                 :          0 :         osl_getProcessWorkingDir( &pCwdPath );
     829                 :            : 
     830                 :          0 :         bSentArgs = send_args( fd, pCwdPath );
     831                 :            : 
     832                 :          0 :         close( fd );
     833                 :            :     }
     834                 :            : #if OSL_DEBUG_LEVEL > 1
     835                 :            :     else
     836                 :            :         ustr_debug( "Failed to connect to pipe", pPipePath );
     837                 :            : #endif
     838                 :            : 
     839         [ +  - ]:         99 :     if ( !bSentArgs )
     840                 :            :     {
     841                 :            :         /* we have to prepare for, and exec the binary */
     842                 :         99 :         int nPercent = 0;
     843                 :            :         ChildInfo *info;
     844                 :         99 :         sal_Bool bAllArgs = sal_True;
     845                 :            :         sal_Bool bShortWait, bRestart;
     846                 :            : 
     847                 :            :         /* sanity check pieces */
     848                 :         99 :         system_checks();
     849                 :            : 
     850                 :            :         /* load splash image and create window */
     851         [ -  + ]:         99 :         if ( !args->bInhibitSplash )
     852                 :            :         {
     853                 :          0 :             splash = splash_create(args->pAppPath, argc, argv);
     854                 :            :         }
     855                 :            : 
     856                 :            :         /* pagein */
     857         [ -  + ]:         99 :         if (!args->bInhibitPagein)
     858                 :          0 :             exec_pagein (args);
     859                 :            : 
     860                 :            :         /* javaldx */
     861                 :            : #ifdef SOLAR_JAVA
     862         [ -  + ]:         99 :         if (!args->bInhibitJavaLdx)
     863                 :          0 :             exec_javaldx (args);
     864                 :            : #endif
     865                 :            : 
     866                 :            :         do
     867                 :            :         {
     868                 :        161 :             bRestart = sal_False;
     869                 :            : 
     870                 :            :             /* fast updates if we have somewhere to update it to */
     871                 :        161 :             bShortWait = splash ? sal_True : sal_False;
     872                 :            : 
     873                 :            :             /* Periodically update the splash & the percent according
     874                 :            :                to what status_fd says, poll quickly only while starting */
     875                 :        161 :             info = child_spawn (args, bAllArgs, bShortWait);
     876                 :        161 :             g_pProcess = info->child;
     877         [ -  + ]:        161 :             while (!child_exited_wait (info, bShortWait))
     878                 :            :             {
     879                 :            :                 ProgressStatus eResult;
     880                 :            : 
     881                 :          0 :                 splash_draw_progress( splash, nPercent );
     882                 :          0 :                 eResult = read_percent( info, &nPercent );
     883         [ #  # ]:          0 :                 if (eResult != ProgressContinue)
     884                 :            :                 {
     885                 :          0 :                     splash_destroy(splash);
     886                 :          0 :                     splash = NULL;
     887                 :          0 :                     bShortWait = sal_False;
     888                 :            :                 }
     889                 :            : 
     890                 :            : #if OSL_DEBUG_LEVEL > 1
     891                 :            :                 fprintf( stderr, "Polling, result is %s\n",
     892                 :            :                          ( eResult == ProgressContinue )? "continue" :
     893                 :            :                          ( ( eResult == ProgressRestart )? "restart" : "exit" ) );
     894                 :            : #endif
     895                 :            :             }
     896                 :            : 
     897                 :            : #if OSL_DEBUG_LEVEL > 0
     898                 :            :             fprintf (stderr, "Exited with code '%d'\n", child_get_exit_code (info));
     899                 :            : #endif
     900                 :            : 
     901                 :        161 :             status = child_get_exit_code(info);
     902                 :        161 :             g_pProcess = 0; // reset
     903      [ -  +  + ]:        161 :             switch (status) {
     904                 :            :             case 79: // re-start with just -env: parameters
     905                 :            : #if OSL_DEBUG_LEVEL > 0
     906                 :            :                 fprintf (stderr, "oosplash: re-start with just -env: params !\n");
     907                 :            : #endif
     908                 :          0 :                 bRestart = sal_True;
     909                 :          0 :                 bAllArgs = sal_False;
     910                 :          0 :                 break;
     911                 :            :             case 81: // re-start with all arguments
     912                 :            : #if OSL_DEBUG_LEVEL > 0
     913                 :            :                 fprintf (stderr, "oosplash: re-start with all params !\n");
     914                 :            : #endif
     915                 :         62 :                 bRestart = sal_True;
     916                 :         62 :                 bAllArgs = sal_True;
     917                 :         62 :                 break;
     918                 :            :             default:
     919                 :         99 :                 break;
     920                 :            :             }
     921                 :            : 
     922                 :        161 :             child_info_destroy (info);
     923         [ +  + ]:        161 :         } while (bRestart);
     924                 :            :     }
     925                 :            : 
     926                 :            :     /* cleanup */
     927                 :         99 :     rtl_uString_release( pPipePath );
     928                 :         99 :     args_free (args);
     929                 :            : 
     930                 :         99 :     return status;
     931                 :            : }
     932                 :            : 
     933                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10