1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <arpa/inet.h>
25 #include <osl/process.h>
26 #include <osl/thread.h>
27 #include <rtl/bootstrap.h>
28 #include <rtl/digest.h>
29 #include <rtl/process.h>
30 #include <rtl/ustrbuf.h>
34 #include "../../source/inc/exithelper.h"
37 #define PIPEDEFAULTPATH "/tmp"
38 #define PIPEALTERNATEPATH "/var/tmp"
40 /* Easier conversions: rtl_uString to rtl_String */
42 ustr_to_str( rtl_uString
*pStr
)
44 rtl_String
*pOut
= NULL
;
46 rtl_uString2String( &pOut
, rtl_uString_getStr( pStr
),
47 rtl_uString_getLength( pStr
), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS
);
52 /* Easier conversions: char * to rtl_uString */
54 charp_to_ustr( const char *pStr
)
56 rtl_uString
*pOut
= NULL
;
58 rtl_string2UString( &pOut
, pStr
, strlen( pStr
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
63 /* Easier debugging of rtl_uString values. */
64 #if OSL_DEBUG_LEVEL > 1
66 ustr_debug( const char *pMessage
, rtl_uString
*pStr
)
68 rtl_String
*pOut
= ustr_to_str( pStr
);
70 fprintf( stderr
, "%s: %s\n", pMessage
, rtl_string_getStr( pOut
) );
72 rtl_string_release( pOut
);
76 #define ustr_debug( a, b ) {}
85 child_info_get_status_fd (ChildInfo
*info
)
87 return info
->status_fd
;
91 child_info_destroy (ChildInfo
*info
)
93 close (info
->status_fd
);
94 osl_freeProcessHandle (info
->child
);
99 child_spawn ( Args
*args
, sal_Bool bAllArgs
, sal_Bool bWithStatus
)
101 rtl_uString
*pApp
= NULL
, *pTmp
= NULL
;
102 rtl_uString
**ppArgs
;
107 oslProcessError nError
;
109 info
= calloc (1, sizeof (ChildInfo
));
112 if ( pipe( status_pipe
) < 0 )
114 fprintf( stderr
, "ERROR: no file handles\n");
117 info
->status_fd
= status_pipe
[0];
119 /* application name */
120 rtl_uString_newFromAscii( &pApp
, "file://" );
121 rtl_uString_newConcat( &pApp
, pApp
, args
->pAppPath
);
122 rtl_uString_newFromAscii( &pTmp
, "soffice.bin" );
123 rtl_uString_newConcat( &pApp
, pApp
, pTmp
);
124 rtl_uString_release( pTmp
);
128 nArgs
= bAllArgs
? args
->nArgsTotal
: args
->nArgsEnv
;
129 ppArgs
= (rtl_uString
**)calloc( nArgs
+ 1, sizeof( rtl_uString
* ) );
130 for ( i
= 0; i
< nArgs
; ++i
)
131 ppArgs
[i
] = args
->ppArgs
[i
];
135 /* add the pipe arg */
136 snprintf (buffer
, 63, "--splash-pipe=%d", status_pipe
[1]);
137 rtl_uString_newFromAscii( &pTmp
, buffer
);
138 ppArgs
[nArgs
] = pTmp
;
142 /* start the main process */
143 nError
= osl_executeProcess( pApp
, ppArgs
, nArgs
,
151 rtl_uString_release( pTmp
);
154 if ( nError
!= osl_Process_E_None
)
156 fprintf( stderr
, "ERROR %d forking process", nError
);
157 ustr_debug( "", pApp
);
158 rtl_uString_release( pApp
);
162 rtl_uString_release( pApp
);
163 close( status_pipe
[1] );
169 child_exited_wait (ChildInfo
*info
, sal_Bool bShortWait
)
171 TimeValue t
= { 0, 250 /* ms */ * 1000 * 1000 };
174 return osl_joinProcessWithTimeout (info
->child
, &t
) != osl_Process_E_TimedOut
;
178 child_get_exit_code (ChildInfo
*info
)
183 inf
.Size
= sizeof (inf
);
184 if (osl_getProcessInfo (info
->child
, osl_Process_EXITCODE
, &inf
) != osl_Process_E_None
)
186 fprintf (stderr
, "Warning: failed to fetch libreoffice exit status\n");
192 typedef enum { ProgressContinue
, ProgressRestart
, ProgressExit
} ProgressStatus
;
194 /* Path of the application, with trailing slash. */
196 get_app_path( const char *pAppExec
)
198 char pRealPath
[PATH_MAX
];
199 rtl_uString
*pResult
;
203 char *pOrigPath
= strdup( pAppExec
);
204 char *pPath
= dirname( pOrigPath
);
206 dummy
= realpath( pPath
, pRealPath
);
208 pResult
= charp_to_ustr( pRealPath
);
211 len
= rtl_uString_getLength(pResult
);
212 if (len
> 0 && rtl_uString_getStr(pResult
)[len
- 1] != '/')
214 rtl_uString
*pSlash
= NULL
;
215 rtl_uString_newFromAscii(&pSlash
, "/");
216 rtl_uString_newConcat(&pResult
, pResult
, pSlash
);
217 rtl_uString_release(pSlash
);
223 /* Compute the OOo md5 hash from 'pText' */
225 get_md5hash( rtl_uString
*pText
)
227 rtl_uString
*pResult
= NULL
;
228 sal_Int32 nCapacity
= 100;
229 unsigned char *pData
= NULL
;
230 sal_uInt32 nSize
= 0;
232 sal_uInt32 md5_key_len
= 0;
233 sal_uInt8
* md5_buf
= NULL
;
235 #if OSL_DEBUG_LEVEL > 1
242 #if OSL_DEBUG_LEVEL > 1
243 pOut
= ustr_to_str( pText
);
244 fprintf (stderr
, "Generate pipe md5 for '%s'\n", pOut
->buffer
);
245 rtl_string_release( pOut
);
248 pData
= (unsigned char *)rtl_uString_getStr( pText
);
249 nSize
= rtl_uString_getLength( pText
) * sizeof( sal_Unicode
);
253 digest
= rtl_digest_create( rtl_Digest_AlgorithmMD5
);
257 md5_key_len
= rtl_digest_queryLength( digest
);
258 md5_buf
= (sal_uInt8
*)calloc( md5_key_len
, sizeof( sal_uInt8
) );
260 rtl_digest_init( digest
, pData
, nSize
);
261 rtl_digest_update( digest
, pData
, nSize
);
262 rtl_digest_get( digest
, md5_buf
, md5_key_len
);
263 rtl_digest_destroy( digest
);
265 /* create hex-value string from the MD5 value to keep
266 the string size minimal */
267 rtl_uString_new_WithLength( &pResult
, nCapacity
);
268 for ( ; i
< md5_key_len
; ++i
)
271 snprintf( val
, 3, "%x", md5_buf
[i
] ); /* sic! we ignore some of the 0's */
273 rtl_uStringbuffer_insert_ascii( &pResult
, &nCapacity
, rtl_uString_getLength( pResult
),
274 val
, strlen( val
) );
283 /* Construct the pipe name */
285 get_pipe_path( rtl_uString
*pAppPath
)
287 rtl_uString
*pPath
= NULL
, *pTmp
= NULL
, *pUserInstallation
= NULL
;
288 rtl_uString
*pResult
= NULL
, *pBasePath
= NULL
, *pAbsUserInstallation
= NULL
;
289 rtlBootstrapHandle handle
;
290 rtl_uString
*pMd5hash
= NULL
;
291 sal_Unicode pUnicode
[RTL_USTR_MAX_VALUEOFINT32
];
293 /* setup bootstrap filename */
294 rtl_uString_newFromAscii( &pPath
, "file://" );
295 rtl_uString_newConcat( &pPath
, pPath
, pAppPath
);
296 rtl_uString_newConcat( &pPath
, pPath
, pTmp
);
297 rtl_uString_newFromAscii( &pTmp
, SAL_CONFIGFILE( "bootstrap" ) );
298 rtl_uString_newConcat( &pPath
, pPath
, pTmp
);
300 ustr_debug( "bootstap", pPath
);
302 /* read userinstallation value */
303 handle
= rtl_bootstrap_args_open( pPath
);
305 rtl_uString_newFromAscii( &pTmp
, "UserInstallation" );
306 rtl_bootstrap_get_from_handle( handle
, pTmp
, &pUserInstallation
, NULL
);
308 rtl_bootstrap_args_close( handle
);
310 /* turn it into an absolute path - unwinding symlinks etc. */
311 if ( osl_getProcessWorkingDir (&pBasePath
) ||
312 osl_getAbsoluteFileURL( pBasePath
, pUserInstallation
, &pAbsUserInstallation
) )
313 rtl_uString_newFromString (&pAbsUserInstallation
, pUserInstallation
);
315 /* create the pipe name */
316 ustr_debug( "user installation", pAbsUserInstallation
);
317 pMd5hash
= get_md5hash( pAbsUserInstallation
);
319 rtl_uString_new( &pMd5hash
);
321 if ( access( PIPEDEFAULTPATH
, R_OK
|W_OK
) == 0 )
322 rtl_uString_newFromAscii( &pResult
, PIPEDEFAULTPATH
);
324 rtl_uString_newFromAscii( &pResult
, PIPEALTERNATEPATH
);
326 rtl_uString_newFromAscii( &pTmp
, "/OSL_PIPE_" );
327 rtl_uString_newConcat( &pResult
, pResult
, pTmp
);
329 rtl_ustr_valueOfInt32( pUnicode
, (int)getuid(), 10 );
330 rtl_uString_newFromStr( &pTmp
, pUnicode
);
331 rtl_uString_newConcat( &pResult
, pResult
, pTmp
);
333 rtl_uString_newFromAscii( &pTmp
, "_SingleOfficeIPC_" );
334 rtl_uString_newConcat( &pResult
, pResult
, pTmp
);
336 rtl_uString_newConcat( &pResult
, pResult
, pMd5hash
);
338 ustr_debug( "result", pResult
);
341 rtl_uString_release( pMd5hash
);
342 rtl_uString_release( pPath
);
343 rtl_uString_release( pTmp
);
346 rtl_uString_release( pBasePath
);
348 rtl_uString_release( pUserInstallation
);
349 rtl_uString_release( pAbsUserInstallation
);
354 /* Get fd of the pipe of the already running OOo. */
356 connect_pipe( rtl_uString
*pPipePath
)
360 struct sockaddr_un addr
;
362 rtl_String
*pPipeStr
= ustr_to_str( pPipePath
);
364 memset( &addr
, 0, sizeof( addr
) );
366 if ( ( fd
= socket( AF_UNIX
, SOCK_STREAM
, 0 ) ) < 0 )
369 fcntl( fd
, F_SETFD
, FD_CLOEXEC
);
371 addr
.sun_family
= AF_UNIX
;
372 strncpy( addr
.sun_path
, rtl_string_getStr( pPipeStr
), sizeof( addr
.sun_path
) - 1 );
373 rtl_string_release( pPipeStr
);
375 /* cut / paste from osl's pipe.c */
377 len
= SUN_LEN( &addr
);
379 len
= sizeof( addr
);
382 if ( connect( fd
, (struct sockaddr
*)&addr
, len
) < 0 )
390 /* Escape: "," -> "\\,", "\0" -> "\\0", "\\" -> "\\\\" */
392 escape_path( rtl_uString
*pToEscape
)
394 rtl_uString
*pBuffer
= NULL
;
395 sal_Int32 nCapacity
= 1000;
397 sal_Int32 nEscapeLength
= rtl_uString_getLength( pToEscape
);
399 rtl_uString_new_WithLength( &pBuffer
, nCapacity
);
401 for ( ; i
< nEscapeLength
; ++i
)
403 sal_Unicode c
= pToEscape
->buffer
[i
];
406 case (sal_Unicode
)'\0':
407 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
408 rtl_uString_getLength( pBuffer
),
409 RTL_CONSTASCII_STRINGPARAM( "\\0" ) );
411 case (sal_Unicode
)',':
412 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
413 rtl_uString_getLength( pBuffer
),
414 RTL_CONSTASCII_STRINGPARAM( "\\," ) );
416 case (sal_Unicode
)'\\':
417 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
418 rtl_uString_getLength( pBuffer
),
419 RTL_CONSTASCII_STRINGPARAM( "\\\\" ) );
422 rtl_uStringbuffer_insert( &pBuffer
, &nCapacity
,
423 rtl_uString_getLength( pBuffer
),
431 /* Send args to the OOo instance (using the 'fd' file descriptor) */
433 send_args( int fd
, rtl_uString
*pCwdPath
)
435 rtl_uString
*pBuffer
= NULL
, *pTmp
= NULL
;
436 sal_Int32 nCapacity
= 1000;
437 rtl_String
*pOut
= NULL
;
440 rtl_uString
*pEscapedCwdPath
= escape_path( pCwdPath
);
442 sal_uInt32 nArgCount
= rtl_getAppCommandArgCount();
444 rtl_uString_new_WithLength( &pBuffer
, nCapacity
);
445 rtl_uString_new( &pTmp
);
447 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
448 rtl_uString_getLength( pBuffer
),
449 RTL_CONSTASCII_STRINGPARAM( "InternalIPC::Arguments" ) );
451 if ( rtl_uString_getLength( pEscapedCwdPath
) )
453 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
454 rtl_uString_getLength( pBuffer
),
455 RTL_CONSTASCII_STRINGPARAM( "1" ) );
456 rtl_uStringbuffer_insert( &pBuffer
, &nCapacity
,
457 rtl_uString_getLength( pBuffer
),
458 rtl_uString_getStr( pEscapedCwdPath
),
459 rtl_uString_getLength( pEscapedCwdPath
) );
463 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
464 rtl_uString_getLength( pBuffer
),
465 RTL_CONSTASCII_STRINGPARAM( "0" ) );
468 for ( nArg
= 0; nArg
< nArgCount
; ++nArg
)
470 rtl_uString
*pEscapedTmp
= NULL
;
471 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
472 rtl_uString_getLength( pBuffer
),
475 rtl_getAppCommandArg( nArg
, &pTmp
);
477 pEscapedTmp
= escape_path( pTmp
);
479 rtl_uStringbuffer_insert( &pBuffer
, &nCapacity
,
480 rtl_uString_getLength( pBuffer
),
481 rtl_uString_getStr( pEscapedTmp
),
482 rtl_uString_getLength( pEscapedTmp
) );
484 rtl_uString_release( pEscapedTmp
);
487 ustr_debug( "Pass args", pBuffer
);
489 if ( !rtl_convertUStringToString(
490 &pOut
, rtl_uString_getStr( pBuffer
),
491 rtl_uString_getLength( pBuffer
), RTL_TEXTENCODING_UTF8
,
492 ( RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
493 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
) ) )
495 fprintf( stderr
, "ERROR: cannot convert arguments to UTF-8" );
499 nLen
= rtl_string_getLength( pOut
) + 1;
500 bResult
= ( write( fd
, rtl_string_getStr( pOut
), nLen
) == (ssize_t
) nLen
);
504 char resp
[ strlen( "InternalIPC::ProcessingDone" ) ];
505 ssize_t n
= read( fd
, resp
, SAL_N_ELEMENTS( resp
) );
506 bResult
= n
== (ssize_t
) SAL_N_ELEMENTS( resp
)
508 resp
, "InternalIPC::ProcessingDone",
509 SAL_N_ELEMENTS( resp
) )
514 rtl_uString_release( pEscapedCwdPath
);
515 rtl_uString_release( pBuffer
);
516 rtl_uString_release( pTmp
);
517 rtl_string_release( pOut
);
523 #define BUFFER_LEN 255
525 /* Read the percent to show in splash. */
526 static ProgressStatus
527 read_percent( ChildInfo
*info
, int *pPercent
)
529 static char pBuffer
[BUFFER_LEN
+ 1];
530 static char *pNext
= pBuffer
;
531 static ssize_t nRead
= 0;
537 /* from the last call */
538 int nNotProcessed
= nRead
- ( pNext
- pBuffer
);
539 if ( nNotProcessed
>= BUFFER_LEN
)
542 memmove( pBuffer
, pNext
, nNotProcessed
);
545 nRead
= read( child_info_get_status_fd (info
),
546 pBuffer
+ nNotProcessed
, BUFFER_LEN
- nNotProcessed
);
549 return ProgressContinue
;
553 nRead
+= nNotProcessed
;
554 pBuffer
[nRead
] = '\0';
559 for ( pIter
= pBuffer
; *pIter
; ++pIter
)
561 if ( *pIter
== '\n' )
568 #if OSL_DEBUG_LEVEL > 1
569 fprintf( stderr
, "Got status: %s\n", pBegin
);
571 if ( !strncasecmp( pBegin
, "end", 3 ) )
573 else if ( !strncasecmp( pBegin
, "restart", 7 ) )
574 return ProgressRestart
;
575 else if ( sscanf( pBegin
, "%d%c", pPercent
, &c
) == 2 && c
== '%' )
576 return ProgressContinue
;
578 /* unexpected - let's exit the splash to be safe */
582 /* Simple system check. */
584 system_checks( void )
589 /* check proc is mounted - lots of things fail otherwise */
590 if ( stat( "/proc/version", &buf
) != 0 )
592 fprintf( stderr
, "ERROR: /proc not mounted - LibreOffice is unlikely to work well if at all" );
598 /* re-use the pagein code */
599 extern int pagein_execute (int argc
, char **argv
);
601 static char *build_pagein_path (Args
*args
, const char *pagein_name
)
604 rtl_String
*app_path
;
606 app_path
= ustr_to_str (args
->pAppPath
);
608 RTL_CONSTASCII_LENGTH("@") + app_path
->length
+ strlen (pagein_name
) +
611 strcpy (path
+ 1, rtl_string_getStr (app_path
));
612 strcat (path
, pagein_name
);
614 rtl_string_release( app_path
);
620 exec_pagein (Args
*args
)
624 /* don't use -L - since that does a chdir that breaks relative paths */
625 argv
[0] = "dummy-pagein";
626 argv
[1] = build_pagein_path (args
, "pagein-common");
627 if (args
->pPageinType
) {
628 argv
[2] = build_pagein_path (args
, args
->pPageinType
);
632 pagein_execute (args
->pPageinType
? 3 : 2, argv
);
639 #if defined SOLAR_JAVA
641 static void extend_library_path (const char *new_element
)
643 rtl_uString
*pEnvName
=NULL
, *pOrigEnvVar
=NULL
, *pNewEnvVar
=NULL
;
644 const char *pathname
;
646 pathname
= "LIBPATH";
648 pathname
= "LD_LIBRARY_PATH";
651 rtl_uString_newFromAscii( &pEnvName
, pathname
);
652 rtl_uString_newFromAscii( &pNewEnvVar
, new_element
);
654 osl_getEnvironment( pEnvName
, &pOrigEnvVar
);
655 if (pOrigEnvVar
&& pOrigEnvVar
->length
)
657 rtl_uString
*pDelim
= NULL
;
658 rtl_uString_newFromAscii( &pDelim
, ":" );
659 rtl_uString_newConcat( &pNewEnvVar
, pNewEnvVar
, pDelim
);
660 rtl_uString_newConcat( &pNewEnvVar
, pNewEnvVar
, pOrigEnvVar
);
661 rtl_uString_release( pDelim
);
664 osl_setEnvironment( pEnvName
, pNewEnvVar
);
667 rtl_uString_release( pOrigEnvVar
);
668 rtl_uString_release( pNewEnvVar
);
669 rtl_uString_release( pEnvName
);
673 exec_javaldx (Args
*args
)
678 rtl_uString
**ppArgs
;
679 rtl_uString
*pTmp
, *pTmp2
;
681 oslProcess javaldx
= NULL
;
682 oslFileHandle fileOut
= 0;
685 ppArgs
= (rtl_uString
**)calloc( args
->nArgsEnv
+ 2, sizeof( rtl_uString
* ) );
687 for ( nArgs
= 0; nArgs
< args
->nArgsEnv
; ++nArgs
)
688 ppArgs
[nArgs
] = args
->ppArgs
[nArgs
];
690 /* Use absolute path to redirectrc */
692 rtl_uString_newFromAscii( &pTmp
, "-env:INIFILENAME=vnd.sun.star.pathname:" );
693 rtl_uString_newConcat( &pTmp
, pTmp
, args
->pAppPath
);
695 rtl_uString_newFromAscii( &pTmp2
, "redirectrc" );
696 rtl_uString_newConcat( &pTmp
, pTmp
, pTmp2
);
697 ppArgs
[nArgs
] = pTmp
;
698 rtl_uString_release (pTmp2
);
701 /* And also to javaldx */
703 rtl_uString_newFromAscii( &pApp
, "file://" );
704 rtl_uString_newConcat( &pApp
, pApp
, args
->pAppPath
);
706 rtl_uString_newFromAscii( &pTmp
, "../ure-link/bin/javaldx" );
707 rtl_uString_newConcat( &pApp
, pApp
, pTmp
);
708 rtl_uString_release( pTmp
);
710 err
= osl_executeProcess_WithRedirectedIO( pApp
, ppArgs
, nArgs
,
715 &javaldx
, // process handle
720 rtl_uString_release( ppArgs
[nArgs
-1] );
721 rtl_uString_release( pApp
);
724 if( err
!= osl_Process_E_None
)
726 fprintf (stderr
, "Warning: failed to launch javaldx - java may not function correctly\n");
728 osl_freeProcessHandle(javaldx
);
730 osl_closeFile(fileOut
);
734 sal_uInt64 bytes_read
;
736 /* Magically osl_readLine doesn't work with pipes with E_SPIPE - so be this lame instead: */
737 while (osl_readFile (fileOut
, newpath
, SAL_N_ELEMENTS (newpath
), &bytes_read
) == osl_File_E_INTR
);
739 if (bytes_read
<= 0) {
740 fprintf (stderr
, "Warning: failed to read path from javaldx\n");
742 osl_freeProcessHandle(javaldx
);
744 osl_closeFile(fileOut
);
747 newpath
[bytes_read
] = '\0';
749 if ((chomp
= strstr (newpath
, "\n")))
753 #if OSL_DEBUG_LEVEL > 1
754 fprintf (stderr
, "Adding javaldx path of '%s'\n", newpath
);
756 extend_library_path (newpath
);
759 osl_freeProcessHandle(javaldx
);
761 osl_closeFile(fileOut
);
766 // has to be a global :(
767 oslProcess
* volatile g_pProcess
= 0;
769 void sigterm_handler(int ignored
)
774 // forward signal to soffice.bin
775 osl_terminateProcess(g_pProcess
);
781 SAL_IMPLEMENT_MAIN_WITH_ARGS( argc
, argv
)
784 sal_Bool bSentArgs
= sal_False
;
785 const char* pUsePlugin
;
786 rtl_uString
*pPipePath
= NULL
;
789 struct splash
* splash
= NULL
;
790 struct sigaction sigpipe_action
;
791 struct sigaction sigterm_action
;
793 /* turn SIGPIPE into an error */
794 memset(&sigpipe_action
, 0, sizeof(struct sigaction
));
795 sigpipe_action
.sa_handler
= SIG_IGN
;
796 sigemptyset(&sigpipe_action
.sa_mask
);
797 sigaction(SIGPIPE
, &sigpipe_action
, 0);
798 memset(&sigterm_action
, 0, sizeof(struct sigaction
));
799 sigterm_action
.sa_handler
= &sigterm_handler
;
800 sigemptyset(&sigterm_action
.sa_mask
);
801 sigaction(SIGTERM
, &sigterm_action
, 0);
803 args
= args_parse ();
804 args
->pAppPath
= get_app_path( argv
[0] );
805 if ( !args
->pAppPath
)
807 fprintf( stderr
, "ERROR: Can't read app link\n" );
810 ustr_debug( "App path", args
->pAppPath
);
812 #ifndef ENABLE_QUICKSTART_LIBPNG
813 /* we can't load and render it anyway */
814 args
->bInhibitSplash
= sal_True
;
817 pUsePlugin
= getenv( "SAL_USE_VCLPLUGIN" );
818 if ( pUsePlugin
&& !strcmp(pUsePlugin
, "svp") )
819 args
->bInhibitSplash
= sal_True
;
821 if ( !args
->bInhibitPipe
)
823 pPipePath
= get_pipe_path( args
->pAppPath
);
825 if ( ( fd
= connect_pipe( pPipePath
) ) >= 0 )
828 char resp
[ strlen( "InternalIPC::SendArguments" ) + 1];
829 ssize_t n
= read( fd
, resp
, SAL_N_ELEMENTS( resp
) );
830 if (n
== (ssize_t
) SAL_N_ELEMENTS( resp
)
832 resp
, "InternalIPC::SendArguments",
833 SAL_N_ELEMENTS( resp
) - 1) == 0)) {
834 rtl_uString
*pCwdPath
= NULL
;
835 osl_getProcessWorkingDir( &pCwdPath
);
838 bSentArgs
= send_args( fd
, pCwdPath
);
843 #if OSL_DEBUG_LEVEL > 1
845 ustr_debug( "Failed to connect to pipe", pPipePath
);
851 /* we have to prepare for, and exec the binary */
854 sal_Bool bAllArgs
= sal_True
;
855 sal_Bool bShortWait
, bRestart
;
857 /* sanity check pieces */
860 /* load splash image and create window */
861 if ( !args
->bInhibitSplash
)
863 splash
= splash_create(args
->pAppPath
, argc
, argv
);
867 if (!args
->bInhibitPagein
)
872 if (!args
->bInhibitJavaLdx
)
878 bRestart
= sal_False
;
880 /* fast updates if we have somewhere to update it to */
881 bShortWait
= splash
? sal_True
: sal_False
;
883 /* Periodically update the splash & the percent according
884 to what status_fd says, poll quickly only while starting */
885 info
= child_spawn (args
, bAllArgs
, bShortWait
);
886 g_pProcess
= info
->child
;
887 while (!child_exited_wait (info
, bShortWait
))
889 ProgressStatus eResult
;
891 splash_draw_progress( splash
, nPercent
);
892 eResult
= read_percent( info
, &nPercent
);
893 if (eResult
!= ProgressContinue
)
895 splash_destroy(splash
);
897 bShortWait
= sal_False
;
900 #if OSL_DEBUG_LEVEL > 1
901 fprintf( stderr
, "Polling, result is %s\n",
902 ( eResult
== ProgressContinue
)? "continue" :
903 ( ( eResult
== ProgressRestart
)? "restart" : "exit" ) );
907 #if OSL_DEBUG_LEVEL > 0
908 fprintf (stderr
, "Exited with code '%d'\n", child_get_exit_code (info
));
911 status
= child_get_exit_code(info
);
912 g_pProcess
= 0; // reset
914 case EXITHELPER_CRASH_WITH_RESTART
: // re-start with just -env: parameters
915 #if OSL_DEBUG_LEVEL > 0
916 fprintf (stderr
, "oosplash: re-start with just -env: params !\n");
919 bAllArgs
= sal_False
;
921 case EXITHELPER_NORMAL_RESTART
: // re-start with all arguments
922 #if OSL_DEBUG_LEVEL > 0
923 fprintf (stderr
, "oosplash: re-start with all params !\n");
932 child_info_destroy (info
);
938 rtl_uString_release( pPipePath
);
944 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */