| /******************************************************************************* |
| * Copyright (c) 2000, 2007 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Kevin Cornell (Rational Software Corporation) |
| * Markus Schorn (Wind River Systems), bug 193340 |
| *******************************************************************************/ |
| |
| /* Eclipse Program Launcher |
| * |
| * This file forms the base of the eclipse_*.dll/so. This dll is loaded by eclipse.exe |
| * to start a Java VM, or alternatively it is loaded from Java to show the splash |
| * screen or write to the shared memory. See eclipseJNI.c for descriptions of the methods |
| * exposed to the Java program using JNI. |
| * |
| * To display a splash screen before starting the java vm, the launcher should be started |
| * with the location of the splash bitmap to use: |
| * -showsplash <path/to/splash.bmp> |
| * Otherwise, when the Java program starts, it should determine the location of |
| * the splash bitmap to be used and use the JNI method show_splash. |
| * |
| * When the Java program initialization is complete, the splash window |
| * is brought down by calling the JNI method takedown_splash. |
| * |
| * The Java program can also call the get_splash_handle method to get the handle to the splash |
| * window. This can be passed to SWT to create SWT widgets in the splash screen. |
| * |
| * The Java application will receive two other arguments: |
| * -exitdata <shared memory id> |
| * |
| * The java program can call set_exit_data with this shared-memory-id |
| * to provide specific exit data to the launcher. |
| * |
| * The exit data size must not exceed MAX_SHARED_LENGTH which is |
| * 16Kb. The interpretation of the exit data is dependent on the |
| * exit value of the java application. |
| * |
| * The main launcher recognizes the following exit codes from the |
| * Java application: |
| * |
| * 0 - Exit normally. |
| * RESTART_LAST_EC = 23 |
| * - restart the java VM again with the same arguments as the previous one. |
| * RESTART_NEW_EC = 24 |
| * - restart the java VM again with the arguments taken from the exit data. |
| * The exit data format is a list of arguments separated by '\n'. The Java |
| * application should build this list using the arguments passed to it on |
| * startup. See below. |
| * |
| * Additionally, if the Java application exits with an exit code other than the |
| * ones above, the main launcher will display an error message with the contents |
| * of the exit data. If the exit data is empty, a generic error message is |
| * displayed. The generic error message shows the exit code and the arguments |
| * passed to the Java application. |
| * |
| * The options that can be specified by the user to the launcher are: |
| * -vm <javaVM> the Java VM to be used |
| * -os <opSys> the operating system being run on |
| * -arch <osArch> the hardware architecture of the OS: x86, sparc, hp9000 |
| * -ws <gui> the window system to be used: win32, motif, gtk, ... |
| * -nosplash do not display the splash screen. The java application will |
| * not receive the -showsplash command. |
| * -showsplash <bitmap> show the given bitmap in the splash screen. |
| * -name <name> application name displayed in error message dialogs and |
| * splash screen window. Default value is computed from the |
| * name of the executable - with the first letter capitalized |
| * if possible. e.g. eclipse.exe defaults to the name Eclipse. |
| * -startup <startup.jar> the startup jar to execute. The argument is first assumed to be |
| * relative to the path of the launcher. If such a file does not |
| * exist, the argument is then treated as an absolute path. |
| * The default is find the plugins/org.eclipse.equinox.launcher jar |
| * with the highest version number. |
| * The jar must contain an org.eclipse.equinox.launcher.Main class. |
| * (unless JNI invocation is not being used, then the jar only needs to be |
| * an executable jar) |
| * -library the location of the eclipse launcher shared library (this library) to use |
| * By default, the launcher exe (see eclipseMain.c) finds |
| * <userArgs> arguments that are passed along to the Java application |
| * (i.e, -data <path>, -debug, -console, -consoleLog, etc) |
| * -vmargs <userVMargs> ... a list of arguments for the VM itself |
| * |
| * The -vmargs option and all user specified VM arguments must appear |
| * at the end of the command line, after all arguments that are |
| * being passed to Java application. |
| * |
| * The argument order for the new Java VM process is as follows: |
| * |
| * <javaVM> <all VM args> |
| * -os <user or default OS value> |
| * -ws <user or default WS value> |
| * -arch <user or default ARCH value> |
| * -launcher <absolute launcher name> |
| * -name <application name> |
| * -library <eclipse library location> |
| * -startup <startup.jar location> |
| * [-showsplash] |
| * [-exitdata <shared memory id>] |
| * <userArgs> |
| * -vm <javaVM> |
| * -vmargs <all VM args> |
| * |
| * where: |
| * <all VM args> = |
| * [<defaultVMargs | <userVMargs>] |
| * -jar |
| * <startup jar full path> |
| * |
| * The startup jar must be an executable jar. |
| * |
| * |
| * See "Main.java" for a simple implementation of the Java |
| * application. |
| * |
| * Configuration file |
| * The launcher gets arguments from the command line and/or from a configuration file. |
| * The configuration file must have the same name and location as the launcher executable |
| * and the extension .ini. For example, the eclipse.ini configuration file must be |
| * in the same folder as the eclipse.exe or eclipse executable. |
| * The format of the ini file matches that of the command line arguments - one |
| * argument per line. |
| * In general, the settings of the config file are expected to be overriden by the |
| * command line. |
| * - launcher arguments (-os, -arch...) set in the config file are overriden by the command line |
| * - the -vmargs from the command line replaces in its entirety the -vmargs from the config file. |
| * - user arguments from the config file are prepended to the user arguments defined in the |
| * config file. This is consistent with the java behaviour in the following case: |
| * java -Dtest="one" -Dtest="two" ... : test is set to the value "two" |
| */ |
| |
| #include "eclipseOS.h" |
| #include "eclipseUtil.h" |
| #include "eclipseShm.h" |
| #include "eclipseJNI.h" |
| #include "eclipseConfig.h" |
| #include "eclipseCommon.h" |
| |
| #ifdef _WIN32 |
| #include <windows.h> |
| #include <direct.h> |
| #include <io.h> |
| #include <fcntl.h> |
| #else |
| #include <unistd.h> |
| #include <strings.h> |
| #endif |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <locale.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <errno.h> |
| #include <ctype.h> |
| |
| #define MAX_PATH_LENGTH 2000 |
| #define MAX_SHARED_LENGTH (16 * 1024) |
| |
| /* Global Data */ |
| static _TCHAR* program = NULL; /* full pathname of the program */ |
| static _TCHAR* programDir = NULL; /* directory where program resides */ |
| static _TCHAR* javaVM = NULL; /* full pathname of the Java VM to run */ |
| static _TCHAR* jniLib = NULL; /* full path of a java vm library for JNI invocation */ |
| static _TCHAR* jarFile = NULL; /* full pathname of the startup jar file to run */ |
| static _TCHAR* sharedID = NULL; /* ID for the shared memory */ |
| static _TCHAR* officialName = NULL; |
| |
| _TCHAR* exitData = NULL; /* exit data set from Java */ |
| int initialArgc; |
| _TCHAR** initialArgv = NULL; |
| |
| |
| /* Define the special exit codes returned from Eclipse. */ |
| #define RESTART_LAST_EC 23 |
| #define RESTART_NEW_EC 24 |
| |
| /* constants for launch mode */ |
| #define LAUNCH_JNI 1 |
| #define LAUNCH_EXE 2 |
| |
| #define DEFAULT_EE _T_ECLIPSE("default.ee") |
| |
| /* Define error messages. (non-NLS) */ |
| static _TCHAR* exitMsg = _T_ECLIPSE("JVM terminated. Exit code=%d\n%s"); |
| static _TCHAR* goVMMsg = _T_ECLIPSE("Start VM: %s\n"); |
| static _TCHAR* pathMsg = _T_ECLIPSE("%s in your current PATH"); |
| static _TCHAR* shareMsg = _T_ECLIPSE("No exit data available."); |
| static _TCHAR* noVMMsg = |
| _T_ECLIPSE("A Java Runtime Environment (JRE) or Java Development Kit (JDK)\n\ |
| must be available in order to run %s. No Java virtual machine\n\ |
| was found after searching the following locations:\n\ |
| %s"); |
| static _TCHAR* startupMsg = |
| _T_ECLIPSE("The %s executable launcher was unable to locate its \n\ |
| companion launcher jar."); |
| |
| static _TCHAR* homeMsg = |
| _T_ECLIPSE("The %s executable launcher was unable to locate its \n\ |
| home directory."); |
| |
| #define OLD_STARTUP _T_ECLIPSE("startup.jar") |
| #define CLASSPATH_PREFIX _T_ECLIPSE("-Djava.class.path=") |
| |
| /* Define constants for the options recognized by the launcher. */ |
| #define CONSOLE _T_ECLIPSE("-console") |
| #define CONSOLELOG _T_ECLIPSE("-consoleLog") |
| #define DEBUG _T_ECLIPSE("-debug") |
| #define OS _T_ECLIPSE("-os") |
| #define OSARCH _T_ECLIPSE("-arch") |
| #define NOSPLASH _T_ECLIPSE("-nosplash") |
| #define LAUNCHER _T_ECLIPSE("-launcher") |
| #define SHOWSPLASH _T_ECLIPSE("-showsplash") |
| #define EXITDATA _T_ECLIPSE("-exitdata") |
| #define STARTUP _T_ECLIPSE("-startup") |
| #define VM _T_ECLIPSE("-vm") |
| #define WS _T_ECLIPSE("-ws") |
| #define NAME _T_ECLIPSE("-name") |
| #define VMARGS _T_ECLIPSE("-vmargs") /* special option processing required */ |
| #define CP _T_ECLIPSE("-cp") |
| #define CLASSPATH _T_ECLIPSE("-classpath") |
| #define JAR _T_ECLIPSE("-jar") |
| |
| #define LIBRARY _T_ECLIPSE("--launcher.library") |
| #define SUPRESSERRORS _T_ECLIPSE("--launcher.suppressErrors") |
| #define INI _T_ECLIPSE("--launcher.ini") |
| #define SECOND_THREAD _T_ECLIPSE("--launcher.secondThread") |
| #define PERM_GEN _T_ECLIPSE("--launcher.XXMaxPermSize") |
| |
| #define XXPERMGEN _T_ECLIPSE("-XX:MaxPermSize=") |
| |
| /* constants for ee options file */ |
| #define EE_EXECUTABLE _T_ECLIPSE("-Dee.executable=") |
| #define EE_CONSOLE _T_ECLIPSE("-Dee.executable.console=") |
| #define EE_VM_LIBRARY _T_ECLIPSE("-Dee.vm.library=") |
| #define EE_LIBRARY_PATH _T_ECLIPSE("-Dee.library.path=") |
| #define EE_HOME _T_ECLIPSE("-Dee.home=") |
| #define EE_FILENAME _T_ECLIPSE("-Dee.filename=") |
| |
| /* Define the variables to receive the option values. */ |
| static int needConsole = 0; /* True: user wants a console */ |
| static int debug = 0; /* True: output debugging info */ |
| static int noSplash = 0; /* True: do not show splash win */ |
| static int suppressErrors = 0; /* True: do not display errors dialogs */ |
| int secondThread = 0; /* True: start the VM on a second thread */ |
| |
| static _TCHAR* showSplashArg = NULL; /* showsplash data (main launcher window) */ |
| static _TCHAR* splashBitmap = NULL; /* the actual splash bitmap */ |
| static _TCHAR * startupArg = NULL; /* path of the startup.jar the user wants to run relative to the program path */ |
| static _TCHAR* vmName = NULL; /* Java VM that the user wants to run */ |
| static _TCHAR* name = NULL; /* program name */ |
| static _TCHAR* library = NULL; /* the shared library */ |
| static _TCHAR* permGen = NULL; /* perm gen size for sun */ |
| |
| /* variables for ee options */ |
| static _TCHAR* eeExecutable = NULL; |
| static _TCHAR* eeConsole = NULL; |
| static _TCHAR* eeLibrary = NULL; |
| _TCHAR* eeLibPath = NULL; /* this one is global so others can see it */ |
| |
| /* Define a table for processing command line options. */ |
| typedef struct |
| { |
| _TCHAR* name; /* the option recognized by the launcher */ |
| void* value; /* the variable where the option value is saved */ |
| /* value is a _TCHAR** or int* depending on if VALUE_IS_FLAG is set */ |
| int flag; /* flags */ |
| int remove; /* the number of argments to remove from the list */ |
| } Option; |
| |
| /* flags for the Option struct */ |
| #define VALUE_IS_FLAG 1 /* value is an int*, if not set, value is a _TCHAR** */ |
| #define OPTIONAL_VALUE 2 /* value is optional, if next arg does not start with '-', */ |
| /* don't assign it and only remove (remove - 1) arguments */ |
| |
| /* flags being used by EE options */ |
| #define EE_ADJUST_PATH 4 /* value is a path, do processing on relative paths to try and make them absolute */ |
| #define EE_PATH_LIST 8 /* value is a list of paths */ |
| |
| static Option options[] = { |
| { CONSOLE, &needConsole, VALUE_IS_FLAG, 0 }, |
| { CONSOLELOG, &needConsole, VALUE_IS_FLAG, 0 }, |
| { DEBUG, &debug, VALUE_IS_FLAG, 0 }, |
| { NOSPLASH, &noSplash, VALUE_IS_FLAG, 1 }, |
| { SUPRESSERRORS, &suppressErrors, VALUE_IS_FLAG, 1}, |
| { SECOND_THREAD, &secondThread, VALUE_IS_FLAG, 1 }, |
| { LIBRARY, NULL, 0, 2 }, /* library was parsed by exe, just remove it */ |
| { INI, NULL, 0, 2 }, /* same with ini */ |
| { OS, &osArg, 0, 2 }, |
| { OSARCH, &osArchArg, 0, 2 }, |
| { SHOWSPLASH, &showSplashArg, OPTIONAL_VALUE, 2 }, |
| { STARTUP, &startupArg, 0, 2 }, |
| { VM, &vmName, 0, 2 }, |
| { NAME, &name, 0, 2 }, |
| { PERM_GEN, &permGen, 0, 2 }, |
| { WS, &wsArg, 0, 2 } }; |
| static int optionsSize = (sizeof(options) / sizeof(options[0])); |
| |
| static Option eeOptions[] = { |
| { EE_EXECUTABLE, &eeExecutable, EE_ADJUST_PATH, 0 }, |
| { EE_CONSOLE, &eeConsole, EE_ADJUST_PATH, 0 }, |
| { EE_VM_LIBRARY, &eeLibrary, EE_ADJUST_PATH, 0 }, |
| { EE_LIBRARY_PATH, &eeLibPath, EE_ADJUST_PATH | EE_PATH_LIST, 0 } |
| }; |
| static int eeOptionsSize = (sizeof(eeOptions) / sizeof(eeOptions[0])); |
| |
| /* Define the required VM arguments (all platforms). */ |
| static _TCHAR* cp = NULL; |
| static _TCHAR* cpValue = NULL; |
| static _TCHAR** reqVMarg[] = { &cp, &cpValue, NULL }; /* required VM args */ |
| static _TCHAR** userVMarg = NULL; /* user specific args for the Java VM */ |
| static _TCHAR** eeVMarg = NULL; /* vm args specified in ee file */ |
| static int nEEargs = 0; |
| |
| /* Local methods */ |
| static void parseArgs( int* argc, _TCHAR* argv[] ); |
| static void getVMCommand( int argc, _TCHAR* argv[], _TCHAR **vmArgv[], _TCHAR **progArgv[] ); |
| static int determineVM(_TCHAR** msg); |
| static int processEEProps(_TCHAR* eeFile); |
| static _TCHAR** buildLaunchCommand( _TCHAR* program, _TCHAR** vmArgs, _TCHAR** progArgs ); |
| static _TCHAR** parseArgList( _TCHAR *data ); |
| static _TCHAR* formatVmCommandMsg( _TCHAR* args[], _TCHAR* vmArgs[], _TCHAR* progArgs[] ); |
| static _TCHAR* getDefaultOfficialName(); |
| static _TCHAR* findStartupJar(); |
| static _TCHAR* findSplash(_TCHAR* splashArg); |
| static _TCHAR** getRelaunchCommand( _TCHAR **vmCommand ); |
| |
| #ifdef _WIN32 |
| static void createConsole(); |
| #endif |
| |
| /* Record the arguments that were used to start the original executable */ |
| JNIEXPORT void setInitialArgs(int argc, _TCHAR** argv, _TCHAR* lib) { |
| initialArgc = argc; |
| initialArgv = argv; |
| library = lib; |
| } |
| |
| /* this method must match the RunMethod typedef in eclipseMain.c */ |
| /* vmArgs must be NULL terminated */ |
| JNIEXPORT int run(int argc, _TCHAR* argv[], _TCHAR* vmArgs[]) |
| { |
| _TCHAR** vmCommand = NULL; |
| _TCHAR** vmCommandArgs = NULL; |
| _TCHAR** progCommandArgs = NULL; |
| _TCHAR** relaunchCommand = NULL; |
| _TCHAR* errorMsg = NULL, *msg = NULL; |
| int exitCode = 0; |
| int launchMode; |
| int running = 1; |
| |
| /* arg[0] should be the full pathname of this program. */ |
| program = _tcsdup( argv[0] ); |
| |
| /* Parse command line arguments (looking for the VM to use). */ |
| /* Override configuration file arguments */ |
| parseArgs( &argc, argv ); |
| |
| /* Initialize official program name */ |
| officialName = name != NULL ? _tcsdup( name ) : getDefaultOfficialName(); |
| |
| /* Initialize the window system. */ |
| initWindowSystem( &argc, argv, !noSplash ); |
| |
| /* Find the directory where the Eclipse program is installed. */ |
| programDir = getProgramDir(); |
| if (programDir == NULL) |
| { |
| if (!suppressErrors) { |
| errorMsg = malloc( (_tcslen(homeMsg) + _tcslen(officialName) + 10) * sizeof(_TCHAR) ); |
| _stprintf( errorMsg, homeMsg, officialName ); |
| displayMessage( officialName, errorMsg ); |
| free( errorMsg ); |
| } |
| exit( 1 ); |
| } |
| |
| /* platform specific processing of user's vmargs */ |
| processVMArgs(&vmArgs); |
| launchMode = determineVM(&msg); |
| if (launchMode == -1) { |
| /* problem */ |
| if (!suppressErrors) { |
| errorMsg = malloc((_tcslen(noVMMsg) + _tcslen(officialName) + _tcslen(msg) + 1) * sizeof(_TCHAR)); |
| _stprintf( errorMsg, noVMMsg, officialName, msg ); |
| displayMessage( officialName, errorMsg ); |
| free( errorMsg ); |
| } |
| free( msg ); |
| exit(1); |
| } |
| |
| /* Find the startup.jar */ |
| jarFile = findStartupJar(); |
| if(jarFile == NULL) { |
| if (!suppressErrors) { |
| errorMsg = malloc( (_tcslen(startupMsg) + _tcslen(officialName) + 10) * sizeof(_TCHAR) ); |
| _stprintf( errorMsg, startupMsg, officialName ); |
| displayMessage( officialName, errorMsg ); |
| free( errorMsg ); |
| } |
| exit( 1 ); |
| } |
| |
| #ifdef _WIN32 |
| if( launchMode == LAUNCH_JNI && (debug || needConsole) ) { |
| createConsole(); |
| } |
| #endif |
| |
| /* If the showsplash option was given and we are using JNI */ |
| if (!noSplash && showSplashArg && launchMode == LAUNCH_JNI) |
| { |
| splashBitmap = findSplash(showSplashArg); |
| if (splashBitmap != NULL) { |
| showSplash(splashBitmap); |
| } |
| } |
| |
| /* not using JNI launching, need some shared data */ |
| if (launchMode == LAUNCH_EXE && createSharedData( &sharedID, MAX_SHARED_LENGTH )) { |
| if (debug && !suppressErrors) { |
| displayMessage( officialName, shareMsg ); |
| } |
| } |
| |
| /* the startup jarFile goes on the classpath */ |
| if (launchMode == LAUNCH_JNI) { |
| /* JNI launching, classpath is set using -Djava.class.path */ |
| cp = malloc((_tcslen(CLASSPATH_PREFIX) + _tcslen(jarFile) + 1) * sizeof(_TCHAR)); |
| cp = _tcscpy(cp, CLASSPATH_PREFIX); |
| _tcscat(cp, jarFile); |
| } else { |
| /* exec java, jar is specified with -jar */ |
| cp = JAR; |
| cpValue = malloc((_tcslen(jarFile) + 1) * sizeof(_TCHAR)); |
| _tcscpy(cpValue, jarFile); |
| } |
| |
| /* Get the command to start the Java VM. */ |
| userVMarg = vmArgs; |
| getVMCommand( argc, argv, &vmCommandArgs, &progCommandArgs ); |
| |
| if (launchMode == LAUNCH_EXE) { |
| vmCommand = buildLaunchCommand(javaVM, vmCommandArgs, progCommandArgs); |
| } |
| |
| /* While the Java VM should be restarted */ |
| while(running) |
| { |
| msg = formatVmCommandMsg( vmCommand, vmCommandArgs, progCommandArgs ); |
| if (debug) _tprintf( goVMMsg, msg ); |
| |
| if(launchMode == LAUNCH_JNI) { |
| exitCode = startJavaVM(jniLib, vmCommandArgs, progCommandArgs); |
| } else { |
| exitCode = launchJavaVM(vmCommand); |
| } |
| |
| switch( exitCode ) { |
| case 0: /* normal exit */ |
| running = 0; |
| break; |
| case RESTART_LAST_EC: |
| if (launchMode == LAUNCH_JNI) { |
| /* copy for relaunch, +1 to ensure NULL terminated */ |
| relaunchCommand = malloc((initialArgc + 1) * sizeof(_TCHAR*)); |
| memcpy(relaunchCommand, initialArgv, (initialArgc + 1) * sizeof(_TCHAR*)); |
| relaunchCommand[initialArgc] = 0; |
| relaunchCommand[0] = program; |
| running = 0; |
| } |
| break; |
| |
| case RESTART_NEW_EC: |
| if(launchMode == LAUNCH_EXE) { |
| if (exitData != NULL) free(exitData); |
| getSharedData( sharedID, &exitData ); |
| } |
| if (exitData != 0) { |
| if (vmCommand != NULL) free( vmCommand ); |
| vmCommand = parseArgList( exitData ); |
| if (launchMode == LAUNCH_JNI) { |
| relaunchCommand = getRelaunchCommand(vmCommand); |
| running = 0; |
| } |
| } else { |
| running = 0; |
| if (debug && !suppressErrors) displayMessage( officialName, shareMsg ); |
| } |
| break; |
| default: { |
| _TCHAR *title = _tcsdup(officialName); |
| running = 0; |
| if(!suppressErrors) { |
| errorMsg = NULL; |
| if (launchMode == LAUNCH_EXE) { |
| if (exitData != NULL) free(exitData); |
| getSharedData( sharedID, &exitData ); |
| } |
| if (exitData != 0) { |
| errorMsg = exitData; |
| exitData = NULL; /* keep exit data from being free'd twice */ |
| if (_tcslen( errorMsg ) == 0) { |
| free( errorMsg ); |
| errorMsg = NULL; |
| } else { |
| _TCHAR *str; |
| if (_tcsncmp(errorMsg, _T_ECLIPSE("<title>"), _tcslen(_T_ECLIPSE("<title>"))) == 0) { |
| str = _tcsstr(errorMsg, _T_ECLIPSE("</title>")); |
| if (str != NULL) { |
| free( title ); |
| str[0] = _T_ECLIPSE('\0'); |
| title = _tcsdup( errorMsg + _tcslen(_T_ECLIPSE("<title>")) ); |
| str = _tcsdup( str + _tcslen(_T_ECLIPSE("</title>")) ); |
| free( errorMsg ); |
| errorMsg = str; |
| } |
| } |
| } |
| } else { |
| if (debug) displayMessage( title, shareMsg ); |
| } |
| if (errorMsg == NULL) { |
| errorMsg = malloc( (_tcslen(exitMsg) + _tcslen(msg) + 10) * sizeof(_TCHAR) ); |
| _stprintf( errorMsg, exitMsg, exitCode, msg ); |
| } |
| displayMessage( title, errorMsg ); |
| free( errorMsg ); |
| } |
| free( title ); |
| break; |
| } |
| } |
| free( msg ); |
| } |
| |
| if(relaunchCommand != NULL) |
| restartLauncher(NULL, relaunchCommand); |
| |
| if (launchMode == LAUNCH_JNI) |
| cleanupVM(exitCode); |
| |
| if (sharedID != NULL) { |
| destroySharedData( sharedID ); |
| free( sharedID ); |
| } |
| |
| /* Cleanup time. */ |
| free( vmCommandArgs ); |
| free( progCommandArgs ); |
| free( jarFile ); |
| free( programDir ); |
| free( program ); |
| free( officialName ); |
| if ( vmCommand != NULL ) free( vmCommand ); |
| if ( launchMode == LAUNCH_JNI ) free( cp ); |
| if ( cpValue != NULL) free( cpValue ); |
| if ( exitData != NULL ) free( exitData ); |
| if ( splashBitmap != NULL ) free( splashBitmap ); |
| |
| return exitCode; |
| } |
| |
| static _TCHAR** buildLaunchCommand( _TCHAR* program, _TCHAR** vmArgs, _TCHAR** progArgs ) { |
| int nVM = -1, nProg = -1; |
| _TCHAR** result; |
| |
| while(vmArgs[++nVM] != NULL) {} |
| while(progArgs[++nProg] != NULL) {} |
| |
| result = malloc((nVM + nProg + 2) * sizeof(_TCHAR*)); |
| memset(result, 0, (nVM + nProg + 2) * sizeof(_TCHAR*)); |
| result[0] = program; |
| memcpy(result + 1, vmArgs, nVM * sizeof(_TCHAR*)); |
| memcpy(result + 1 + nVM, progArgs, nProg * sizeof(_TCHAR*)); |
| return result; |
| } |
| /* |
| * Parse arguments of the command. |
| */ |
| static void parseArgs( int* pArgc, _TCHAR* argv[] ) |
| { |
| Option* option; |
| int remArgs; |
| int index; |
| int i; |
| |
| /* Ensure the list of user argument is NULL terminated. */ |
| /*argv[ *pArgc ] = NULL;*/ |
| |
| /* For each user defined argument (excluding the program) */ |
| for (index = 1; index < *pArgc; index++){ |
| remArgs = 0; |
| |
| /* Find the corresponding argument is a option supported by the launcher */ |
| option = NULL; |
| for (i = 0; option == NULL && i < optionsSize; i++) |
| { |
| if (_tcsicmp( argv[ index ], options[ i ].name ) == 0) { |
| option = &options[ i ]; |
| break; |
| } |
| } |
| |
| /* If the option is recognized by the launcher */ |
| if (option != NULL) |
| { |
| int optional = 0; |
| /* If the option requires a value and there is one, extract the value. */ |
| if (option->value != NULL) { |
| if (option->flag & VALUE_IS_FLAG) |
| *((int *)option->value) = 1; |
| else if((index + 1) < *pArgc) { |
| _TCHAR * next = argv[index + 1]; |
| if(!((option->flag & OPTIONAL_VALUE) && next[0] == _T_ECLIPSE('-'))) { |
| *((_TCHAR**)option->value) = next; |
| } else { |
| /* value was optional, and the next arg starts with '-' */ |
| optional = 1; |
| } |
| } |
| } |
| |
| /* If the option requires a flag to be set, set it. */ |
| remArgs = option->remove - optional; |
| } |
| |
| /* Remove any matched arguments from the list. */ |
| if (remArgs > 0) |
| { |
| for (i = (index + remArgs); i <= *pArgc; i++) |
| { |
| argv[ i - remArgs ] = argv[ i ]; |
| } |
| index--; |
| *pArgc -= remArgs; |
| } |
| } |
| } |
| |
| /* |
| * Parse the data into a list of arguments separated by \n. |
| */ |
| static _TCHAR** parseArgList( _TCHAR* data ) { |
| int totalArgs = 0, dst = 0, length; |
| _TCHAR *ch1, *ch2, **execArg; |
| length = _tcslen( data ); |
| ch1 = ch2 = data; |
| while ((ch2 = _tcschr( ch1, _T_ECLIPSE('\n') )) != NULL) { |
| totalArgs++; |
| ch1 = ch2 + 1; |
| } |
| if (ch1 != data + length) totalArgs++; |
| execArg = malloc( (totalArgs + 1) * sizeof( _TCHAR* ) ); |
| ch1 = ch2 = data; |
| while ((ch2 = _tcschr( ch1, _T_ECLIPSE('\n') )) != NULL) { |
| execArg[ dst++ ] = ch1; |
| ch2[ 0 ] = _T_ECLIPSE('\0'); |
| ch1 = ch2 + 1; |
| } |
| if (ch1 != data + length) execArg[ dst++ ] = ch1; |
| execArg[ dst++ ] = NULL; |
| return execArg; |
| } |
| |
| static void adjustVMArgs( _TCHAR *vm, _TCHAR **vmArgv[] ) { |
| /* Sun VMs need some extra perm gen space */ |
| if (isSunVM(vm) && permGen != NULL) { |
| int specified = 0, i = -1; |
| |
| /* first check to see if it is already specified */ |
| while ( (*vmArgv)[++i] != NULL) { |
| /* we are also counting the number of args here */ |
| if (!specified && _tcsncmp((*vmArgv)[i], XXPERMGEN, _tcslen(XXPERMGEN)) == 0) { |
| specified = 1; |
| } |
| } |
| |
| if (!specified) { |
| _TCHAR ** oldArgs = *vmArgv; |
| _TCHAR *newArg = malloc((_tcslen(XXPERMGEN) + _tcslen(permGen) + 1) * sizeof(_TCHAR)); |
| _stprintf(newArg, _T_ECLIPSE("%s%s"), XXPERMGEN, permGen); |
| |
| *vmArgv = malloc((i + 2) * sizeof(_TCHAR *)); |
| memcpy(*vmArgv, oldArgs, i * sizeof(_TCHAR *)); |
| (*vmArgv)[i] = newArg; |
| (*vmArgv)[i + 1] = 0; |
| } |
| } |
| } |
| /* |
| * Get the command and arguments to start the Java VM. |
| * |
| * Memory allocated by this function is assumed to be |
| * deallocated when the program terminates. |
| * |
| * Some of the arguments returned by this function were |
| * passed directly from the main( argv ) array so they |
| * should not be deallocated. |
| * |
| * Arguments are split into 2: vm arguments and program arguments |
| */ |
| static void getVMCommand( int argc, _TCHAR* argv[], _TCHAR **vmArgv[], _TCHAR **progArgv[] ) |
| { |
| _TCHAR** vmArg; |
| int nReqVMarg = 0; |
| int nVMarg = 0; |
| int totalVMArgs; |
| int totalProgArgs; |
| int src; |
| int dst; |
| |
| /* If the user specified "-vmargs", add them instead of the default VM args. */ |
| vmArg = (userVMarg != NULL) ? userVMarg : getArgVM( javaVM != NULL ? javaVM : jniLib ); |
| |
| adjustVMArgs(javaVM != NULL ? javaVM : jniLib, &vmArg); |
| |
| /* Calculate the number of VM arguments. */ |
| while (vmArg[ nVMarg ] != NULL) |
| nVMarg++; |
| |
| /* Calculate the number of required VM arguments. */ |
| while (reqVMarg[ nReqVMarg ] != NULL) |
| nReqVMarg++; |
| |
| /* VM argument list */ |
| totalVMArgs = nVMarg + nReqVMarg + nEEargs + 1; |
| *vmArgv = malloc( totalVMArgs * sizeof(_TCHAR*) ); |
| |
| dst = 0; |
| for (src = 0; src < nVMarg; src++){ |
| /*if the user specified a classpath, skip it */ |
| if(_tcscmp(vmArg[src], cp) == 0){ |
| src++; |
| continue; |
| } |
| (*vmArgv)[ dst++ ] = vmArg[ src ]; |
| } |
| |
| if (eeVMarg != NULL) |
| for (src = 0; src < nEEargs; src++) |
| (*vmArgv)[ dst++ ] = eeVMarg[ src ]; |
| |
| /* For each required VM arg */ |
| for (src = 0; src < nReqVMarg; src++) |
| if( *(reqVMarg[src]) != NULL) |
| (*vmArgv)[ dst++ ] = *(reqVMarg[ src ]); |
| |
| |
| (*vmArgv)[dst] = NULL; |
| |
| /* Program arguments */ |
| /* OS <os> + WS <ws> + ARCH <arch> + LAUNCHER <launcher> + NAME <officialName> + |
| * + LIBRARY <library> + SHOWSPLASH <cmd> + EXITDATA <cmd> + STARTUP <jar> + argv[] + VM + <vm> + |
| * VMARGS + vmArg + requiredVMargs |
| * + NULL) |
| */ |
| totalProgArgs = 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + argc + 2 + 1 + nVMarg + nEEargs + nReqVMarg + 1; |
| *progArgv = malloc( totalProgArgs * sizeof( _TCHAR* ) ); |
| dst = 0; |
| |
| /* Append the required options. */ |
| (*progArgv)[ dst++ ] = OS; |
| (*progArgv)[ dst++ ] = osArg; |
| (*progArgv)[ dst++ ] = WS; |
| (*progArgv)[ dst++ ] = wsArg; |
| if (_tcslen(osArchArg) > 0) { |
| (*progArgv)[ dst++ ] = OSARCH; |
| (*progArgv)[ dst++ ] = osArchArg; |
| } |
| |
| /* Append the show splash window command, if defined. */ |
| if (!noSplash) |
| { |
| (*progArgv)[ dst++ ] = SHOWSPLASH; |
| if(splashBitmap != NULL) |
| (*progArgv)[ dst++ ] = splashBitmap; |
| } |
| |
| /* Append the launcher command */ |
| (*progArgv)[ dst++ ] = LAUNCHER; |
| (*progArgv)[ dst++ ] = program; |
| |
| /* Append the name command */ |
| (*progArgv)[ dst++ ] = NAME; |
| (*progArgv)[ dst++ ] = officialName; |
| |
| /* And the shared library */ |
| if (library != NULL) { |
| (*progArgv)[ dst++ ] = LIBRARY; |
| (*progArgv)[ dst++ ] = library; |
| } |
| |
| /* the startup jar */ |
| (*progArgv)[ dst++ ] = STARTUP; |
| (*progArgv)[ dst++ ] = jarFile; |
| |
| /* Append the exit data command. */ |
| if (sharedID) { |
| (*progArgv)[ dst++ ] = EXITDATA; |
| (*progArgv)[ dst++ ] = sharedID; |
| } |
| |
| /* Append the remaining user defined arguments. */ |
| for (src = 1; src < argc; src++) |
| { |
| (*progArgv)[ dst++ ] = argv[ src ]; |
| } |
| |
| /* Append VM and VMARGS to be able to relaunch using exit data. */ |
| (*progArgv)[ dst++ ] = VM; |
| if(jniLib != NULL) |
| (*progArgv)[ dst++ ] = jniLib; |
| else |
| (*progArgv)[ dst++ ] = javaVM; |
| (*progArgv)[ dst++ ] = VMARGS; |
| |
| for (src = 0; src < nVMarg; src++) |
| (*progArgv)[ dst++ ] = vmArg[ src ]; |
| |
| if (eeVMarg != NULL) |
| for (src = 0; src < nEEargs; src++) |
| (*progArgv)[ dst++ ] = eeVMarg[ src ]; |
| |
| /* For each required VM arg */ |
| for (src = 0; src < nReqVMarg; src++) |
| if (*(reqVMarg[src]) != NULL) |
| (*progArgv)[ dst++ ] = *(reqVMarg[ src ]); |
| |
| (*progArgv)[ dst++ ] = NULL; |
| |
| } |
| |
| /* Format the JVM start command for error messages |
| * |
| * This method formats a string with the JVM start command (and all arguments) |
| * that can be used in displaying error messages. The string returned from this |
| * method is probably not NLS compliant and must be deallocated by the caller. |
| * |
| * The arguments in the message are either args (if not null) or the combination |
| * of vmArgs + progArgs |
| */ |
| static _TCHAR* formatVmCommandMsg( _TCHAR* args[], _TCHAR* vmArgs[], _TCHAR* progArgs[] ) |
| { |
| int index; |
| int length = 0; |
| _TCHAR** list; |
| _TCHAR* ch; |
| _TCHAR* message; |
| |
| /* Determine the length of the message buffer. */ |
| if(args != NULL) list = args; |
| else list = vmArgs; |
| while(list != NULL) { |
| for (index = 0; list[index] != NULL; index++) |
| { |
| length += _tcslen(list[index]) + 1; |
| } |
| if(list == vmArgs) list = progArgs; |
| else list = NULL; |
| } |
| message = malloc( (length + 5) * sizeof(_TCHAR) ); |
| |
| /* Format the message such that options (args starting with '-') begin |
| on a new line. Otherwise, the Motif MessageBox does not automatically wrap |
| the messages and the message window can extend beyond both sides of the display. */ |
| ch = message; |
| if(args != NULL) list = args; |
| else list = vmArgs; |
| while(list != NULL) { |
| for (index = 0; list[index] != NULL; index++) |
| { |
| if (list[index][0] == _T_ECLIPSE('-') && *(ch-1) == _T_ECLIPSE(' ')) |
| *(ch-1) = _T_ECLIPSE('\n'); |
| _tcscpy( ch, list[index] ); |
| ch += _tcslen( list[index] ); |
| *ch++ = _T_ECLIPSE(' '); |
| } |
| if(list == vmArgs) list = progArgs; |
| else list = NULL; |
| } |
| *ch = _T_ECLIPSE('\0'); |
| |
| return message; |
| } |
| |
| _TCHAR* getOfficialName() { |
| return officialName; |
| } |
| |
| /* |
| * Determine the default official application name |
| * |
| * This function provides the default application name that appears in a variety of |
| * places such as: title of message dialog, title of splash screen window |
| * that shows up in Windows task bar. |
| * It is computed from the name of the launcher executable and |
| * by capitalizing the first letter. e.g. "c:/ide/eclipse.exe" provides |
| * a default name of "Eclipse". |
| */ |
| static _TCHAR* getDefaultOfficialName() |
| { |
| _TCHAR *ch = NULL; |
| |
| /* Skip the directory part */ |
| ch = _tcsrchr( program, dirSeparator ); |
| if (ch == NULL) ch = program; |
| else ch++; |
| |
| ch = _tcsdup( ch ); |
| #ifdef _WIN32 |
| { |
| /* Search for the extension .exe and cut it */ |
| _TCHAR *extension = _tcsrchr(ch, _T_ECLIPSE('.')); |
| if (extension != NULL) |
| { |
| *extension = _T_ECLIPSE('\0'); |
| } |
| } |
| #endif |
| /* Upper case the first character */ |
| #ifndef LINUX |
| { |
| *ch = _totupper(*ch); |
| } |
| #else |
| { |
| if (*ch >= 'a' && *ch <= 'z') |
| { |
| *ch -= 32; |
| } |
| } |
| #endif |
| return ch; |
| } |
| |
| /* Determine the Program Directory |
| * |
| * This function takes the directory where program executable resides and |
| * determines the installation directory. |
| */ |
| _TCHAR* getProgramDir( ) |
| { |
| _TCHAR* ch; |
| _TCHAR* programDir; |
| |
| programDir = malloc( (_tcslen( program ) + 1) * sizeof(_TCHAR) ); |
| _tcscpy( programDir, program ); |
| ch = _tcsrchr( programDir, dirSeparator ); |
| if (ch != NULL) |
| { |
| *(ch+1) = _T_ECLIPSE('\0'); |
| return programDir; |
| } |
| |
| free( programDir ); |
| return NULL; |
| } |
| |
| static _TCHAR* findSplash(_TCHAR* splashArg) { |
| struct _stat stats; |
| _TCHAR *ch; |
| _TCHAR *path, *prefix; |
| int length; |
| |
| if (splashArg == NULL) |
| return NULL; |
| |
| splashArg = _tcsdup(splashArg); |
| length = _tcslen(splashArg); |
| /* _tstat doesn't seem to like dirSeparators on the end */ |
| while (splashArg[length - 1] == dirSeparator) { |
| splashArg[--length] = 0; |
| } |
| |
| /* does splashArg exist */ |
| if (_tstat(splashArg, &stats) == 0) { |
| /* pointing to a file */ |
| if (stats.st_mode & S_IFREG) { |
| /* file, use it*/ |
| return splashArg; |
| } else if (stats.st_mode & S_IFDIR) { |
| /*directory, look for splash.bmp*/ |
| ch = malloc( (length + 12) * sizeof(_TCHAR)); |
| _stprintf( ch, _T_ECLIPSE("%s%c%s"), splashArg, dirSeparator, _T_ECLIPSE("splash.bmp") ); |
| if (_tstat(ch, &stats) == 0 && stats.st_mode & S_IFREG) { |
| free(splashArg); |
| return ch; |
| } |
| free(ch); |
| } |
| free(splashArg); |
| return NULL; |
| } |
| |
| /* doesn't exist, separate into path & prefix and look for a /path/prefix_<version> */ |
| ch = _tcsrchr( splashArg, dirSeparator ); |
| if (ch != NULL) { |
| if (splashArg[0] == dirSeparator || (_tcslen(splashArg) > 2 && splashArg[1] == _T_ECLIPSE(':'))) |
| { /*absolute path*/ |
| path = _tcsdup(splashArg); |
| path[ch - splashArg] = 0; |
| } else { |
| /* relative path, prepend with programDir */ |
| path = malloc( (_tcslen(programDir) + ch - splashArg + 2) * sizeof(_TCHAR)); |
| *ch = 0; |
| _stprintf(path, _T_ECLIPSE("%s%c%s"), programDir, dirSeparator, splashArg); |
| *ch = dirSeparator; |
| } |
| prefix = _tcsdup(ch + 1); |
| } else { |
| /* No separator, treat splashArg as the prefix and look in the plugins dir */ |
| path = malloc( (_tcslen(programDir) + 9) * sizeof(_TCHAR)); |
| _stprintf(path, _T_ECLIPSE("%s%c%s"), programDir, dirSeparator, _T_ECLIPSE("plugins")); |
| prefix = _tcsdup(splashArg); |
| } |
| |
| ch = findFile(path, prefix); |
| free(path); |
| free(prefix); |
| free(splashArg); |
| if (ch != NULL) { |
| path = malloc((_tcslen(ch) + 12) * sizeof(_TCHAR)); |
| _stprintf( path, _T_ECLIPSE("%s%c%s"), ch, dirSeparator, _T_ECLIPSE("splash.bmp") ); |
| return path; |
| } |
| return NULL; |
| } |
| |
| static _TCHAR* findStartupJar(){ |
| _TCHAR * file, *ch; |
| _TCHAR * pluginsPath; |
| struct _stat stats; |
| int pathLength, progLength; |
| |
| if( startupArg != NULL ) { |
| /* startup jar was specified on the command line */ |
| ch = _tcsdup(startupArg); |
| /* check path will check relative paths against programDir and workingDir */ |
| file = checkPath(ch, programDir, 0); |
| if(file != ch) |
| free(ch); |
| /* check existence */ |
| if (_tstat( file, &stats ) != 0) { |
| free(file); |
| file = NULL; |
| } |
| return file; |
| } |
| |
| progLength = pathLength = _tcslen(programDir); |
| #ifdef MACOSX |
| pathLength += 9; |
| #endif |
| pluginsPath = malloc( (pathLength + 1 + 7 + 1) * sizeof(_TCHAR)); |
| _tcscpy(pluginsPath, programDir); |
| if(pluginsPath[progLength - 1] != dirSeparator) { |
| pluginsPath[progLength] = dirSeparator; |
| pluginsPath[progLength + 1] = 0; |
| } |
| #ifdef MACOSX |
| _tcscat(pluginsPath, _T_ECLIPSE("../../../")); |
| #endif |
| _tcscat(pluginsPath, _T_ECLIPSE("plugins")); |
| |
| /* equinox startup jar? */ |
| file = findFile(pluginsPath, DEFAULT_EQUINOX_STARTUP); |
| if(file != NULL) |
| return file; |
| |
| /* old startup.jar? */ |
| file = checkPath(OLD_STARTUP, programDir, 0); |
| if (_tstat( file, &stats ) == 0) |
| return (file == OLD_STARTUP) ? _tcsdup(OLD_STARTUP) : file; |
| |
| return NULL; |
| } |
| |
| /* |
| * Return the portion of the vmCommand that should be used for relaunching |
| * |
| * The memory allocated for the command array must be freed |
| */ |
| static _TCHAR ** getRelaunchCommand( _TCHAR **vmCommand ) |
| { |
| int i = -1, req = 0, begin = -1; |
| int idx = 0; |
| _TCHAR ** relaunch; |
| |
| if (vmCommand == NULL) return NULL; |
| while(vmCommand[++i] != NULL){ |
| if ( begin == -1 && _tcsicmp( vmCommand[i], *reqVMarg[req] ) == 0) { |
| if(reqVMarg[++req] == NULL || *reqVMarg[req] == NULL){ |
| begin = i + 1; |
| } |
| } |
| } |
| |
| relaunch = malloc((1 + i + 1) * sizeof(_TCHAR *)); |
| relaunch[idx++] = program; |
| if(begin == -1) { |
| begin = 1; |
| } |
| for (i = begin; vmCommand[i] != NULL; i++){ |
| if (_tcsicmp(vmCommand[i], SHOWSPLASH) == 0) { |
| /* remove if the next argument is not the bitmap to show */ |
| if(vmCommand[i + 1] != NULL && vmCommand[i + 1][0] == _T_ECLIPSE('-')) { |
| continue; |
| } |
| } else if(_tcsncmp(vmCommand[i], CLASSPATH_PREFIX, _tcslen(CLASSPATH_PREFIX)) == 0) { |
| /* skip -Djava.class.path=... */ |
| continue; |
| } |
| relaunch[idx++] = vmCommand[i]; |
| } |
| if(_tcsicmp(relaunch[idx - 1], VMARGS) == 0) |
| relaunch[idx - 1] = NULL; |
| relaunch[idx] = NULL; |
| return relaunch; |
| } |
| |
| #ifdef _WIN32 |
| static void createConsole() { |
| long stdHandle; |
| int conHandle; |
| FILE *fp; |
| |
| AllocConsole(); |
| |
| /* redirect stdout */ |
| stdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); |
| conHandle = _open_osfhandle(stdHandle, _O_TEXT); |
| if (conHandle != -1) { |
| fp = _fdopen(conHandle, "w"); |
| *stdout = *fp; |
| } |
| |
| /* redirect stdin */ |
| stdHandle = (long)GetStdHandle(STD_INPUT_HANDLE); |
| conHandle = _open_osfhandle(stdHandle, _O_TEXT); |
| if (conHandle != -1) { |
| fp = _fdopen(conHandle, "r"); |
| *stdin = *fp; |
| } |
| |
| /* stderr */ |
| stdHandle = (long)GetStdHandle(STD_ERROR_HANDLE); |
| conHandle = _open_osfhandle(stdHandle, _O_TEXT); |
| if (conHandle != -1) { |
| fp = _fdopen(conHandle, "r"); |
| *stderr = *fp; |
| } |
| } |
| #endif |
| |
| /* |
| * determine the vm to use. |
| * return LAUNCH_JNI for launching with JNI invocation API. jniLib contains the name of the library |
| * returh LAUNCH_EXE for execing java, javaVM contains the path to the exe |
| * return -1 if problem finding vm, the passed in msg points to the places we looked. Caller should free |
| * this memory. |
| */ |
| static int determineVM(_TCHAR** msg) { |
| _TCHAR* ch = NULL; |
| _TCHAR* result = NULL; |
| _TCHAR* vmSearchPath = NULL; |
| int type = 0; |
| |
| /* vmName is passed in on command line with -vm */ |
| if (vmName != NULL) { |
| int length = _tcslen(vmName); |
| /* remove the trailing separator */ |
| if (vmName[length - 1] == _T_ECLIPSE('/') || vmName[length - 1] == _T_ECLIPSE('\\')) { |
| vmName[length - 1] = 0; |
| } |
| |
| vmName = checkPath(vmName, programDir, 0); |
| type = checkProvidedVMType(vmName); |
| switch (type) { |
| case VM_DIRECTORY: |
| /* vmName is a directory, look for default.ee */ |
| ch = malloc((_tcslen(vmName) + 1 + _tcslen(DEFAULT_EE) + 1) * sizeof(_TCHAR)); |
| _stprintf( ch, _T_ECLIPSE("%s%c%s"), vmName, dirSeparator, DEFAULT_EE ); |
| |
| result = findCommand(ch); |
| free(ch); |
| if (result == NULL) { |
| /* No default.ee file, look for default VM */ |
| ch = malloc((_tcslen(vmName) + 1 + _tcslen(defaultVM) + 1) * sizeof(_TCHAR)); |
| _stprintf( ch, _T_ECLIPSE("%s%c%s"), vmName, dirSeparator, defaultVM ); |
| javaVM = findSymlinkCommand(ch, 0); |
| free(ch); |
| if (javaVM == NULL) { |
| /* No vm executable, look for library */ |
| ch = malloc((_tcslen(vmName) + 1 + _tcslen(vmLibrary) + 1) * sizeof(_TCHAR)); |
| _stprintf( ch, _T_ECLIPSE("%s%c%s"), vmName, dirSeparator, vmLibrary ); |
| jniLib = findVMLibrary(ch); |
| if (jniLib != ch) |
| free(ch); |
| if (jniLib != NULL) { |
| return LAUNCH_JNI; |
| } |
| /* found nothing, return error */ |
| *msg = malloc( (3 * (_tcslen(vmName) + 2) + _tcslen(DEFAULT_EE) + _tcslen(defaultVM) + _tcslen(vmLibrary) + 1) * sizeof(_TCHAR)); |
| _stprintf( *msg, _T_ECLIPSE("%s%c%s\n%s%c%s\n%s%c%s"), vmName, dirSeparator, DEFAULT_EE, |
| vmName, dirSeparator, defaultVM, |
| vmName, dirSeparator, vmLibrary); |
| return -1; |
| } |
| break; |
| } |
| |
| /* else default.ee does exist */ |
| vmName = result; |
| /* fall through to VM_EE_PROPS*/ |
| case VM_EE_PROPS: |
| if (processEEProps(vmName) != 0) { |
| *msg = _tcsdup(vmName); |
| return -1; |
| } |
| if (eeLibrary != NULL) { |
| jniLib = findVMLibrary(eeLibrary); |
| if (jniLib != NULL) |
| return LAUNCH_JNI; |
| } |
| |
| if (eeConsole != NULL && (debug || needConsole) ) { |
| javaVM = findSymlinkCommand(eeConsole, 0); |
| if (javaVM != NULL) |
| return LAUNCH_EXE; |
| } |
| |
| if (eeExecutable != NULL) { |
| javaVM = findSymlinkCommand(eeExecutable, 0); |
| if (javaVM != NULL) |
| return LAUNCH_EXE; |
| } |
| |
| *msg = _tcsdup(vmName); |
| return -1; |
| |
| case VM_LIBRARY: |
| ch = findCommand(vmName); |
| if(ch != NULL) { |
| jniLib = findVMLibrary(ch); |
| if (ch != jniLib) |
| free(ch); |
| return LAUNCH_JNI; |
| } |
| /* file didn't exist, error */ |
| if (_tcschr( vmName, dirSeparator ) == NULL) { |
| /* if vmName doesn't contain a dirSeparator, we looked on the path */ |
| *msg = malloc((_tcslen(pathMsg) + _tcslen(vmName)) * sizeof(_TCHAR)); |
| _stprintf( *msg, pathMsg,vmName ); |
| } else { |
| *msg = _tcsdup(vmName); |
| } |
| return -1; |
| |
| default: |
| /*otherwise, assume executable */ |
| javaVM = findSymlinkCommand(vmName, 0); |
| if(javaVM != NULL) { |
| #ifdef MACOSX |
| /* right now, we are always doing JNI on Mac */ |
| break; |
| #else |
| return LAUNCH_EXE; |
| #endif |
| } |
| /* file didn't exist, error */ |
| if (_tcschr( vmName, dirSeparator ) == NULL) { |
| /* if vmName doesn't contain a dirSeparator, we looked on the path */ |
| *msg = malloc((_tcslen(pathMsg) + _tcslen(vmName)) * sizeof(_TCHAR)); |
| _stprintf( *msg, pathMsg, vmName ); |
| } else { |
| *msg = _tcsdup(vmName); |
| } |
| return -1; |
| } |
| } |
| |
| if (vmName == NULL) { |
| /* no vm specified, Try to find the VM shipped with eclipse. */ |
| ch = malloc( (_tcslen( programDir ) + _tcslen( shippedVMDir ) + _tcslen( defaultVM ) + 10) * sizeof(_TCHAR) ); |
| _stprintf( ch, _T_ECLIPSE("%s%s%s"), programDir, shippedVMDir, defaultVM ); |
| vmSearchPath = _tcsdup(ch); |
| |
| javaVM = findSymlinkCommand( ch, 0 ); |
| free(ch); |
| } |
| |
| if (javaVM == NULL) { |
| /* vm not found yet, look for one on the search path, but don't resolve symlinks */ |
| javaVM = findSymlinkCommand(defaultVM, 0); |
| if (javaVM == NULL) { |
| /* can't find vm, error */ |
| ch = malloc( (_tcslen(pathMsg) + _tcslen(defaultVM) + 1) * sizeof(_TCHAR)); |
| _stprintf(ch, pathMsg, defaultVM); |
| |
| if(vmSearchPath != NULL) { |
| *msg = malloc((_tcslen(ch) + 1 + _tcslen(vmSearchPath) + 1) * sizeof(_TCHAR)); |
| _stprintf(*msg, _T_ECLIPSE("%s\n%s"), vmSearchPath, ch); |
| free(ch); |
| } else { |
| *msg = ch; |
| } |
| return -1; |
| } |
| } |
| |
| if (vmSearchPath != NULL) |
| free(vmSearchPath); |
| |
| #ifndef DEFAULT_JAVA_EXEC |
| /* resolve symlinks for finding the library */ |
| ch = resolveSymlinks(javaVM); |
| jniLib = findVMLibrary(ch); |
| if (ch != jniLib) |
| free(ch); |
| if (jniLib != NULL) |
| return LAUNCH_JNI; |
| #endif |
| |
| return LAUNCH_EXE; |
| } |
| |
| static int processEEProps(_TCHAR* eeFile) |
| { |
| _TCHAR ** argv; |
| _TCHAR * c1, * c2; |
| _TCHAR * eeDir; |
| int argc; |
| int index, i; |
| int matches = 0; |
| Option *option; |
| |
| if(readConfigFile(eeFile, &argc, &argv) != 0) |
| return -1; |
| |
| nEEargs = argc; |
| eeVMarg = argv; |
| |
| eeDir = _tcsdup(eeFile); |
| c1 = _tcsrchr( eeDir, dirSeparator ); |
| if (c1 != NULL) |
| { |
| *(c1+1) = _T_ECLIPSE('\0'); |
| } |
| |
| for (index = 0; index < argc; index++){ |
| /* Find the corresponding argument is a option supported by the launcher */ |
| option = NULL; |
| for (i = 0; option == NULL && i < eeOptionsSize; i++) |
| { |
| if (_tcsncmp( argv[index], eeOptions[i].name, _tcslen(eeOptions[i].name) ) == 0) { |
| option = &eeOptions[i]; |
| break; |
| } |
| } |
| if(option != NULL) { |
| ++matches; |
| if (option->flag & VALUE_IS_FLAG) |
| *((int*)option->value) = 1; |
| else { |
| c1 = malloc( (_tcslen(argv[index]) - _tcslen(option->name) + 1) *sizeof(_TCHAR)); |
| _tcscpy(c1, argv[index] + _tcslen(option->name)); |
| if (option->flag & EE_ADJUST_PATH && option->flag & EE_PATH_LIST) { |
| c2 = checkPathList(c1, eeDir, 1); |
| free(c1); |
| c1 = c2; |
| } else if (option->flag & EE_ADJUST_PATH) { |
| c2 = checkPath(c1, eeDir, 1); |
| if (c2 != c1) { |
| free(c1); |
| c1 = c2; |
| } |
| } |
| *((_TCHAR**)option->value) = c1; |
| } |
| if(matches == eeOptionsSize) |
| break; |
| } |
| } |
| /* set ee.home and ee.filename variables */ |
| argv = realloc(argv, (nEEargs + 2) * sizeof(_TCHAR*)); |
| |
| c1 = malloc( (_tcslen(EE_HOME) + _tcslen(eeFile) + 1) * sizeof(_TCHAR)); |
| _stprintf(c1, _T_ECLIPSE("%s%s"), EE_HOME, eeDir); |
| argv[nEEargs++] = c1; |
| |
| c1 = malloc( (_tcslen(EE_FILENAME) + _tcslen(eeFile) + 1) * sizeof(_TCHAR)); |
| _stprintf(c1, _T_ECLIPSE("%s%s"), EE_FILENAME, eeFile); |
| argv[nEEargs++] = c1; |
| |
| argv[nEEargs] = NULL; |
| |
| free(eeDir); |
| return 0; |
| } |