View | Details | Raw Unified | Return to issue 60696
Collapse All | Expand All

(-)desktop/source/splash/splash.hxx (+5 lines)
Lines 33-38 Link Here
33
 *
33
 *
34
 ************************************************************************/
34
 ************************************************************************/
35
35
36
#include <stdio.h>
37
36
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
38
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
37
#include <com/sun/star/lang/XServiceInfo.hpp>
39
#include <com/sun/star/lang/XServiceInfo.hpp>
38
#endif
40
#endif
Lines 113-122 private: Link Here
113
	sal_Bool _bPaintBitmap;
115
	sal_Bool _bPaintBitmap;
114
	sal_Bool _bPaintProgress;
116
	sal_Bool _bPaintProgress;
115
	sal_Bool _bVisible;
117
	sal_Bool _bVisible;
118
	FILE *_outFd;
116
	long _height, _width, _tlx, _tly, _barwidth;
119
	long _height, _width, _tlx, _tly, _barwidth;
117
    long _barheight, _barspace;
120
    long _barheight, _barspace;
118
    const long _xoffset, _yoffset;
121
    const long _xoffset, _yoffset;
119
122
123
	bool doRender() { return _outFd == NULL; };
124
120
public:
125
public:
121
    static const char* interfaces[];
126
    static const char* interfaces[];
122
	static const sal_Char *serviceName;
127
	static const sal_Char *serviceName;
(-)desktop/source/splash/splash.cxx (-4 / +45 lines)
Lines 82-92 SplashScreen::SplashScreen(const Referen Link Here
82
	, _yoffset(18)
85
	, _yoffset(18)
83
    , _barheight(-1)
86
    , _barheight(-1)
84
    , _barspace(2)
87
    , _barspace(2)
88
    , _bVisible( FALSE )
89
    , _outFd(NULL)
85
{
90
{
86
	_rFactory = rSMgr;
91
	_rFactory = rSMgr;
87
92
88
    loadConfig();
93
#ifdef UNX
89
	initBitmap();
94
	::vos::OStartupInfo aInfo;
95
#define PIPE_ARG "-splash-pipe="
96
	for (sal_uInt32 i = 0; i < aInfo.getCommandArgCount(); i++)
97
	{
98
		rtl::OUString aArg;
99
		if (aInfo.getCommandArg (i, aArg))
100
		    break;
101
		if (aArg.matchIgnoreAsciiCaseAsciiL (PIPE_ARG, sizeof (PIPE_ARG) - 1, 0))
102
		{
103
			OUString aNum = aArg.copy (sizeof (PIPE_ARG) - 1);
104
			int fd = aNum.toInt32();
105
			_outFd = fdopen (fd, "w");
106
/*			fprintf (stderr, "Got argument '-splash-pipe=%d ('%s') (%p)\n",
107
					 fd, (const sal_Char *)rtl::OUStringToOString (aNum, RTL_TEXTENCODING_UTF8),
108
					 _outFd); */
109
		}
110
	}
111
#endif
112
113
	if (!doRender())
114
		return;
115
90
	Size aSize = _aIntroBmp.GetSizePixel();
116
	Size aSize = _aIntroBmp.GetSizePixel();
91
	SetOutputSizePixel( aSize );
117
	SetOutputSizePixel( aSize );
92
    _vdev.SetOutputSizePixel( aSize );
118
    _vdev.SetOutputSizePixel( aSize );
Lines 139-147 SplashScreen::SplashScreen(const Referen Link Here
139
165
140
SplashScreen::~SplashScreen()
166
SplashScreen::~SplashScreen()
141
{
167
{
168
	if (!doRender())
169
		return;
142
	Application::RemoveEventListener(
170
	Application::RemoveEventListener(
143
		LINK( this, SplashScreen, AppEventListenerHdl ) );
171
		LINK( this, SplashScreen, AppEventListenerHdl ) );
144
	Hide();
172
	if (_bVisible) Hide();
145
}
173
}
146
174
147
void SAL_CALL SplashScreen::start(const OUString& aText, sal_Int32 nRange)
175
void SAL_CALL SplashScreen::start(const OUString& aText, sal_Int32 nRange)
Lines 160-165 void SAL_CALL SplashScreen::end() Link Here
160
	_iProgress = _iMax;
188
	_iProgress = _iMax;
161
	updateStatus();
189
	updateStatus();
162
	if (_bVisible) Hide();
190
	if (_bVisible) Hide();
191
#ifdef UNX
192
	if (!doRender()) {
193
/*			fprintf (stderr, "SplashScreen::end()\n"); */
194
			fprintf (_outFd, "end\n");
195
			fflush (_outFd);
196
			fclose (_outFd);
197
			_outFd = NULL;
198
	}
199
#endif
163
}
200
}
164
void SAL_CALL SplashScreen::reset()
201
void SAL_CALL SplashScreen::reset()
165
	throw (RuntimeException)
202
	throw (RuntimeException)
Lines 184-189 void SAL_CALL SplashScreen::setValue(sal Link Here
184
    RTL_LOGFILE_CONTEXT_TRACE1( aLog, "value=%d", nValue );
221
    RTL_LOGFILE_CONTEXT_TRACE1( aLog, "value=%d", nValue );
185
222
186
    ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
223
    ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
224
#ifdef UNX
225
	if (!doRender())
226
	{
227
		fprintf (_outFd, "%d%%\n", nValue);
228
		fflush (_outFd);
229
	}
230
#endif
187
    if (_bVisible) {
231
    if (_bVisible) {
188
        Show();
232
        Show();
189
	    if (nValue >= _iMax) _iProgress = _iMax;
233
	    if (nValue >= _iMax) _iProgress = _iMax;
Lines 198-204 SplashScreen::initialize( const ::com::s Link Here
198
	throw (RuntimeException)
242
	throw (RuntimeException)
199
{
243
{
200
	::osl::ClearableMutexGuard	aGuard(	_aMutex );
244
	::osl::ClearableMutexGuard	aGuard(	_aMutex );
201
	if (aArguments.getLength() > 0)
245
	if (aArguments.getLength() > 0 && doRender())
202
		aArguments[0] >>= _bVisible;
246
		aArguments[0] >>= _bVisible;
203
}
247
}
204
248
(-)desktop/prj/build.lst (-1 / +2 lines)
Lines 14-19 dt desktop\win32\source\setup nmake - Link Here
14
dt	desktop\win32\source\officeloader		nmake	-	w	dt_officeloader NULL
14
dt	desktop\win32\source\officeloader		nmake	-	w	dt_officeloader NULL
15
dt	desktop\win32\source\applauncher		nmake	-	w	dt_applauncher NULL
15
dt	desktop\win32\source\applauncher		nmake	-	w	dt_applauncher NULL
16
dt	desktop\win32\source\applauncher\ooo	nmake	-	w	dt_applauncher_ooo dt_applauncher.w NULL
16
dt	desktop\win32\source\applauncher\ooo	nmake	-	w	dt_applauncher_ooo dt_applauncher.w NULL
17
dt	desktop\unx\source					nmake	-	u	dt_uwrapper NULL
17
dt	desktop\source\pagein					nmake	-	u	dt_pagein NULL
18
dt	desktop\source\pagein					nmake	-	u	dt_pagein NULL
18
dt	desktop\source\pkgchk					nmake	-	all	dt_pkgchk dt_dp_misc dt_app NULL
19
dt	desktop\source\pkgchk					nmake	-	all	dt_pkgchk dt_dp_misc dt_app NULL
19
dt	desktop\source\pkgchk\msi				nmake	-	w	dt_pkgchk_msi dt_pkgchk NULL
20
dt	desktop\source\pkgchk\msi				nmake	-	w	dt_pkgchk_msi dt_pkgchk NULL
Lines 30-33 dt desktop\source\deployment\registry\co Link Here
30
dt	desktop\source\deployment\registry\configuration	nmake	-	all	dt_dp_registry_configuration dt_dp_misc NULL
31
dt	desktop\source\deployment\registry\configuration	nmake	-	all	dt_dp_registry_configuration dt_dp_misc NULL
31
dt	desktop\scripts 						nmake	-	u	dt_scripts NULL
32
dt	desktop\scripts 						nmake	-	u	dt_scripts NULL
32
dt	desktop\macosx\source					nmake	-	u	dt_macosx_bundle	NULL
33
dt	desktop\macosx\source					nmake	-	u	dt_macosx_bundle	NULL
33
dt	desktop\util							nmake	-	all	dt_util dt_app dt_so_comp dt_spl dt_wrapper.w dt_officeloader.w dt_migr dt_macosx_bundle.u NULL
34
dt	desktop\util							nmake	-	all	dt_util dt_app dt_so_comp dt_spl dt_uwrapper.u dt_wrapper.w dt_officeloader.w dt_migr dt_macosx_bundle.u NULL
(-)desktop/prj/d.lst (+1 lines)
Lines 7-13 mkdir: %_DEST%\bin%_EXT%\remote2 Link Here
7
..\%__SRC%\bin\soffice.bin %_DEST%\bin%_EXT%\soffice.bin
7
..\%__SRC%\bin\soffice.bin %_DEST%\bin%_EXT%\soffice.bin
8
..\%__SRC%\bin\officeloader.exe %_DEST%\bin%_EXT%\soffice.exe
8
..\%__SRC%\bin\officeloader.exe %_DEST%\bin%_EXT%\soffice.exe
9
..\%__SRC%\bin\soffice %_DEST%\bin%_EXT%\soffice.bin
9
..\%__SRC%\bin\soffice %_DEST%\bin%_EXT%\soffice.bin
10
..\%__SRC%\bin\ooqstart %_DEST%\bin%_EXT%\ooqstart
10
11
11
..\%__SRC%\bin\soffice_oo.exe %_DEST%\bin%_EXT%\soffice_oo.exe
12
..\%__SRC%\bin\soffice_oo.exe %_DEST%\bin%_EXT%\soffice_oo.exe
12
..\%__SRC%\bin\soffice_so.exe %_DEST%\bin%_EXT%\soffice_so.exe
13
..\%__SRC%\bin\soffice_so.exe %_DEST%\bin%_EXT%\soffice_so.exe
(-)scp2/source/ooo/file_ooo.scp (+9 lines)
Lines 335-340 File gid_File_Bin_Soffice_Bin Link Here
335
    Name = "soffice.bin";
335
    Name = "soffice.bin";
336
End
336
End
337
337
338
#if defined(UNX) && defined(ENABLE_GTK)
339
File gid_File_Bin_QStart_Bin
340
    BIN_FILE_BODY;
341
    Dir = gid_Dir_Program;
342
    Styles = (PACKED, PATCH);
343
    Name = "ooqstart";
344
End
345
#endif
346
338
#ifdef UNX
347
#ifdef UNX
339
348
340
File gid_File_Bin_Open_Url
349
File gid_File_Bin_Open_Url
(-) (+30 lines)
Added Link Here
1
PRJ=..$/..
2
PRJNAME=desktop
3
TARGET=ooqstart
4
5
NO_DEFAULT_STL=TRUE
6
7
.INCLUDE :  settings.mk
8
9
.IF "$(ENABLE_GTK)" != "TRUE"
10
dummy:
11
	@echo "Nothing to build. GUIBASE == $(GUIBASE), WITH_WIDGETSET == $(WITH_WIDGETSET)"
12
13
.ELSE # build with gtk+
14
15
PKGCONFIG_MODULES=gtk+-2.0
16
.INCLUDE: pkg_config.mk
17
18
CFLAGS+= $(PKGCONFIG_CFLAGS)
19
20
APP1TARGET = $(TARGET)
21
APP1OBJS   = $(OBJ)$/start.obj
22
APP1NOSAL  = TRUE
23
APP1LIBSALCPPRT=
24
APP1STDLIBS = $(PKGCONFIG_LIBS)
25
26
.ENDIF
27
28
# --- Targets ------------------------------------------------------
29
30
.INCLUDE :	target.mk
(-) (+525 lines)
Added Link Here
1
#include <signal.h>
2
#include <unistd.h>
3
#include <gtk/gtk.h>
4
#include <limits.h>
5
#include <stdlib.h>
6
#include <sys/types.h>
7
#include <sys/stat.h>
8
#include <sys/socket.h>
9
#include <arpa/inet.h>
10
#include <sys/un.h>
11
#include <fcntl.h>
12
#include <stdio.h>
13
14
#define PIPEDEFAULTPATH		"/tmp"
15
#define PIPEALTERNATEPATH	"/var/tmp"
16
17
static char *
18
read_path_and_chomp (const char *app)
19
{
20
		int len;
21
		char buffer[PATH_MAX];
22
23
		/* Readlink on argv[0] to point to the install path */
24
		if ((len = readlink (app, buffer, sizeof(buffer))) < 0)
25
				return NULL;
26
		buffer[MIN(len, 4095)] = '\0';
27
28
		return g_path_get_dirname (buffer);
29
}
30
31
static char *
32
get_app_path (const char *app_exec)
33
{
34
		if (app_exec[0] != '/')
35
				g_error ("%s must be called with an absolute path\n", app_exec);
36
		
37
		return g_path_get_dirname (app_exec);
38
}
39
40
/* OO.o likes to find real paths, unwinding symlinks etc. */
41
static char *
42
get_real_app_path (const char *app_path)
43
{
44
		char *path, *bin_path;
45
46
		path = g_strdup (app_path);
47
48
		/* Hack for use with linkoo: follow soffice.bin
49
		   if it is a symlink */
50
		bin_path = g_strconcat (app_path, "/soffice.bin", NULL);
51
		if (g_file_test (bin_path, G_FILE_TEST_IS_SYMLINK)) 
52
		{
53
				g_free (path);
54
				path = read_path_and_chomp (bin_path);
55
		}
56
		g_free (bin_path);
57
58
		/* Nasty - but OO.o likes to call realpath too ... */
59
		char *real_path = (char *)g_malloc (PATH_MAX + 1);
60
		realpath (path, real_path);
61
		real_path[PATH_MAX] = '\0';
62
		g_free (path);
63
64
		return real_path;
65
}
66
67
static char *
68
get_pipe_path (const char *app_path)
69
{
70
		char *pipe_path;
71
		char *real_app_path;
72
		char *terminated_path;
73
		const char *base_path;
74
75
		real_app_path = get_real_app_path (app_path);
76
		terminated_path = g_strconcat (real_app_path, "/", NULL);
77
78
		if (access(PIPEDEFAULTPATH, R_OK|W_OK) == 0)
79
				base_path = PIPEDEFAULTPATH;
80
		else
81
				base_path = PIPEALTERNATEPATH;
82
83
		pipe_path = g_strdup_printf (
84
				"%s/OSL_PIPE_%u_SingleOfficeIPC_%d-%x", base_path, (int)getuid(),
85
				SUPD, g_str_hash (terminated_path));
86
87
/*		fprintf (stderr, "pipe path is '%s' from '%s'\n", pipe_path, real_app_path); */
88
89
		g_free (terminated_path);
90
		g_free (real_app_path);
91
92
		return pipe_path;
93
}
94
95
static int
96
connect_pipe (const char *pipe_path)
97
{
98
		int fd;
99
		size_t len;
100
		struct sockaddr_un addr;
101
102
		memset(&addr, 0, sizeof(addr));
103
104
		if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
105
				return fd;
106
		
107
		fcntl (fd, F_SETFD, FD_CLOEXEC);
108
109
		addr.sun_family = AF_UNIX;
110
		strncpy(addr.sun_path, pipe_path, sizeof(addr.sun_path));
111
112
/* cut / paste from osl's pipe.c */
113
#if defined(FREEBSD)
114
		len = SUN_LEN(&addr);
115
#else
116
		len = sizeof(addr);
117
#endif
118
119
		if (connect (fd, (struct sockaddr *)&addr, len) < 0)
120
				return -1;
121
122
		return fd;
123
}
124
125
static gboolean
126
send_args (int fd, GPtrArray *args, const char *cwd)
127
{
128
		int i, len;
129
		GString *arg_str = g_string_new ("");
130
131
		for (i = 1; i < args->len; i++)
132
		{
133
				g_string_append (arg_str, (char *)args->pdata[i]);
134
				g_string_append_c (arg_str, '|');
135
		}
136
137
#ifdef DEBUG		
138
		fprintf (stderr, "Pass args: '%s'\n", arg_str->str); 
139
#endif
140
		len = arg_str->len + 1;
141
142
		return write (fd, arg_str->str, len) == len;
143
}
144
145
static void
146
init_gtk (int argc, char **argv)
147
{
148
	int i;
149
    char *args[3];
150
	char **argptr = args;
151
	
152
	args[0] = argv[0];
153
	argc = 1;
154
	for (i = 0; i < argc - 1; i++)
155
	{
156
			if (!strcmp (argv[i], "-display") ||
157
				!strcmp (argv[i], "--display"))
158
			{
159
					args[argc++] = g_strdup ("--display");
160
					args[argc++] = argv[i+1];
161
			}
162
	}
163
    gtk_init_check( &argc, &argptr );
164
}
165
166
static void
167
center_window (GtkWindow *window, void *dummy)
168
{
169
	GdkRectangle rect;
170
171
	gdk_screen_get_monitor_geometry (window->screen, 0, &rect);
172
	int sx = rect.width;
173
	int sy = rect.height;
174
	
175
	GdkGeometry geom;
176
	geom.base_width = GTK_WIDGET (window)->allocation.width;
177
	geom.base_height = GTK_WIDGET (window)->allocation.height;
178
	geom.min_width = geom.max_width = geom.base_width;
179
	geom.min_height = geom.max_height = geom.base_height;
180
181
	gtk_window_move (window, sx / 2 - geom.min_width / 2,
182
					 sy / 2 - geom.min_height / 2);
183
184
	int hints = GDK_HINT_POS | GDK_HINT_USER_POS |
185
			GDK_HINT_BASE_SIZE | GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE |
186
			GDK_HINT_USER_SIZE;
187
188
	gtk_window_set_geometry_hints (window, NULL, &geom, (GdkWindowHints) hints);
189
}
190
191
typedef struct {
192
		gboolean finish;
193
		gboolean error;
194
		GtkProgressBar *progress_bar;
195
}  StatusClosure;
196
197
static gboolean
198
status_pipe_update (GIOChannel * source,
199
					GIOCondition condition, 
200
					StatusClosure *cl)
201
{
202
	gboolean retval = TRUE;
203
204
#ifdef DEBUG
205
	fprintf (stderr, "Status pipe update (0x%x)\n", (int) condition);
206
#endif
207
208
	if ((int)condition & (G_IO_IN | G_IO_PRI))
209
	{
210
			int percent;
211
			GString *str = g_string_new ("");
212
			switch (g_io_channel_read_line_string (source, str, NULL, NULL)) {
213
			case G_IO_STATUS_ERROR:
214
					cl->error = TRUE;
215
					/* drop through */
216
			case G_IO_STATUS_EOF:
217
					retval = FALSE;
218
					break;
219
			default:
220
					/* pipe lifecycle is odd - HUP only for remote process death */
221
					if (!g_ascii_strncasecmp (str->str, "end", 3))
222
							retval = FALSE;
223
					if (sscanf (str->str, "%d%%", &percent))
224
							gtk_progress_bar_set_fraction (cl->progress_bar,
225
														   (float) percent / 100.0);
226
					break;
227
			}
228
			g_string_free (str, TRUE);
229
	}
230
231
	if ((int)condition & (G_IO_HUP | G_IO_NVAL | G_IO_ERR))
232
	{
233
			cl->error = TRUE;
234
			retval = FALSE;
235
	}
236
237
	if (!retval)
238
			cl->finish = TRUE;
239
240
	return retval;
241
}
242
243
static GdkPixbuf *
244
get_splash (const char *image_path)
245
{
246
		char *path;
247
		GdkPixbuf *pixbuf;
248
249
		path = g_strconcat (image_path, "/intro-nld.bmp", NULL);
250
		pixbuf = gdk_pixbuf_new_from_file (path, NULL);
251
		g_free (path);
252
		if (pixbuf)
253
				return pixbuf;
254
255
		path = g_strconcat (image_path, "/intro.bmp", NULL);
256
		pixbuf = gdk_pixbuf_new_from_file (path, NULL);
257
		g_free (path);
258
259
		return pixbuf;
260
}
261
262
static void
263
show_splash (const char *image_path, GIOChannel *status_channel)
264
{
265
		GdkPixbuf *pixbuf;
266
		GtkWidget *contents;
267
		GtkWidget *vbox;
268
		StatusClosure cl;
269
270
		if ((pixbuf = get_splash (image_path)))
271
				contents = gtk_image_new_from_pixbuf (pixbuf);
272
		else
273
				contents = gtk_label_new ("No splash pixmap");
274
275
		/* setup closure */
276
		cl.finish = FALSE;
277
		cl.error = FALSE;
278
		cl.progress_bar = GTK_PROGRESS_BAR (gtk_progress_bar_new ());
279
280
		/* pack contents & progres bar */
281
		vbox = gtk_vbox_new (FALSE, 0);
282
		gtk_box_pack_start (GTK_BOX (vbox), contents,
283
							TRUE, FALSE, 0);
284
		gtk_progress_bar_set_orientation (
285
			cl.progress_bar, GTK_PROGRESS_LEFT_TO_RIGHT);
286
		gtk_progress_bar_set_fraction (cl.progress_bar, 0.03);
287
		gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (cl.progress_bar),
288
							FALSE, FALSE, 0);
289
290
		/* setup window */
291
		GtkWindow *window;
292
		window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
293
		gtk_window_set_has_frame (window, FALSE);
294
		gtk_window_set_resizable (window, FALSE);
295
		gtk_window_set_decorated (window, FALSE);
296
/*		gtk_window_set_icon_name (window, "foo"); FIXME splash WM icon ? */
297
298
		/* click to dismiss */
299
		GtkWidget *event_box;
300
		event_box = gtk_event_box_new ();
301
		gtk_container_add (GTK_CONTAINER (event_box), vbox);
302
		g_signal_connect_swapped (G_OBJECT (event_box), "button_press_event",
303
								  G_CALLBACK (gtk_widget_hide), (gpointer) window);
304
305
		gtk_container_add (GTK_CONTAINER (window), event_box);
306
		g_signal_connect (G_OBJECT (window), "realize", 
307
						  G_CALLBACK (center_window), NULL);
308
		gtk_widget_show_all (GTK_WIDGET (window));
309
310
		/* setup status listener ... */
311
		g_io_add_watch (status_channel, 
312
						(GIOCondition)(G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_NVAL | G_IO_ERR),
313
						(GIOFunc) status_pipe_update, (gpointer) &cl);
314
315
#ifdef DEBUG
316
		g_warning ("Start main loop...\n");
317
#endif
318
		while (!cl.finish)
319
                g_main_context_iteration (g_main_context_default (), TRUE);
320
321
		if (cl.error)
322
				g_warning ("Unknown error forking main binary / abnormal early exit ...");
323
        
324
        g_io_channel_shutdown (status_channel, FALSE, NULL);
325
        g_io_channel_unref (status_channel);
326
}
327
328
typedef struct {
329
		int pipe_fd;
330
		int clone_fd;
331
} ChildClosure;
332
333
static void
334
child_setup (gpointer user_data)
335
{
336
		ChildClosure *cl = (ChildClosure *)user_data;
337
		if (cl->pipe_fd >= 0)
338
				close (cl->pipe_fd);
339
		close (cl->clone_fd);
340
}
341
342
static gboolean
343
fork_app (const char *app_path, GPtrArray *args, int pipe_fd,
344
		  GIOChannel **status_channel)
345
{
346
		int status_pipe[2];
347
		gboolean spawn_success;
348
		GError *error = NULL;
349
		char *splash_pipe_arg;
350
		ChildClosure *cl = g_new (ChildClosure, 1);
351
		GIOChannel *status;
352
353
		args->pdata[0] = (gpointer)g_strconcat (app_path, "/soffice", NULL);
354
355
		/* create pipe */
356
     	if (pipe (status_pipe) < 0)
357
				g_error ("no file handles\n");
358
359
        status = g_io_channel_unix_new (status_pipe[0]);
360
        g_io_channel_set_encoding (status, NULL, NULL);
361
362
		splash_pipe_arg = g_strdup_printf ("-splash-pipe=%d", status_pipe[1]);
363
#ifdef DEBUG
364
		fprintf ( stderr, "Pass splash pipe arg: '%s'\n", splash_pipe_arg);
365
#endif
366
		g_ptr_array_add (args, splash_pipe_arg);
367
368
#ifdef DEBUG
369
		fprintf (stderr, "Fork app '%s' in '%s'\n", (char *)args->pdata[0], app_path);
370
#endif
371
		cl->pipe_fd = pipe_fd;
372
		cl->clone_fd = status_pipe[0];
373
		spawn_success = g_spawn_async
374
				(app_path, (char **)args->pdata, NULL,
375
				 G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
376
				 (GSpawnChildSetupFunc) child_setup,
377
				 (gpointer) cl,
378
				 NULL, /* child_pid */
379
				 &error);
380
		close (status_pipe[1]);
381
382
		if (!spawn_success)
383
				fprintf (stderr, "Error forking '%s/%s': '%s'\n",
384
						 app_path, "/soffice",
385
						 error ? error->message : "<no message>");
386
387
		*status_channel = status;
388
389
		return spawn_success;
390
}
391
392
static gboolean
393
arg_check (const char *arg, const char *cmp_with)
394
{
395
		if (arg[0] == '-')
396
				arg++;
397
		else
398
				return FALSE;
399
		if (arg[0] == '-') /* tolerate -- prefixes etc. */
400
				arg++;
401
		return !g_ascii_strcasecmp (arg, cmp_with);
402
}
403
404
static GPtrArray *
405
setup_args (int argc, char **argv, gboolean *inhibit_splash)
406
{
407
		int i;
408
		gboolean have_non_option = FALSE;
409
		GPtrArray *args = g_ptr_array_sized_new (argc + 8);
410
411
		*inhibit_splash = FALSE;
412
		
413
		for (i = 0; i < argc; i++)
414
		{
415
				if (arg_check (argv[i], "widgets-set")) {
416
						char *widget_env;
417
						if (i >= argc - 1)
418
								continue;
419
						widget_env = g_strconcat ("SAL_USE_VCLPLUGIN=", argv[i+1], NULL);
420
						putenv (widget_env); /* deliberate leak */
421
						i++;
422
						continue;
423
				}
424
				g_ptr_array_add (args, g_strdup (argv[i]));
425
				if (!i)
426
						continue;
427
428
				if (argv[i][0] != '-')
429
						have_non_option = TRUE;
430
431
				else if (arg_check (argv[i], "nologo") ||
432
						 arg_check (argv[i], "headless") ||
433
						 arg_check (argv[i], "invisible"))
434
						*inhibit_splash = TRUE;
435
		}
436
437
		/* It's necessary to append eg. -writer for writer. */
438
		if (!have_non_option)
439
		{
440
				const char *extra_arg = g_getenv ("OOO_EXTRA_ARG");
441
				if (!extra_arg)
442
						g_error ("Missing default argument in OOO_EXTRA_ARG");
443
				g_ptr_array_add (args, g_strdup (extra_arg));
444
		}
445
446
		return args;
447
}
448
449
static void
450
system_checks ()
451
{
452
#ifdef LINUX
453
		int fd;
454
		char *recently_used;
455
456
		/* FIXME: force right ownership of ~/.ooo-* as well
457
		 * really all that work should be done by OO.o - not here.
458
		 */
459
460
		/* force right ownership on ~/.recently-used despite umask */
461
		recently_used = g_strconcat (g_get_home_dir (), "/.recently-used", NULL);
462
		fd = open (recently_used, O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
463
		if (fd >= 0)
464
				close (fd);
465
		g_free (recently_used);
466
467
		/* check proc is mounted - lots of things fail otherwise */
468
		if (!g_file_test ("/proc/version", G_FILE_TEST_EXISTS))
469
				g_warning ("/proc not mounted - OO.o is unlikely to work well if at all");
470
#endif
471
}
472
473
int main (int argc, char **argv)
474
{
475
		int fd;
476
		gboolean inhibit_splash;
477
		GIOChannel *status_channel = NULL;
478
		gboolean sent_args = FALSE;
479
		char *app_path, *pipe_path;
480
		GPtrArray *args;
481
		char cwd_str[PATH_MAX];
482
483
		/* turn SIGPIPE into an error */
484
		signal (SIGPIPE, SIG_IGN);
485
		if (!getcwd (cwd_str, sizeof (cwd_str)))
486
				g_error ("can't get cwd");
487
		cwd_str[sizeof(cwd_str)-1] = '\0';
488
	
489
		args = setup_args (argc, argv, &inhibit_splash);
490
491
		app_path = get_app_path (argv[0]);
492
		if (!app_path)
493
				g_error ("Pathalogical failure: can't read app link\n");
494
495
		pipe_path = get_pipe_path (app_path);
496
497
		if ((fd = connect_pipe (pipe_path)) >= 0)
498
				sent_args = send_args (fd, args, cwd_str);
499
#ifdef DEBUG
500
		else
501
				fprintf (stderr, "Failed to connect to pipe '%s'\n", pipe_path);
502
#endif
503
504
		if (!sent_args)
505
		{
506
				if (! fork_app (app_path, args, fd, &status_channel))
507
						return 1;
508
		}
509
510
		init_gtk (argc, argv);
511
		if (sent_args || inhibit_splash)
512
		{
513
				gdk_notify_startup_complete ();
514
				return 0;
515
		}
516
517
		if (!inhibit_splash)
518
				show_splash (app_path, status_channel);
519
520
		g_ptr_array_foreach (args, (GFunc)g_free, NULL);
521
		g_ptr_array_free (args, TRUE);
522
		g_free (app_path);
523
524
		return 0;
525
}

Return to issue 60696