1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
9 * last change: $Author: jholesovsky $ $Date: 2007-07-03 16:36:09 +0200 (Út, 03 čec 2007) $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 ************************************************************************/
40 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <arpa/inet.h>
50 #include <osl/nlsupport.h>
51 #include <osl/process.h>
52 #include <osl/thread.h>
53 #include <rtl/bootstrap.h>
54 #include <rtl/digest.h>
55 #include <rtl/ustrbuf.h>
59 #include <introbmpnames.hxx>
61 #define PIPEDEFAULTPATH "/tmp"
62 #define PIPEALTERNATEPATH "/var/tmp"
64 /* Easier conversions: rtl_uString to rtl_String */
66 ustr_to_str( rtl_uString
*pStr
)
68 rtl_String
*pOut
= NULL
;
70 rtl_uString2String( &pOut
, rtl_uString_getStr( pStr
),
71 rtl_uString_getLength( pStr
), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS
);
76 /* Easier conversions: char * to rtl_uString */
78 charp_to_ustr( const char *pStr
)
80 rtl_uString
*pOut
= NULL
;
82 rtl_string2UString( &pOut
, pStr
, strlen( pStr
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
87 /* Easier debugging of rtl_uString values. */
88 #if OSL_DEBUG_LEVEL > 0
90 ustr_debug( const char *pMessage
, rtl_uString
*pStr
)
92 rtl_String
*pOut
= ustr_to_str( pStr
);
94 fprintf( stderr
, "%s: %s\n", pMessage
, rtl_string_getStr( pOut
) );
96 rtl_string_release( pOut
);
100 #define ustr_debug( a, b ) {}
103 /* Path of the application. */
105 get_app_path( const char *pAppExec
)
107 char pRealPath
[PATH_MAX
];
108 rtl_uString
*pResult
;
110 char *pPath
= strdup( pAppExec
);
111 pPath
= dirname( pPath
);
113 realpath( pPath
, pRealPath
);
114 pResult
= charp_to_ustr( pRealPath
);
120 /* Compute the OOo md5 hash from 'pText' */
122 get_md5hash( rtl_uString
*pText
)
124 rtl_uString
*pResult
= NULL
;
125 sal_Int32 nCapacity
= 100;
130 unsigned char *pData
= (unsigned char *)rtl_uString_getStr( pText
);
131 sal_uInt32 nSize
= rtl_uString_getLength( pText
) * sizeof( sal_Unicode
);
135 rtlDigest digest
= rtl_digest_create( rtl_Digest_AlgorithmMD5
);
139 sal_uInt32 md5_key_len
= rtl_digest_queryLength( digest
);
140 sal_uInt8
*md5_buf
= (sal_uInt8
*)calloc( md5_key_len
, sizeof( sal_uInt8
) );
142 rtl_digest_init( digest
, pData
, nSize
);
143 rtl_digest_update( digest
, pData
, nSize
);
144 rtl_digest_get( digest
, md5_buf
, md5_key_len
);
145 rtl_digest_destroy( digest
);
147 /* create hex-value string from the MD5 value to keep
148 the string size minimal */
149 rtl_uString_new_WithLength( &pResult
, nCapacity
);
151 for ( ; i
< md5_key_len
; ++i
)
154 snprintf( val
, 3, "%x", md5_buf
[i
] ); /* sic! we ignore some of the 0's */
156 rtl_uStringbuffer_insert_ascii( &pResult
, &nCapacity
, rtl_uString_getLength( pResult
),
157 val
, strlen( val
) );
166 /* Construct the pipe name */
168 get_pipe_path( rtl_uString
*pAppPath
)
170 rtl_uString
*pPath
= NULL
, *pTmp
= NULL
, *pUserInstallation
= NULL
;
171 rtl_uString
*pResult
= NULL
;
173 /* setup bootstrap filename */
174 rtl_uString_newFromAscii( &pPath
, "file://" );
175 rtl_uString_newConcat( &pPath
, pPath
, pAppPath
);
176 rtl_uString_newFromAscii( &pTmp
, "/" );
177 rtl_uString_newConcat( &pPath
, pPath
, pTmp
);
178 rtl_uString_newFromAscii( &pTmp
, SAL_CONFIGFILE( "bootstrap" ) );
179 rtl_uString_newConcat( &pPath
, pPath
, pTmp
);
181 ustr_debug( "bootstap", pPath
);
183 /* read userinstallation value */
184 rtlBootstrapHandle handle
= rtl_bootstrap_args_open( pPath
);
186 rtl_uString_newFromAscii( &pTmp
, "UserInstallation" );
187 rtl_bootstrap_get_from_handle( handle
, pTmp
, &pUserInstallation
, NULL
);
189 rtl_bootstrap_args_close( handle
);
191 /* create the pipe name */
192 ustr_debug( "user installation", pUserInstallation
);
193 rtl_uString
*pMd5hash
= get_md5hash( pUserInstallation
);
195 rtl_uString_new( &pMd5hash
);
197 if ( access( PIPEDEFAULTPATH
, R_OK
|W_OK
) == 0 )
198 rtl_uString_newFromAscii( &pResult
, PIPEDEFAULTPATH
);
200 rtl_uString_newFromAscii( &pResult
, PIPEALTERNATEPATH
);
202 rtl_uString_newFromAscii( &pTmp
, "/OSL_PIPE_" );
203 rtl_uString_newConcat( &pResult
, pResult
, pTmp
);
205 sal_Unicode pUnicode
[RTL_USTR_MAX_VALUEOFINT32
];
206 rtl_ustr_valueOfInt32( pUnicode
, (int)getuid(), 10 );
207 rtl_uString_newFromStr( &pTmp
, pUnicode
);
208 rtl_uString_newConcat( &pResult
, pResult
, pTmp
);
210 rtl_uString_newFromAscii( &pTmp
, "_SingleOfficeIPC_" );
211 rtl_uString_newConcat( &pResult
, pResult
, pTmp
);
213 rtl_uString_newConcat( &pResult
, pResult
, pMd5hash
);
215 ustr_debug( "result", pResult
);
218 rtl_uString_release( pPath
);
219 rtl_uString_release( pTmp
);
220 rtl_uString_release( pUserInstallation
);
225 /* Get fd of the pipe of the already running OOo. */
227 connect_pipe( rtl_uString
*pPipePath
)
231 struct sockaddr_un addr
;
233 rtl_String
*pPipeStr
= ustr_to_str( pPipePath
);
235 memset( &addr
, 0, sizeof( addr
) );
237 if ( ( fd
= socket( AF_UNIX
, SOCK_STREAM
, 0 ) ) < 0 )
240 fcntl( fd
, F_SETFD
, FD_CLOEXEC
);
242 addr
.sun_family
= AF_UNIX
;
243 strncpy( addr
.sun_path
, rtl_string_getStr( pPipeStr
), sizeof( addr
.sun_path
) );
244 rtl_string_release( pPipeStr
);
246 /* cut / paste from osl's pipe.c */
248 len
= SUN_LEN( &addr
);
250 len
= sizeof( addr
);
253 if ( connect( fd
, (struct sockaddr
*)&addr
, len
) < 0 )
259 /* Escape: "," -> "\\,", "\0" -> "\\0", "\\" -> "\\\\" */
261 escape_path( rtl_uString
*pToEscape
)
263 rtl_uString
*pBuffer
= NULL
;
264 sal_Int32 nCapacity
= 1000;
266 rtl_uString_new_WithLength( &pBuffer
, nCapacity
);
269 sal_Int32 nEscapeLength
= rtl_uString_getLength( pToEscape
);
270 for ( ; i
< nEscapeLength
; ++i
)
272 sal_Unicode c
= pToEscape
->buffer
[i
];
275 case (sal_Unicode
)'\0':
276 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
277 rtl_uString_getLength( pBuffer
),
278 RTL_CONSTASCII_STRINGPARAM( "\\0" ) );
280 case (sal_Unicode
)',':
281 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
282 rtl_uString_getLength( pBuffer
),
283 RTL_CONSTASCII_STRINGPARAM( "\\," ) );
285 case (sal_Unicode
)'\\':
286 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
287 rtl_uString_getLength( pBuffer
),
288 RTL_CONSTASCII_STRINGPARAM( "\\\\" ) );
291 rtl_uStringbuffer_insert( &pBuffer
, &nCapacity
,
292 rtl_uString_getLength( pBuffer
),
300 /* Send args to the OOo instance (using the 'fd' file descriptor) */
302 send_args( int fd
, rtl_uString
*pCwdPath
)
304 rtl_uString
*pBuffer
= NULL
, *pTmp
= NULL
;
305 sal_Int32 nCapacity
= 1000;
306 rtl_String
*pOut
= NULL
;
309 rtl_uString
*pEscapedCwdPath
= escape_path( pCwdPath
);
311 rtl_uString_new_WithLength( &pBuffer
, nCapacity
);
312 rtl_uString_new( &pTmp
);
314 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
315 rtl_uString_getLength( pBuffer
),
316 RTL_CONSTASCII_STRINGPARAM( "InternalIPC::Arguments" ) );
318 if ( rtl_uString_getLength( pEscapedCwdPath
) )
320 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
321 rtl_uString_getLength( pBuffer
),
322 RTL_CONSTASCII_STRINGPARAM( "1" ) );
323 rtl_uStringbuffer_insert( &pBuffer
, &nCapacity
,
324 rtl_uString_getLength( pBuffer
),
325 rtl_uString_getStr( pEscapedCwdPath
),
326 rtl_uString_getLength( pEscapedCwdPath
) );
329 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
330 rtl_uString_getLength( pBuffer
),
331 RTL_CONSTASCII_STRINGPARAM( "0" ) );
333 sal_Bool bDontConvertNext
= sal_False
;
335 sal_uInt32 nArgCount
= osl_getCommandArgCount();
336 for ( nArg
= 0; nArg
< nArgCount
; ++nArg
)
338 rtl_uStringbuffer_insert_ascii( &pBuffer
, &nCapacity
,
339 rtl_uString_getLength( pBuffer
),
342 osl_getCommandArg( nArg
, &pTmp
);
344 if ( rtl_uString_getLength( pTmp
) == 0 )
347 // this is not a param, we have to prepend filenames with file://
348 // FIXME: improve the check
349 if ( ( pTmp
->buffer
[0] != (sal_Unicode
)'-' ) &&
350 ( rtl_ustr_indexOfAscii_WithLength( pTmp
->buffer
, pTmp
->length
, "slot:", 5 /* length */ ) ) )
352 sal_Int32 nFirstColon
= rtl_ustr_indexOfChar_WithLength( pTmp
->buffer
, pTmp
->length
, ':' );
353 sal_Int32 nFirstSlash
= rtl_ustr_indexOfChar_WithLength( pTmp
->buffer
, pTmp
->length
, '/' );
355 // check that pTmp is not an URI yet
356 if ( nFirstColon
< 1 || ( nFirstSlash
!= nFirstColon
+ 1 ) )
358 // some of the switches (currently just -pt) don't want to
359 // have the filenames as URIs
360 if ( !bDontConvertNext
)
361 osl_getAbsoluteFileURL( pCwdPath
, pTmp
, &pTmp
);
365 // don't convert filenames with some of the switches
366 // (currently just -pt)
367 bDontConvertNext
= !rtl_ustr_ascii_compareIgnoreAsciiCase( pTmp
->buffer
, "-pt" );
369 rtl_uString
*pEscapedTmp
= escape_path( pTmp
);
371 rtl_uStringbuffer_insert( &pBuffer
, &nCapacity
,
372 rtl_uString_getLength( pBuffer
),
373 rtl_uString_getStr( pEscapedTmp
),
374 rtl_uString_getLength( pEscapedTmp
) );
376 rtl_uString_release( pEscapedTmp
);
379 ustr_debug( "Pass args", pBuffer
);
381 pOut
= ustr_to_str( pBuffer
);
383 nLen
= rtl_string_getLength( pOut
) + 1;
384 bResult
= ( write( fd
, rtl_string_getStr( pOut
), nLen
) == (ssize_t
) nLen
);
387 rtl_uString_release( pEscapedCwdPath
);
388 rtl_uString_release( pBuffer
);
389 rtl_uString_release( pTmp
);
390 rtl_string_release( pOut
);
395 /* Load the splash bitmap. */
397 load_splash_image( rtl_uString
*pImagePath
)
399 rtl_uString
*pPath
= NULL
, *pBitmaps
= NULL
, *pTmp
= NULL
;
400 rtl_uString
*pToken
= NULL
, *pFilename
= NULL
;
402 sal_Int32 nIndex
= 0;
405 rtl_uString_newFromString( &pPath
, pImagePath
);
406 rtl_uString_newFromAscii( &pTmp
, "/" );
407 rtl_uString_newConcat( &pPath
, pPath
, pTmp
);
409 rtl_uString_newFromAscii( &pBitmaps
, INTRO_BITMAP_STRINGLIST
);
410 rtl_uString_newFromAscii( &pTmp
, ",intro.bmp" );
411 rtl_uString_newConcat( &pBitmaps
, pBitmaps
, pTmp
);
413 /* try all the bitmaps from INTRO_BITMAP_STRINGLIST
414 (and the intro.bmp fallback) */
415 while ( nIndex
>= 0 )
417 nIndex
= rtl_uString_getToken( &pToken
, pBitmaps
, 0, ',', nIndex
);
418 rtl_uString_newConcat( &pFilename
, pPath
, pToken
);
420 if ( rtl_uString_getLength( pToken
) > 0 )
422 rtl_String
*pFilenameStr
= ustr_to_str( pFilename
);
423 sal_Bool bLoaded
= splash_load_bmp( rtl_string_getStr( pFilenameStr
) );
424 rtl_string_release( pFilenameStr
);
432 rtl_uString_release( pPath
);
433 rtl_uString_release( pBitmaps
);
434 rtl_uString_release( pTmp
);
435 rtl_uString_release( pToken
);
436 rtl_uString_release( pFilename
);
439 /* Fill 'array' with values of the key 'name'.
440 Its value is a comma delimited list of integers */
442 get_bootstrap_value( int *array
, int size
, rtlBootstrapHandle handle
, const char *name
)
444 rtl_uString
*pKey
= NULL
, *pValue
= NULL
;
445 sal_Int32 nIndex
= 0;
448 /* get the value from the ini file */
449 rtl_uString_newFromAscii( &pKey
, name
);
450 rtl_bootstrap_get_from_handle( handle
, pKey
, &pValue
, NULL
);
452 /* the value is several numbers delimited by ',' - parse it */
453 if ( rtl_uString_getLength( pValue
) > 0 )
455 rtl_uString
*pToken
= NULL
;
457 for ( ; ( nIndex
>= 0 ) && ( i
< size
); ++i
)
459 nIndex
= rtl_uString_getToken( &pToken
, pValue
, 0, ',', nIndex
);
460 array
[i
] = rtl_ustr_toInt32( rtl_uString_getStr( pToken
), 10 );
463 rtl_uString_release( pToken
);
467 rtl_uString_release( pKey
);
468 rtl_uString_release( pValue
);
471 /* Load the colors and size of the splash. */
473 load_splash_defaults( rtl_uString
*pAppPath
, sal_Bool
*pInhibitSplash
)
475 rtl_uString
*pSettings
= NULL
, *pTmp
= NULL
;
476 rtlBootstrapHandle handle
;
478 /* costruct the sofficerc file location */
479 rtl_uString_newFromAscii( &pSettings
, "file://" );
480 rtl_uString_newConcat( &pSettings
, pSettings
, pAppPath
);
481 rtl_uString_newFromAscii( &pTmp
, "/" );
482 rtl_uString_newConcat( &pSettings
, pSettings
, pTmp
);
483 rtl_uString_newFromAscii( &pTmp
, SAL_CONFIGFILE( "soffice" ) );
484 rtl_uString_newConcat( &pSettings
, pSettings
, pTmp
);
486 /* use it as the bootstrap file */
487 handle
= rtl_bootstrap_args_open( pSettings
);
489 int logo
[1] = { -1 },
490 bar
[3] = { -1, -1, -1 },
491 frame
[3] = { -1, -1, -1 },
493 size
[2] = { -1, -1 };
496 get_bootstrap_value( logo
, 1, handle
, "Logo" );
497 get_bootstrap_value( bar
, 3, handle
, "ProgressBarColor" );
498 get_bootstrap_value( frame
, 3, handle
, "ProgressFrameColor" );
499 get_bootstrap_value( pos
, 2, handle
, "ProgressPosition" );
500 get_bootstrap_value( size
, 2, handle
, "ProgressSize" );
503 *pInhibitSplash
= sal_True
;
505 splash_setup( bar
, frame
, pos
[0], pos
[1], size
[0], size
[1] );
508 rtl_bootstrap_args_close( handle
);
509 rtl_uString_release( pSettings
);
510 rtl_uString_release( pTmp
);
513 #define BUFFER_LEN 255
515 /* Read the percent to show in splash. */
517 read_percent( int status_fd
, int *pPercent
)
519 static char pBuffer
[BUFFER_LEN
+ 1];
520 static char *pNext
= pBuffer
;
521 static ssize_t nRead
= 0;
526 /* from the last call */
527 int nNotProcessed
= nRead
- ( pNext
- pBuffer
);
528 if ( nNotProcessed
>= BUFFER_LEN
)
531 memmove( pBuffer
, pNext
, nNotProcessed
);
534 nRead
= read( status_fd
, pBuffer
+ nNotProcessed
, BUFFER_LEN
- nNotProcessed
);
538 nRead
+= nNotProcessed
;
539 pBuffer
[nRead
] = '\0';
544 for ( pIter
= pBuffer
; *pIter
; ++pIter
)
545 if ( *pIter
== '\n' )
551 #if OSL_DEBUG_LEVEL > 0
552 fprintf( stderr
, "Got status: %s\n", pBegin
);
554 if ( !strncasecmp( pBegin
, "end", 3 ) )
556 else if ( sscanf( pBegin
, "%d%%", pPercent
) )
562 /* Periodically update the splash & the percent acconding to what
565 show_splash( int status_fd
)
571 sal_Bool bFinish
= sal_False
;
573 /* we want to watch status_fd */
575 aPfd
.events
= POLLIN
;
577 #if OSL_DEBUG_LEVEL > 0
578 fprintf( stderr
, "Starting main loop, status fd: %d\n", status_fd
);
583 splash_draw_progress( nPercent
);
585 /* read from pipe if data available */
586 nRetval
= poll( &aPfd
, 1, 50 );
587 if ( aPfd
.revents
& ( POLLERR
| POLLHUP
| POLLNVAL
) )
589 else if ( nRetval
> 0 )
590 bFinish
= !read_percent( status_fd
, &nPercent
);
591 else if ( nRetval
< 0 )
593 } while ( !bFinish
);
596 /* Simple system check. */
598 system_checks( void )
603 /* check proc is mounted - lots of things fail otherwise */
604 if ( stat( "/proc/version", &buf
) != 0 )
606 fprintf( stderr
, "ERROR: /proc not mounted - OO.o is unlikely to work well if at all" );
612 /* Start the OOo application */
614 fork_app( rtl_uString
*pAppPath
, int *status_fd
)
616 rtl_uString
*pApp
= NULL
, *pTmp
= NULL
, *pArg
= NULL
;
617 rtl_uString
**ppArgs
;
621 oslProcessError nError
;
626 /* application name */
627 rtl_uString_newFromAscii( &pApp
, "file://" );
628 rtl_uString_newConcat( &pApp
, pApp
, pAppPath
);
629 rtl_uString_newFromAscii( &pTmp
, "/soffice.bin" );
630 rtl_uString_newConcat( &pApp
, pApp
, pTmp
);
632 rtl_uString_new( &pTmp
);
635 nArgs
= osl_getCommandArgCount();
636 ppArgs
= (rtl_uString
**)calloc( nArgs
+ 1, sizeof( rtl_uString
* ) );
637 for ( i
= 0; i
< nArgs
; ++i
)
640 osl_getCommandArg( i
, &pTmp
);
642 rtl_uString_newFromString( &(ppArgs
[i
]), pTmp
);
646 if ( pipe( status_pipe
) < 0 )
648 fprintf( stderr
, "ERROR: no file handles\n");
652 /* add the pipe arg */
653 sal_Unicode pUnicode
[RTL_USTR_MAX_VALUEOFINT32
];
654 rtl_ustr_valueOfInt32( pUnicode
, status_pipe
[1], 10 );
656 rtl_uString_newFromAscii( &pArg
, "-splash-pipe=" );
657 rtl_uString_newFromStr( &pTmp
, pUnicode
);
658 rtl_uString_newConcat( &pArg
, pArg
, pTmp
);
660 ppArgs
[nArgs
] = NULL
;
661 rtl_uString_newFromString( &(ppArgs
[nArgs
]), pArg
);
664 /* start the OOo process */
665 nError
= osl_executeProcess( pApp
, ppArgs
, nArgs
,
666 osl_Process_DETACHED
| osl_Process_NORMAL
,
672 *status_fd
= status_pipe
[0];
673 close( status_pipe
[1] );
675 if ( nError
!= osl_Process_E_None
)
677 fprintf( stderr
, "ERROR %d forking process", nError
);
678 ustr_debug( "", pApp
);
685 /* Check if 'pArg' is -pCmpWith or --pCmpWith */
687 arg_check( rtl_uString
*pArg
, const char *pCmpWith
)
689 sal_Unicode
*pUnicode
= rtl_uString_getStr( pArg
);
691 if ( pUnicode
[0] == (sal_Unicode
)'-' )
696 /* tolerate -- prefixes etc. */
697 if ( pUnicode
[0] == (sal_Unicode
)'-' )
700 return !rtl_ustr_ascii_compare( pUnicode
, pCmpWith
);
703 static const char *ppInhibit
[] = {
704 "nologo", "headless", "invisible", "help", "h", "?", "minimized",
706 static const char *ppTwoArgs
[] = {
710 /* Read command line parameters and return whether we display the splash. */
714 rtl_uString
*pTmp
= NULL
;
715 sal_Bool bSkipNextArg
= sal_False
;
718 rtl_uString_new( &pTmp
);
721 sal_uInt32 nArgCount
= osl_getCommandArgCount();
722 for ( nArg
= 0; nArg
< nArgCount
; ++nArg
)
726 bSkipNextArg
= sal_False
;
730 osl_getCommandArg( nArg
, &pTmp
);
732 /* check for inhibit splash params */
733 for ( ppIter
= ppInhibit
; *ppIter
; ++ppIter
)
735 if ( arg_check( pTmp
, *ppIter
) )
737 rtl_uString_release( pTmp
);
741 /* check for 2 arguments params */
742 for ( ppIter
= ppTwoArgs
; *ppIter
; ++ppIter
)
744 if ( arg_check( pTmp
, *ppIter
) )
746 bSkipNextArg
= sal_True
;
753 rtl_uString_release( pTmp
);
758 SAL_IMPLEMENT_MAIN_WITH_ARGS( argc
, argv
)
760 int fd
= 0, status_fd
= 0;
761 sal_Bool bInhibitSplash
;
762 sal_Bool bSentArgs
= sal_False
;
763 rtl_uString
*pAppPath
= NULL
;
764 rtl_uString
*pPipePath
= NULL
;
766 /* turn SIGPIPE into an error */
767 signal( SIGPIPE
, SIG_IGN
);
769 bInhibitSplash
= get_inhibit_splash();
771 pAppPath
= get_app_path( argv
[0] );
774 fprintf( stderr
, "ERROR: Can't read app link\n" );
777 ustr_debug( "App path", pAppPath
);
779 pPipePath
= get_pipe_path( pAppPath
);
781 if ( ( fd
= connect_pipe( pPipePath
) ) >= 0 )
783 rtl_uString
*pCwdPath
= NULL
;
784 osl_getProcessWorkingDir( &pCwdPath
);
786 bSentArgs
= send_args( fd
, pCwdPath
);
788 #if OSL_DEBUG_LEVEL > 0
790 ustr_debug( "Failed to connect to pipe", pPipePath
);
795 if ( !fork_app( pAppPath
, &status_fd
) )
798 if ( !bInhibitSplash
)
800 load_splash_image( pAppPath
);
801 load_splash_defaults( pAppPath
, &bInhibitSplash
);
804 if ( !bInhibitSplash
&& splash_create_window( argc
, argv
) )
806 splash_draw_progress( 0 );
807 show_splash( status_fd
);
808 splash_close_window();
813 rtl_uString_release( pAppPath
);
814 rtl_uString_release( pPipePath
);