12e82054bSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 32e82054bSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 42e82054bSAndrew Rist * or more contributor license agreements. See the NOTICE file 52e82054bSAndrew Rist * distributed with this work for additional information 62e82054bSAndrew Rist * regarding copyright ownership. The ASF licenses this file 72e82054bSAndrew Rist * to you under the Apache License, Version 2.0 (the 82e82054bSAndrew Rist * "License"); you may not use this file except in compliance 92e82054bSAndrew Rist * with the License. You may obtain a copy of the License at 102e82054bSAndrew Rist * 112e82054bSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 122e82054bSAndrew Rist * 132e82054bSAndrew Rist * Unless required by applicable law or agreed to in writing, 142e82054bSAndrew Rist * software distributed under the License is distributed on an 152e82054bSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 162e82054bSAndrew Rist * KIND, either express or implied. See the License for the 172e82054bSAndrew Rist * specific language governing permissions and limitations 182e82054bSAndrew Rist * under the License. 192e82054bSAndrew Rist * 202e82054bSAndrew Rist *************************************************************/ 212e82054bSAndrew Rist 222e82054bSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include <stdlib.h> 25cdf0e10cSrcweir #include <unistd.h> 26cdf0e10cSrcweir #include <stdio.h> 27cdf0e10cSrcweir #include <string.h> 28cdf0e10cSrcweir #include <sys/stat.h> 29cdf0e10cSrcweir 30cdf0e10cSrcweir #ifdef LINUX 31cdf0e10cSrcweir #define __USE_GNU 32cdf0e10cSrcweir #endif 33cdf0e10cSrcweir #include <dlfcn.h> 34cdf0e10cSrcweir 35cdf0e10cSrcweir #include "cppuhelper/findsofficepath.h" 36cdf0e10cSrcweir #include "rtl/string.h" 37cdf0e10cSrcweir #include "sal/types.h" 38cdf0e10cSrcweir 39cdf0e10cSrcweir char const* getPath(); 40cdf0e10cSrcweir char* createCommandName( char* argv0 ); 41cdf0e10cSrcweir 42cdf0e10cSrcweir const int SEPARATOR = '/'; 43cdf0e10cSrcweir const char* PATHSEPARATOR = ":"; 44cdf0e10cSrcweir 45cdf0e10cSrcweir 46cdf0e10cSrcweir /* 47cdf0e10cSrcweir * The main function implements a loader for applications which use UNO. 48cdf0e10cSrcweir * 49cdf0e10cSrcweir * <p>This code runs on the Unix/Linux platforms only.</p> 50cdf0e10cSrcweir * 51cdf0e10cSrcweir * <p>The main function detects a UNO installation on the system and adds the 52cdf0e10cSrcweir * relevant directories of the installation to the LD_LIBRARY_PATH environment 53cdf0e10cSrcweir * variable. After that, the application process is loaded and started, whereby 54cdf0e10cSrcweir * the new process inherits the environment of the calling process, including 55cdf0e10cSrcweir * the modified LD_LIBRARY_PATH environment variable. The application's 56cdf0e10cSrcweir * executable name must be the same as the name of this executable, prefixed 57cdf0e10cSrcweir * by '_'.</p> 58cdf0e10cSrcweir * <p>On MACOSX DYLD_LIBRARY_PATH is used instead of LD_LIBRARY_PATH!<p> 59cdf0e10cSrcweir * 60cdf0e10cSrcweir * <p>A UNO installation can be specified by the user by setting the UNO_PATH 61cdf0e10cSrcweir * environment variable to the program directory of the UNO installation. 62cdf0e10cSrcweir * If no installation is specified by the user, the default installation on 63cdf0e10cSrcweir * the system will be taken. The default installation is found from the 64cdf0e10cSrcweir * PATH environment variable. This requires that the 'soffice' executable or 65cdf0e10cSrcweir * a symbolic link is in one of the directories listed in the PATH environment 66cdf0e10cSrcweir * variable.</p> 67cdf0e10cSrcweir */ 68cdf0e10cSrcweir int main( int argc, char *argv[] ) 69cdf0e10cSrcweir { 70cdf0e10cSrcweir char const* path; 71cdf0e10cSrcweir char* cmdname; 72cdf0e10cSrcweir 73cdf0e10cSrcweir (void) argc; /* avoid warning about unused parameter */ 74cdf0e10cSrcweir 75cdf0e10cSrcweir /* get the path of the UNO installation */ 76cdf0e10cSrcweir path = getPath(); 77cdf0e10cSrcweir 78cdf0e10cSrcweir if ( path != NULL ) 79cdf0e10cSrcweir { 80cdf0e10cSrcweir #ifdef MACOSX 81cdf0e10cSrcweir static const char* ENVVARNAME = "DYLD_LIBRARY_PATH"; 82cdf0e10cSrcweir #else 83cdf0e10cSrcweir static const char* ENVVARNAME = "LD_LIBRARY_PATH"; 84cdf0e10cSrcweir #endif 85cdf0e10cSrcweir char * libpath; 86cdf0e10cSrcweir int freeLibpath; 87cdf0e10cSrcweir 88cdf0e10cSrcweir char* value; 89cdf0e10cSrcweir char* envstr; 90cdf0e10cSrcweir int size; 91cdf0e10cSrcweir 92cdf0e10cSrcweir size_t pathlen = strlen(path); 93cdf0e10cSrcweir struct stat stat; 94cdf0e10cSrcweir int ret; 95cdf0e10cSrcweir char * unoinfo = malloc( 96cdf0e10cSrcweir pathlen + RTL_CONSTASCII_LENGTH("/unoinfo") + 1); 97cdf0e10cSrcweir /*TODO: overflow */ 98cdf0e10cSrcweir if (unoinfo == NULL) { 99cdf0e10cSrcweir fprintf(stderr, "Error: out of memory!\n"); 100cdf0e10cSrcweir exit(EXIT_FAILURE); 101cdf0e10cSrcweir } 102cdf0e10cSrcweir strcpy(unoinfo, path); 103cdf0e10cSrcweir strcpy( 104cdf0e10cSrcweir unoinfo + pathlen, 105cdf0e10cSrcweir "/unoinfo" + (pathlen == 0 || path[pathlen - 1] != '/' ? 0 : 1)); 106cdf0e10cSrcweir ret = lstat(unoinfo, &stat); 107cdf0e10cSrcweir free(unoinfo); 108cdf0e10cSrcweir 109cdf0e10cSrcweir if (ret == 0) { 110cdf0e10cSrcweir char * cmd = malloc( 111cdf0e10cSrcweir 2 * pathlen + RTL_CONSTASCII_LENGTH("/unoinfo c++") + 1); 112cdf0e10cSrcweir /*TODO: overflow */ 113cdf0e10cSrcweir char const * p; 114cdf0e10cSrcweir char * q; 115cdf0e10cSrcweir FILE * f; 116cdf0e10cSrcweir size_t n = 1000; 117cdf0e10cSrcweir size_t old = 0; 118cdf0e10cSrcweir if (cmd == NULL) { 119cdf0e10cSrcweir fprintf(stderr, "Error: out of memory!\n"); 120cdf0e10cSrcweir exit(EXIT_FAILURE); 121cdf0e10cSrcweir } 122cdf0e10cSrcweir p = path; 123cdf0e10cSrcweir q = cmd; 124cdf0e10cSrcweir while (*p != '\0') { 125cdf0e10cSrcweir *q++ = '\\'; 126cdf0e10cSrcweir *q++ = *p++; 127cdf0e10cSrcweir } 128cdf0e10cSrcweir if (p == path || p[-1] != '/') { 129cdf0e10cSrcweir *q++ = '/'; 130cdf0e10cSrcweir } 131cdf0e10cSrcweir strcpy(q, "unoinfo c++"); 132cdf0e10cSrcweir f = popen(cmd, "r"); 133cdf0e10cSrcweir free(cmd); 134cdf0e10cSrcweir if (f == NULL) 135cdf0e10cSrcweir { 136cdf0e10cSrcweir fprintf(stderr, "Error: calling unoinfo failed!\n"); 137cdf0e10cSrcweir exit(EXIT_FAILURE); 138cdf0e10cSrcweir } 139cdf0e10cSrcweir libpath = NULL; 140cdf0e10cSrcweir for (;;) { 141cdf0e10cSrcweir size_t m; 142cdf0e10cSrcweir libpath = realloc(libpath, n); 143cdf0e10cSrcweir if (libpath == NULL) { 144cdf0e10cSrcweir fprintf( 145cdf0e10cSrcweir stderr, 146cdf0e10cSrcweir "Error: out of memory reading unoinfo output!\n"); 147cdf0e10cSrcweir exit(EXIT_FAILURE); 148cdf0e10cSrcweir } 149cdf0e10cSrcweir m = fread(libpath + old, 1, n - old - 1, f); 150cdf0e10cSrcweir if (m != n - old - 1) { 151cdf0e10cSrcweir if (ferror(f)) { 152cdf0e10cSrcweir fprintf(stderr, "Error: cannot read unoinfo output!\n"); 153cdf0e10cSrcweir exit(EXIT_FAILURE); 154cdf0e10cSrcweir } 155cdf0e10cSrcweir libpath[old + m] = '\0'; 156cdf0e10cSrcweir break; 157cdf0e10cSrcweir } 158cdf0e10cSrcweir if (n >= SAL_MAX_SIZE / 2) { 159cdf0e10cSrcweir fprintf( 160cdf0e10cSrcweir stderr, 161cdf0e10cSrcweir "Error: out of memory reading unoinfo output!\n"); 162cdf0e10cSrcweir exit(EXIT_FAILURE); 163cdf0e10cSrcweir } 164cdf0e10cSrcweir old = n - 1; 165cdf0e10cSrcweir n *= 2; 166cdf0e10cSrcweir } 167cdf0e10cSrcweir if (pclose(f) != 0) { 168cdf0e10cSrcweir fprintf(stderr, "Error: executing unoinfo failed!\n"); 169cdf0e10cSrcweir exit(EXIT_FAILURE); 170cdf0e10cSrcweir } 171cdf0e10cSrcweir freeLibpath = 1; 172cdf0e10cSrcweir } 173cdf0e10cSrcweir else 174cdf0e10cSrcweir { 175cdf0e10cSrcweir /* Assume an old OOo 2.x installation without unoinfo: */ 176cdf0e10cSrcweir libpath = (char *) path; 177cdf0e10cSrcweir freeLibpath = 0; 178cdf0e10cSrcweir } 179cdf0e10cSrcweir 180cdf0e10cSrcweir value = getenv( ENVVARNAME ); 181cdf0e10cSrcweir 182bec0253dSJürgen Schmidt // workaround for finding wrong libsqlite3.dylib in the office installation 183bec0253dSJürgen Schmidt // For MacOS > 10.6 nss uses the system lib -> unresolved symbol _sqlite3_wal_checkpoint 184bec0253dSJürgen Schmidt #ifdef MACOSX 185bec0253dSJürgen Schmidt size = strlen( ENVVARNAME ) + strlen( "=/usr/lib:" ) + strlen( libpath ) + 1; 186bec0253dSJürgen Schmidt #else 187cdf0e10cSrcweir size = strlen( ENVVARNAME ) + strlen( "=" ) + strlen( libpath ) + 1; 188bec0253dSJürgen Schmidt #endif 189cdf0e10cSrcweir if ( value != NULL ) 190cdf0e10cSrcweir size += strlen( PATHSEPARATOR ) + strlen( value ); 191cdf0e10cSrcweir envstr = (char*) malloc( size ); 192cdf0e10cSrcweir strcpy( envstr, ENVVARNAME ); 193bec0253dSJürgen Schmidt #ifdef MACOSX 194bec0253dSJürgen Schmidt strcat( envstr, "=/usr/lib:" ); 195bec0253dSJürgen Schmidt #else 196cdf0e10cSrcweir strcat( envstr, "=" ); 197bec0253dSJürgen Schmidt #endif 198cdf0e10cSrcweir strcat( envstr, libpath ); 199cdf0e10cSrcweir if ( freeLibpath != 0 ) 200cdf0e10cSrcweir { 201cdf0e10cSrcweir free( libpath ); 202cdf0e10cSrcweir } 203cdf0e10cSrcweir if ( value != NULL ) 204cdf0e10cSrcweir { 205cdf0e10cSrcweir strcat( envstr, PATHSEPARATOR ); 206cdf0e10cSrcweir strcat( envstr, value ); 207cdf0e10cSrcweir } 208cdf0e10cSrcweir putenv( envstr ); 209cdf0e10cSrcweir } 210cdf0e10cSrcweir else 211cdf0e10cSrcweir { 212bec0253dSJürgen Schmidt fprintf( stderr, "Warning: no office installation found!\n" ); 213cdf0e10cSrcweir fflush( stderr ); 214cdf0e10cSrcweir } 215cdf0e10cSrcweir 216cdf0e10cSrcweir /* set the executable name for the application process */ 217cdf0e10cSrcweir cmdname = createCommandName( argv[0] ); 218cdf0e10cSrcweir argv[0] = cmdname; 219cdf0e10cSrcweir 220cdf0e10cSrcweir /* 221cdf0e10cSrcweir * create the application process; 222cdf0e10cSrcweir * if successful, execvp doesn't return to the calling process 223cdf0e10cSrcweir */ 224cdf0e10cSrcweir execvp( cmdname, argv ); 225cdf0e10cSrcweir fprintf( stderr, "Error: execvp failed!\n" ); 226cdf0e10cSrcweir fflush( stderr ); 227cdf0e10cSrcweir 228cdf0e10cSrcweir return 0; 229cdf0e10cSrcweir } 230cdf0e10cSrcweir 231cdf0e10cSrcweir /* 232cdf0e10cSrcweir * Gets the path of a UNO installation. 233cdf0e10cSrcweir * 234cdf0e10cSrcweir * @return the installation path or NULL, if no installation was specified or 235cdf0e10cSrcweir * found, or if an error occured 236cdf0e10cSrcweir */ 237cdf0e10cSrcweir char const* getPath() 238cdf0e10cSrcweir { 239cdf0e10cSrcweir char const* path = cppuhelper_detail_findSofficePath(); 240cdf0e10cSrcweir 241cdf0e10cSrcweir if ( path == NULL ) 242cdf0e10cSrcweir { 243*2e9bc605SJürgen Schmidt fprintf( stderr, "Warning: getting path from PATH environment variable failed!\n" ); 244cdf0e10cSrcweir fflush( stderr ); 245cdf0e10cSrcweir } 246cdf0e10cSrcweir 247cdf0e10cSrcweir return path; 248cdf0e10cSrcweir } 249cdf0e10cSrcweir 250cdf0e10cSrcweir /* 251cdf0e10cSrcweir * Creates the application's executable file name. 252cdf0e10cSrcweir * 253cdf0e10cSrcweir * <p>The application's executable file name is the name of this executable 254cdf0e10cSrcweir * prefixed by '_'.</p> 255cdf0e10cSrcweir * 256cdf0e10cSrcweir * @param argv0 specifies the argv[0] parameter of the main function 257cdf0e10cSrcweir * 258cdf0e10cSrcweir * @return the application's executable file name or NULL, if an error occured 259cdf0e10cSrcweir */ 260cdf0e10cSrcweir char* createCommandName( char* argv0 ) 261cdf0e10cSrcweir { 262cdf0e10cSrcweir const char* CMDPREFIX = "_"; 263cdf0e10cSrcweir const char* prgname = NULL; 264cdf0e10cSrcweir 265cdf0e10cSrcweir char* cmdname = NULL; 266cdf0e10cSrcweir char* sep = NULL; 267cdf0e10cSrcweir Dl_info dl_info; 268cdf0e10cSrcweir int pos; 269cdf0e10cSrcweir 270cdf0e10cSrcweir /* get the executable file name from argv0 */ 271cdf0e10cSrcweir prgname = argv0; 272cdf0e10cSrcweir 273cdf0e10cSrcweir /* 274cdf0e10cSrcweir * if argv0 doesn't contain an absolute path name, try to get the absolute 275cdf0e10cSrcweir * path name from dladdr; note that this only works for Solaris, not for 276cdf0e10cSrcweir * Linux 277cdf0e10cSrcweir */ 278cdf0e10cSrcweir if ( argv0 != NULL && *argv0 != SEPARATOR && 279cdf0e10cSrcweir dladdr( (void*) &createCommandName, &dl_info ) && 280cdf0e10cSrcweir dl_info.dli_fname != NULL && *dl_info.dli_fname == SEPARATOR ) 281cdf0e10cSrcweir { 282cdf0e10cSrcweir prgname = dl_info.dli_fname; 283cdf0e10cSrcweir } 284cdf0e10cSrcweir 285cdf0e10cSrcweir /* prefix the executable file name by '_' */ 286cdf0e10cSrcweir if ( prgname != NULL ) 287cdf0e10cSrcweir { 288cdf0e10cSrcweir cmdname = (char*) malloc( strlen( prgname ) + strlen( CMDPREFIX ) + 1 ); 289cdf0e10cSrcweir sep = strrchr( prgname, SEPARATOR ); 290cdf0e10cSrcweir if ( sep != NULL ) 291cdf0e10cSrcweir { 292cdf0e10cSrcweir pos = ++sep - prgname; 293cdf0e10cSrcweir strncpy( cmdname, prgname, pos ); 294cdf0e10cSrcweir cmdname[ pos ] = '\0'; 295cdf0e10cSrcweir strcat( cmdname, CMDPREFIX ); 296cdf0e10cSrcweir strcat( cmdname, sep ); 297cdf0e10cSrcweir } 298cdf0e10cSrcweir else 299cdf0e10cSrcweir { 300cdf0e10cSrcweir strcpy( cmdname, CMDPREFIX ); 301cdf0e10cSrcweir strcat( cmdname, prgname ); 302cdf0e10cSrcweir } 303cdf0e10cSrcweir } 304cdf0e10cSrcweir 305cdf0e10cSrcweir return cmdname; 306cdf0e10cSrcweir } 307