Update ooo320-m1
[ooovba.git] / odk / source / unoapploader / unx / unoapploader.c
blob27bf9a6b62cd508900b775ce15933cf0a3c558c1
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unoapploader.c,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <sys/stat.h>
37 #ifdef LINUX
38 #define __USE_GNU
39 #endif
40 #include <dlfcn.h>
42 #include "cppuhelper/findsofficepath.h"
43 #include "rtl/string.h"
44 #include "sal/types.h"
46 char const* getPath();
47 char* createCommandName( char* argv0 );
49 const int SEPARATOR = '/';
50 const char* PATHSEPARATOR = ":";
54 * The main function implements a loader for applications which use UNO.
56 * <p>This code runs on the Unix/Linux platforms only.</p>
58 * <p>The main function detects a UNO installation on the system and adds the
59 * relevant directories of the installation to the LD_LIBRARY_PATH environment
60 * variable. After that, the application process is loaded and started, whereby
61 * the new process inherits the environment of the calling process, including
62 * the modified LD_LIBRARY_PATH environment variable. The application's
63 * executable name must be the same as the name of this executable, prefixed
64 * by '_'.</p>
65 * <p>On MACOSX DYLD_LIBRARY_PATH is used instead of LD_LIBRARY_PATH!<p>
67 * <p>A UNO installation can be specified by the user by setting the UNO_PATH
68 * environment variable to the program directory of the UNO installation.
69 * If no installation is specified by the user, the default installation on
70 * the system will be taken. The default installation is found from the
71 * PATH environment variable. This requires that the 'soffice' executable or
72 * a symbolic link is in one of the directories listed in the PATH environment
73 * variable.</p>
75 int main( int argc, char *argv[] )
77 char const* path;
78 char* cmdname;
80 (void) argc; /* avoid warning about unused parameter */
82 /* get the path of the UNO installation */
83 path = getPath();
85 if ( path != NULL )
87 #ifdef MACOSX
88 static const char* ENVVARNAME = "DYLD_LIBRARY_PATH";
89 #else
90 static const char* ENVVARNAME = "LD_LIBRARY_PATH";
91 #endif
92 char * libpath;
93 int freeLibpath;
95 char* value;
96 char* envstr;
97 int size;
99 size_t pathlen = strlen(path);
100 struct stat stat;
101 int ret;
102 char * unoinfo = malloc(
103 pathlen + RTL_CONSTASCII_LENGTH("/unoinfo") + 1);
104 /*TODO: overflow */
105 if (unoinfo == NULL) {
106 fprintf(stderr, "Error: out of memory!\n");
107 exit(EXIT_FAILURE);
109 strcpy(unoinfo, path);
110 strcpy(
111 unoinfo + pathlen,
112 "/unoinfo" + (pathlen == 0 || path[pathlen - 1] != '/' ? 0 : 1));
113 ret = lstat(unoinfo, &stat);
114 free(unoinfo);
116 if (ret == 0) {
117 char * cmd = malloc(
118 2 * pathlen + RTL_CONSTASCII_LENGTH("/unoinfo c++") + 1);
119 /*TODO: overflow */
120 char const * p;
121 char * q;
122 FILE * f;
123 size_t n = 1000;
124 size_t old = 0;
125 if (cmd == NULL) {
126 fprintf(stderr, "Error: out of memory!\n");
127 exit(EXIT_FAILURE);
129 p = path;
130 q = cmd;
131 while (*p != '\0') {
132 *q++ = '\\';
133 *q++ = *p++;
135 if (p == path || p[-1] != '/') {
136 *q++ = '/';
138 strcpy(q, "unoinfo c++");
139 f = popen(cmd, "r");
140 free(cmd);
141 if (f == NULL)
143 fprintf(stderr, "Error: calling unoinfo failed!\n");
144 exit(EXIT_FAILURE);
146 libpath = NULL;
147 for (;;) {
148 size_t m;
149 libpath = realloc(libpath, n);
150 if (libpath == NULL) {
151 fprintf(
152 stderr,
153 "Error: out of memory reading unoinfo output!\n");
154 exit(EXIT_FAILURE);
156 m = fread(libpath + old, 1, n - old - 1, f);
157 if (m != n - old - 1) {
158 if (ferror(f)) {
159 fprintf(stderr, "Error: cannot read unoinfo output!\n");
160 exit(EXIT_FAILURE);
162 libpath[old + m] = '\0';
163 break;
165 if (n >= SAL_MAX_SIZE / 2) {
166 fprintf(
167 stderr,
168 "Error: out of memory reading unoinfo output!\n");
169 exit(EXIT_FAILURE);
171 old = n - 1;
172 n *= 2;
174 if (pclose(f) != 0) {
175 fprintf(stderr, "Error: executing unoinfo failed!\n");
176 exit(EXIT_FAILURE);
178 freeLibpath = 1;
180 else
182 /* Assume an old OOo 2.x installation without unoinfo: */
183 libpath = (char *) path;
184 freeLibpath = 0;
187 value = getenv( ENVVARNAME );
189 size = strlen( ENVVARNAME ) + strlen( "=" ) + strlen( libpath ) + 1;
190 if ( value != NULL )
191 size += strlen( PATHSEPARATOR ) + strlen( value );
192 envstr = (char*) malloc( size );
193 strcpy( envstr, ENVVARNAME );
194 strcat( envstr, "=" );
195 strcat( envstr, libpath );
196 if ( freeLibpath != 0 )
198 free( libpath );
200 if ( value != NULL )
202 strcat( envstr, PATHSEPARATOR );
203 strcat( envstr, value );
205 putenv( envstr );
207 else
209 fprintf( stderr, "Warning: no UNO installation found!\n" );
210 fflush( stderr );
213 /* set the executable name for the application process */
214 cmdname = createCommandName( argv[0] );
215 argv[0] = cmdname;
218 * create the application process;
219 * if successful, execvp doesn't return to the calling process
221 execvp( cmdname, argv );
222 fprintf( stderr, "Error: execvp failed!\n" );
223 fflush( stderr );
225 return 0;
229 * Gets the path of a UNO installation.
231 * @return the installation path or NULL, if no installation was specified or
232 * found, or if an error occured
234 char const* getPath()
236 char const* path = cppuhelper_detail_findSofficePath();
238 if ( path == NULL )
240 fprintf( stderr, "Warning: getting path from PATH environment "
241 "variable failed!\n" );
242 fflush( stderr );
245 return path;
249 * Creates the application's executable file name.
251 * <p>The application's executable file name is the name of this executable
252 * prefixed by '_'.</p>
254 * @param argv0 specifies the argv[0] parameter of the main function
256 * @return the application's executable file name or NULL, if an error occured
258 char* createCommandName( char* argv0 )
260 const char* CMDPREFIX = "_";
261 const char* prgname = NULL;
263 char* cmdname = NULL;
264 char* sep = NULL;
265 Dl_info dl_info;
266 int pos;
268 /* get the executable file name from argv0 */
269 prgname = argv0;
272 * if argv0 doesn't contain an absolute path name, try to get the absolute
273 * path name from dladdr; note that this only works for Solaris, not for
274 * Linux
276 if ( argv0 != NULL && *argv0 != SEPARATOR &&
277 dladdr( (void*) &createCommandName, &dl_info ) &&
278 dl_info.dli_fname != NULL && *dl_info.dli_fname == SEPARATOR )
280 prgname = dl_info.dli_fname;
283 /* prefix the executable file name by '_' */
284 if ( prgname != NULL )
286 cmdname = (char*) malloc( strlen( prgname ) + strlen( CMDPREFIX ) + 1 );
287 sep = strrchr( prgname, SEPARATOR );
288 if ( sep != NULL )
290 pos = ++sep - prgname;
291 strncpy( cmdname, prgname, pos );
292 cmdname[ pos ] = '\0';
293 strcat( cmdname, CMDPREFIX );
294 strcat( cmdname, sep );
296 else
298 strcpy( cmdname, CMDPREFIX );
299 strcat( cmdname, prgname );
303 return cmdname;