merge the formfield patch from ooo-build
[ooovba.git] / desktop / unx / source / start.c
blobdb99293f361ffe340d26668f7fe60c58f6cb7205
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile$
7 * $Revision: 9695 $
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,
32 * MA 02111-1307 USA
34 ************************************************************************/
36 #include <signal.h>
37 #include <unistd.h>
38 #include <limits.h>
39 #include <stdlib.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <sys/socket.h>
43 #include <arpa/inet.h>
44 #include <sys/un.h>
45 #include <sys/poll.h>
46 #include <fcntl.h>
47 #include <stdio.h>
48 #include <libgen.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>
56 #include <sal/main.h>
58 #include "splashx.h"
59 #include <introbmpnames.hxx>
61 #define PIPEDEFAULTPATH "/tmp"
62 #define PIPEALTERNATEPATH "/var/tmp"
64 /* Easier conversions: rtl_uString to rtl_String */
65 static 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 );
73 return pOut;
76 /* Easier conversions: char * to rtl_uString */
77 static 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 );
84 return pOut;
87 /* Easier debugging of rtl_uString values. */
88 #if OSL_DEBUG_LEVEL > 0
89 static void
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 );
97 return;
99 #else
100 #define ustr_debug( a, b ) {}
101 #endif
103 /* Path of the application. */
104 static rtl_uString *
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 );
115 free( pPath );
117 return pResult;
120 /* Compute the OOo md5 hash from 'pText' */
121 static rtl_uString *
122 get_md5hash( rtl_uString *pText )
124 rtl_uString *pResult = NULL;
125 sal_Int32 nCapacity = 100;
127 if ( !pText )
128 return NULL;
130 unsigned char *pData = (unsigned char *)rtl_uString_getStr( pText );
131 sal_uInt32 nSize = rtl_uString_getLength( pText ) * sizeof( sal_Unicode );
132 if ( !pData )
133 return NULL;
135 rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
136 if ( digest == 0 )
137 return NULL;
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 );
150 sal_uInt32 i = 0;
151 for ( ; i < md5_key_len; ++i )
153 char val[3];
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 ) );
160 /* cleanup */
161 free( md5_buf );
163 return pResult;
166 /* Construct the pipe name */
167 static rtl_uString *
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 );
194 if ( !pMd5hash )
195 rtl_uString_new( &pMd5hash );
197 if ( access( PIPEDEFAULTPATH, R_OK|W_OK ) == 0 )
198 rtl_uString_newFromAscii( &pResult, PIPEDEFAULTPATH );
199 else
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 );
217 /* cleanup */
218 rtl_uString_release( pPath );
219 rtl_uString_release( pTmp );
220 rtl_uString_release( pUserInstallation );
222 return pResult;
225 /* Get fd of the pipe of the already running OOo. */
226 static int
227 connect_pipe( rtl_uString *pPipePath )
229 int fd;
230 size_t len;
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 )
238 return fd;
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 */
247 #if defined(FREEBSD)
248 len = SUN_LEN( &addr );
249 #else
250 len = sizeof( addr );
251 #endif
253 if ( connect( fd, (struct sockaddr *)&addr, len ) < 0 )
254 return -1;
256 return fd;
259 /* Escape: "," -> "\\,", "\0" -> "\\0", "\\" -> "\\\\" */
260 static rtl_uString *
261 escape_path( rtl_uString *pToEscape )
263 rtl_uString *pBuffer = NULL;
264 sal_Int32 nCapacity = 1000;
266 rtl_uString_new_WithLength( &pBuffer, nCapacity );
268 sal_Int32 i = 0;
269 sal_Int32 nEscapeLength = rtl_uString_getLength( pToEscape );
270 for ( ; i < nEscapeLength; ++i )
272 sal_Unicode c = pToEscape->buffer[i];
273 switch ( c )
275 case (sal_Unicode)'\0':
276 rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
277 rtl_uString_getLength( pBuffer ),
278 RTL_CONSTASCII_STRINGPARAM( "\\0" ) );
279 break;
280 case (sal_Unicode)',':
281 rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
282 rtl_uString_getLength( pBuffer ),
283 RTL_CONSTASCII_STRINGPARAM( "\\," ) );
284 break;
285 case (sal_Unicode)'\\':
286 rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
287 rtl_uString_getLength( pBuffer ),
288 RTL_CONSTASCII_STRINGPARAM( "\\\\" ) );
289 break;
290 default:
291 rtl_uStringbuffer_insert( &pBuffer, &nCapacity,
292 rtl_uString_getLength( pBuffer ),
293 &c, 1 );
297 return pBuffer;
300 /* Send args to the OOo instance (using the 'fd' file descriptor) */
301 static sal_Bool
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;
307 sal_Bool bResult;
308 size_t nLen;
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 ) );
328 else
329 rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity,
330 rtl_uString_getLength( pBuffer ),
331 RTL_CONSTASCII_STRINGPARAM( "0" ) );
333 sal_Bool bDontConvertNext = sal_False;
334 sal_uInt32 nArg;
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 ),
340 ",", 1 );
342 osl_getCommandArg( nArg, &pTmp );
344 if ( rtl_uString_getLength( pTmp ) == 0 )
345 continue;
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 );
386 /* cleanup */
387 rtl_uString_release( pEscapedCwdPath );
388 rtl_uString_release( pBuffer );
389 rtl_uString_release( pTmp );
390 rtl_string_release( pOut );
392 return bResult;
395 /* Load the splash bitmap. */
396 static void
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;
404 /* setup values */
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 );
426 if ( bLoaded )
427 break;
431 /* cleanup */
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 */
441 static void
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;
446 int i = 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 );
466 /* cleanup */
467 rtl_uString_release( pKey );
468 rtl_uString_release( pValue );
471 /* Load the colors and size of the splash. */
472 static void
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 },
492 pos[2] = { -1, -1 },
493 size[2] = { -1, -1 };
495 /* get the values */
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" );
502 if ( logo[0] == 0 )
503 *pInhibitSplash = sal_True;
505 splash_setup( bar, frame, pos[0], pos[1], size[0], size[1] );
507 /* cleanup */
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. */
516 static sal_Bool
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;
523 char *pBegin;
524 char *pIter;
526 /* from the last call */
527 int nNotProcessed = nRead - ( pNext - pBuffer );
528 if ( nNotProcessed >= BUFFER_LEN )
529 return sal_False;
531 memmove( pBuffer, pNext, nNotProcessed );
533 /* read data */
534 nRead = read( status_fd, pBuffer + nNotProcessed, BUFFER_LEN - nNotProcessed );
535 if ( nRead < 0 )
536 return sal_False;
538 nRead += nNotProcessed;
539 pBuffer[nRead] = '\0';
541 /* skip old data */
542 pBegin = pBuffer;
543 pNext = pBuffer;
544 for ( pIter = pBuffer; *pIter; ++pIter )
545 if ( *pIter == '\n' )
547 pBegin = pNext;
548 pNext = pIter + 1;
551 #if OSL_DEBUG_LEVEL > 0
552 fprintf( stderr, "Got status: %s\n", pBegin );
553 #endif
554 if ( !strncasecmp( pBegin, "end", 3 ) )
555 return sal_False;
556 else if ( sscanf( pBegin, "%d%%", pPercent ) )
557 return sal_True;
559 return sal_False;
562 /* Periodically update the splash & the percent acconding to what
563 status_fd says */
564 static void
565 show_splash( int status_fd )
567 int nRetval;
568 struct pollfd aPfd;
570 int nPercent = 0;
571 sal_Bool bFinish = sal_False;
573 /* we want to watch status_fd */
574 aPfd.fd = status_fd;
575 aPfd.events = POLLIN;
577 #if OSL_DEBUG_LEVEL > 0
578 fprintf( stderr, "Starting main loop, status fd: %d\n", status_fd );
579 #endif
581 /* main loop */
582 do {
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 ) )
588 bFinish = sal_True;
589 else if ( nRetval > 0 )
590 bFinish = !read_percent( status_fd, &nPercent );
591 else if ( nRetval < 0 )
592 bFinish = sal_True;
593 } while ( !bFinish );
596 /* Simple system check. */
597 static void
598 system_checks( void )
600 #ifdef LINUX
601 struct stat buf;
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" );
607 exit( 1 );
609 #endif
612 /* Start the OOo application */
613 static sal_Bool
614 fork_app( rtl_uString *pAppPath, int *status_fd )
616 rtl_uString *pApp = NULL, *pTmp = NULL, *pArg = NULL;
617 rtl_uString **ppArgs;
618 sal_uInt32 nArgs, i;
620 oslProcess aProcess;
621 oslProcessError nError;
622 int status_pipe[2];
624 system_checks();
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 );
634 /* copy args */
635 nArgs = osl_getCommandArgCount();
636 ppArgs = (rtl_uString **)calloc( nArgs + 1, sizeof( rtl_uString* ) );
637 for ( i = 0; i < nArgs; ++i )
639 ppArgs[i] = NULL;
640 osl_getCommandArg( i, &pTmp );
642 rtl_uString_newFromString( &(ppArgs[i]), pTmp );
645 /* create pipe */
646 if ( pipe( status_pipe ) < 0 )
648 fprintf( stderr, "ERROR: no file handles\n");
649 exit( 1 );
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 );
662 ++nArgs;
664 /* start the OOo process */
665 nError = osl_executeProcess( pApp, ppArgs, nArgs,
666 osl_Process_DETACHED | osl_Process_NORMAL,
667 NULL,
668 NULL,
669 NULL, 0,
670 &aProcess );
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 );
679 return sal_False;
682 return sal_True;
685 /* Check if 'pArg' is -pCmpWith or --pCmpWith */
686 static sal_Bool
687 arg_check( rtl_uString *pArg, const char *pCmpWith )
689 sal_Unicode *pUnicode = rtl_uString_getStr( pArg );
691 if ( pUnicode[0] == (sal_Unicode)'-' )
692 pUnicode++;
693 else
694 return sal_False;
696 /* tolerate -- prefixes etc. */
697 if ( pUnicode[0] == (sal_Unicode)'-' )
698 pUnicode++;
700 return !rtl_ustr_ascii_compare( pUnicode, pCmpWith );
703 static const char *ppInhibit[] = {
704 "nologo", "headless", "invisible", "help", "h", "?", "minimized",
705 NULL };
706 static const char *ppTwoArgs[] = {
707 "pt", "display",
708 NULL };
710 /* Read command line parameters and return whether we display the splash. */
711 static sal_Bool
712 get_inhibit_splash()
714 rtl_uString *pTmp = NULL;
715 sal_Bool bSkipNextArg = sal_False;
716 const char **ppIter;
718 rtl_uString_new( &pTmp );
720 sal_uInt32 nArg;
721 sal_uInt32 nArgCount = osl_getCommandArgCount();
722 for ( nArg = 0; nArg < nArgCount; ++nArg )
724 if ( bSkipNextArg )
726 bSkipNextArg = sal_False;
727 continue;
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 );
738 return sal_True;
741 /* check for 2 arguments params */
742 for ( ppIter = ppTwoArgs; *ppIter; ++ppIter )
744 if ( arg_check( pTmp, *ppIter ) )
746 bSkipNextArg = sal_True;
747 break;
752 /* cleanup */
753 rtl_uString_release( pTmp );
755 return sal_False;
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] );
772 if ( !pAppPath )
774 fprintf( stderr, "ERROR: Can't read app link\n" );
775 exit( 1 );
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
789 else
790 ustr_debug( "Failed to connect to pipe", pPipePath );
791 #endif
793 if ( !bSentArgs )
795 if ( !fork_app( pAppPath, &status_fd ) )
796 return 1;
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();
812 /* cleanup */
813 rtl_uString_release( pAppPath );
814 rtl_uString_release( pPipePath );
816 close( fd );
817 close( status_fd );
819 return 0;