blob: 8d13853f492e15452454c9b18f25b02a6369db16 [file] [log] [blame]
#include "installOS.h"
#include "installShm.h"
#include "installConfig.h"
#include "log.h"
#include "extract.h"
#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#include <strings.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <stddef.h>
#ifndef boolean
#define boolean int
#endif
#define MAX_PATH_LENGTH 2000
#define MAX_SHARED_LENGTH (16 * 1024)
#ifdef _WIN32
#define LOG_FILE _T_INSTALL("C:\\rcpinstall.log")
#else
#define LOG_FILE _T_INSTALL("/tmp/rcpinstall.log")
#endif
/* Global Variables */
_TCHAR* officialName = NULL;
/* Global Data */
static _TCHAR* program = NULL; /* full pathname of the program */
static _TCHAR* temporaryDir = NULL; /* temporary directory where files extracted */
static _TCHAR* javaVM = NULL; /* full pathname of the Java VM to run */
static _TCHAR* jarFile = NULL; /* full pathname of the startup jar file to run */
static _TCHAR* sharedID = NULL; /* ID for the shared memory */
static _TCHAR* sharedSplashID = NULL; /* ID for the shared memory */
/* Define the maximum time (in seconds) for the splash window to remain visible. */
static _TCHAR* splashTimeout = _T_INSTALL("600"); /* 10 minutes */
/* Define error messages. (non-NLS) */
static _TCHAR* exitMsg = _T_INSTALL("JVM terminated. Exit code=%d\n%s");
static _TCHAR* pathMsg = _T_INSTALL("%s\n'%s' in your current PATH");
static _TCHAR* showMsg = _T_INSTALL("Could not load splash bitmap:\n%s");
static _TCHAR* shareMsg = _T_INSTALL("No shared data available.");
static _TCHAR* noVMMsg =
_T_INSTALL("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* configName = _T_INSTALL("install.ini");
static _TCHAR* splashName = _T_INSTALL("splash.bmp");
#define DEFAULT_STARTUP _T_INSTALL("install.jar")
/* Define constants for the options recognized by the launcher. */
#define CONSOLE _T_INSTALL("-console")
#define CONSOLELOG _T_INSTALL("-consoleLog")
#define DEBUG _T_INSTALL("-debug")
#define LOG _T_INSTALL("-log")
#define OS _T_INSTALL("-os")
#define OSARCH _T_INSTALL("-arch")
#define NOSPLASH _T_INSTALL("-nosplash")
#define LAUNCHER _T_INSTALL("-launcher")
#define SHOWSPLASH _T_INSTALL("-showsplash")
#define ENDSPLASH _T_INSTALL("-endsplash")
#define EXITDATA _T_INSTALL("-exitdata")
#define STARTUP _T_INSTALL("-startup")
#define VM _T_INSTALL("-vm")
#define WS _T_INSTALL("-ws")
#define NAME _T_INSTALL("-name")
#define VMARGS _T_INSTALL("-vmargs") /* special option processing required */
/* 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 log = 0; /* True: enable logging */
static int noSplash = 0; /* True: do not show splash win */
static _TCHAR* osArg = _T_INSTALL(DEFAULT_OS);
static _TCHAR* osArchArg = _T_INSTALL(DEFAULT_OS_ARCH);
static _TCHAR* showSplashArg = NULL; /* showsplash data (main launcher window) */
static _TCHAR* exitDataArg = NULL;
static _TCHAR * startupArg = DEFAULT_STARTUP; /* 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* wsArg = _T_INSTALL(DEFAULT_WS); /* the SWT supported GUI to be used */
static _TCHAR* name = NULL; /* program name */
static _TCHAR** userVMarg = NULL; /* user specific args for the Java VM */
static _TCHAR* endSplashArg = NULL;
/* Define a table for processing command line options. */
typedef struct
{
_TCHAR* name; /* the option recognized by the launcher */
_TCHAR** value; /* the variable where the option value is saved */
int* flag; /* the variable that is set if the option is defined */
int remove; /* the number of argments to remove from the list */
} Option;
static Option options[] = {
{ CONSOLE, NULL, &needConsole, 0 },
{ CONSOLELOG, NULL, &needConsole, 0 },
{ DEBUG, NULL, &debug, 0 },
{ LOG, NULL, &log, 0 },
{ NOSPLASH, NULL, &noSplash, 1 },
{ OS, &osArg, NULL, 2 },
{ OSARCH, &osArchArg, NULL, 2 },
// { SHOWSPLASH, &showSplashArg, NULL, 2 },
{ ENDSPLASH, &endSplashArg, NULL, 2 },
// { EXITDATA, &exitDataArg, NULL, 2 },
// { STARTUP, &startupArg, NULL, 2 },
{ VM, &vmName, NULL, 2 },
{ NAME, &name, NULL, 2 },
{ WS, &wsArg, NULL, 2 } };
static int optionsSize = (sizeof(options) / sizeof(options[0]));
static int configArgc = 0;
static _TCHAR** configArgv = NULL;
/* Define the required VM arguments (all platforms). */
static _TCHAR* jar = _T_INSTALL("-jar");
static _TCHAR** reqVMarg[] = { &jar, &jarFile, NULL };
/* Local methods */
static int createUserArgs(int configArgc, _TCHAR **configArgv, int *argc, _TCHAR ***argv);
static void parseArgs( int* argc, _TCHAR* argv[] );
static _TCHAR** parseArgList( _TCHAR *data );
static void freeArgList( _TCHAR** data );
static _TCHAR** getVMCommand( int argc, _TCHAR* argv[] );
_TCHAR* findCommand( _TCHAR* command );
static _TCHAR* formatVmCommandMsg( _TCHAR* args[] );
_TCHAR* getProgramDir();
static _TCHAR* getDefaultOfficialName();
static int isMainInstall( int argc, _TCHAR **argv );
#ifdef _WIN32
#ifdef UNICODE
extern int main(int, char**);
int mainW(int, wchar_t**);
int wmain( int argc, wchar_t** argv ) {
OSVERSIONINFOW info;
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
/*
* If the OS supports UNICODE functions, run the UNICODE version
* of the main function. Otherwise, convert the arguments to
* MBCS and run the ANSI version of the main function.
*/
if (!GetVersionExW (&info)) {
int i, result;
char **newArgv = malloc(argc * sizeof(char *));
for (i=0; i<argc; i++) {
wchar_t *oldArg = argv[i];
int byteCount = WideCharToMultiByte (CP_ACP, 0, oldArg, -1, NULL, 0, NULL, NULL);
char *newArg = malloc(byteCount+1);
newArg[byteCount] = 0;
WideCharToMultiByte (CP_ACP, 0, oldArg, -1, newArg, byteCount, NULL, NULL);
newArgv[i] = newArg;
}
result = main(argc, newArgv);
for (i=0; i<argc; i++) {
free(newArgv[i]);
}
free(newArgv);
return result;
}
return mainW(argc, argv);
}
#define main mainW
#endif /* UNICODE */
#endif /* _WIN32 */
int main( int argc, _TCHAR* argv[] )
{
_TCHAR* splashBitmap = NULL;
_TCHAR* data;
_TCHAR* shippedVM = NULL;
_TCHAR* vmSearchPath = NULL;
_TCHAR** vmCommand = NULL;
_TCHAR** vmCommandList = NULL;
_TCHAR** vmCommandArgs = NULL;
_TCHAR* vmCommandMsg = NULL;
_TCHAR* errorMsg;
int exitCode;
_TCHAR* configFile = NULL;
struct _stat stats;
boolean isMain;
/* Determine the full pathname of this program. */
#ifdef _WIN32
program = malloc( MAX_PATH_LENGTH + 1 );
GetModuleFileName( NULL, program, MAX_PATH_LENGTH );
#else
program = findCommand( argv[0] );
if (program == NULL)
{
program = malloc( strlen( argv[0] ) + 1 );
strcpy( program, argv[0] );
}
#endif
/* Parse command line arguments (looking for the VM to use). */
/* Override configuration file arguments */
parseArgs( &argc, argv );
/* Special case - user arguments specified in the config file
* are appended to the user arguments passed from the command line.
*/
if (configArgc > 1)
{
createUserArgs(configArgc, configArgv, &argc, &argv);
}
if ( isMain = isMainInstall(argc, argv) )
{
int error;
if ( log ) createLog(LOG_FILE);
logFormatS(_T_INSTALL("\tINSTALL_FILE = %s"),program);
temporaryDir = getTempPath();
logFormatS(_T_INSTALL("\tTEMPORARY_DIR = %s"),temporaryDir);
writeLog(_T_INSTALL("[i] Creating TEMPORARY_DIR"));
if ( _tmkdir(temporaryDir) != 0 )
{
writeLog(_T_INSTALL("[x] Failed to create TEMPORARY_DIR"));
exit( 1 );
}
//****************extract config and splash files first****************************
error = extractFile(program,temporaryDir,configName);
if ( error != 0 ) {
cleanup();
exit( error );
}
error = extractFile(program,temporaryDir,splashName);
if ( error != 0 ) {
cleanup();
exit( error );
}
//****************old implementation******************************
/* error = extract(program,temporaryDir);
if ( error != 0 ) {
cleanup();
exit( error );
}
*/
configFile = malloc((_tcslen(temporaryDir)+_tcslen(configName))*sizeof(_TCHAR));
_tcscpy(configFile,temporaryDir);
_tcscat(configFile,configName);
if (_tstat( configFile, &stats ) == 0)
{
logFormatS(_T_INSTALL("\tCONFIG_FILE = %s"),configFile);
writeLog(_T_INSTALL("[i] Reading CONFIG_FILE"));
/* Parse configuration file arguments */
if ( readConfigFile(configFile, argv[0], &configArgc, &configArgv) == 0 )
{
writeLog(_T_INSTALL("[i] Parsing CONFIG_FILE options"));
parseArgs (&configArgc, configArgv);
}
}
if ( configFile != NULL )
free(configFile);
}
/* Initialize official program name */
officialName = name != NULL ? _tcsdup( name ) : getDefaultOfficialName();
/* Initialize the window system. */
initWindowSystem( &argc, argv, (showSplashArg != NULL) );
/* If the exit data option was given, set exit data */
if (exitDataArg != NULL)
{
/* If an extra argument was given, use it as the exit data, otherwise clear exit data */
data = argc > 1 ? argv[1] : NULL;
if (data != NULL && _tcslen( data ) > MAX_SHARED_LENGTH - 1)
{
exitCode = EINVAL;
}
else {
exitCode = setSharedData( exitDataArg, data );
}
if (exitCode != 0 && debug) displayMessage( shareMsg );
exit( exitCode );
}
if ( endSplashArg != NULL )
{
exitCode = setSharedData( endSplashArg, ENDSPLASH );
if (exitCode != 0 && debug) displayMessage( shareMsg );
exit( exitCode );
}
/* If the showsplash option was given */
if ( isMain && !noSplash )
{
/* look for splash */
splashBitmap = malloc((_tcslen(temporaryDir)+_tcslen(splashName))*sizeof(_TCHAR));
_tcscpy(splashBitmap,temporaryDir);
_tcscat(splashBitmap,splashName);
if (_tstat( splashBitmap, &stats ) == 0)
{
logFormatS(_T_INSTALL("\tSPLASH_FILE = %s"),splashBitmap);
writeLog(_T_INSTALL("[i] Showing SPLASH_FILE"));
exitCode = showSplash( NULL, splashBitmap );
if (exitCode && debug)
{
errorMsg = malloc( (_tcslen(showMsg) + _tcslen(splashBitmap) + 10) * sizeof(_TCHAR) );
_stprintf( errorMsg, showMsg, splashBitmap );
displayMessage( errorMsg );
free( errorMsg );
} else {
if (createSharedData( &sharedSplashID, MAX_SHARED_LENGTH )) {
if (debug) {
displayMessage( shareMsg );
}
exit(1);
}
}
}
} else if ( showSplashArg != NULL && argc > 1)
{
splashBitmap = _tcsdup(argv[1]);
exitCode = showSplash( showSplashArg, splashBitmap );
if (exitCode && debug)
{
errorMsg = malloc( (_tcslen(showMsg) + _tcslen(splashBitmap) + 10) * sizeof(_TCHAR) );
_stprintf( errorMsg, showMsg, splashBitmap );
displayMessage( errorMsg );
free( errorMsg );
}
exit( exitCode );
}
/* If the user did not specify a VM to be used */
if (vmName == NULL)
{
/* Determine which type of VM should be used. */
vmName = ((debug || needConsole) ? consoleVM : defaultVM);
/* Try to find the VM shipped with installer. */
shippedVM = malloc( (_tcslen( temporaryDir ) + _tcslen( shippedVMDir ) + _tcslen( vmName ) + 10) * sizeof(_TCHAR) );
_stprintf( shippedVM, _T_INSTALL("%s%s%s"), temporaryDir, shippedVMDir, vmName );
javaVM = findCommand( shippedVM );
/* Format a message to indicate the default VM search path. */
vmSearchPath = malloc( (_tcslen( pathMsg ) + _tcslen( shippedVM ) + _tcslen( vmName ) + 10) * sizeof(_TCHAR) );
_stprintf( vmSearchPath, pathMsg, shippedVM, vmName );
free( shippedVM );
shippedVM = NULL;
}
/* If a Java VM has not been found yet */
if (javaVM == NULL)
{
/* Either verify the VM specified by the user or
attempt to find the VM in the user's PATH. */
javaVM = findCommand( vmName );
/* If the VM was not found, display a message and exit. */
if (javaVM == NULL)
{
if (vmSearchPath != NULL) vmName = vmSearchPath; /* used default VM searching */
errorMsg = malloc( (_tcslen(noVMMsg) + _tcslen(officialName) + _tcslen(vmName) + 10) * sizeof(_TCHAR) );
_stprintf( errorMsg, noVMMsg, officialName, vmName );
cleanup();
displayMessage( errorMsg );
free( errorMsg );
exit(1);
}
}
logFormatS(_T_INSTALL("\tJAVA_VM = %s"),javaVM);
if (createSharedData( &sharedID, MAX_SHARED_LENGTH )) {
if (debug) {
displayMessage( shareMsg );
}
}
//******************************
if ( isMain )
{
int error = extract(program,temporaryDir);
if ( error != 0 ) {
cleanup();
exit( error );
}
}
//*******************************
/* Construct the absolute name of the startup jar */
jarFile = malloc( (_tcslen( temporaryDir ) + _tcslen( startupArg ) + 1) * sizeof( _TCHAR ) );
jarFile = _tcscpy( jarFile, temporaryDir );
jarFile = _tcscat( jarFile, startupArg );
logFormatS(_T_INSTALL("\tSTARTUP_JAR = %s"),jarFile);
/* If the file does not exist, treat the argument as an absolute path */
if (_tstat( jarFile, &stats ) != 0)
{
/* TODO: no STARTUP_JAR */
writeLog(_T_INSTALL("[x] Failed to find STARTUP_JAR"));
}
/* Get the command to start the Java VM. */
vmCommandArgs = getVMCommand( argc, argv );
/* While the Java VM should be restarted */
vmCommand = vmCommandArgs;
while (vmCommand != NULL)
{
vmCommandMsg = formatVmCommandMsg( vmCommand );
if ( debug ) logFormatS(_T_INSTALL("\tVM_COMMAND = %s"),vmCommandMsg);
writeLog(_T_INSTALL("[i] Starting JAVA_VM"));
exitCode = startJavaVM( vmCommand );
logFormatI(_T_INSTALL("[i] Process JAVA_VM completes with exitcode #%i"),exitCode);
switch( exitCode ) {
case 0:
vmCommand = NULL;
break;
default:
vmCommand = NULL;
errorMsg = NULL;
if (getSharedData( sharedID, &errorMsg ) == 0) {
if (_tcslen( errorMsg ) == 0) {
free( errorMsg );
errorMsg = NULL;
}
} else {
if (debug) displayMessage( shareMsg );
}
if (errorMsg == NULL) {
errorMsg = malloc( (_tcslen(exitMsg) + _tcslen(vmCommandMsg) + 10) * sizeof(_TCHAR) );
_stprintf( errorMsg, exitMsg, exitCode, vmCommandMsg );
}
displayMessage( errorMsg );
free( errorMsg );
break;
}
free( vmCommandMsg );
}
/* Cleanup time. */
cleanup();
writeLog(_T_INSTALL("[i] Deleting TEMPORARY_DIR"));
_trmdir(temporaryDir);
free( jarFile );
free( splashBitmap );
free( temporaryDir );
free( program );
if ( vmSearchPath != NULL ) free( vmSearchPath );
if ( vmCommandList != NULL ) freeArgList( vmCommandList );
if ( configArgv != NULL ) freeConfig( configArgv );
if (configArgc > 1) free( argv );
free( officialName );
if ( sharedID != NULL ) {
if (destroySharedData( sharedID ) != 0) {
if (debug) displayMessage( shareMsg );
}
free( sharedID );
}
if ( sharedSplashID != NULL ) {
if (destroySharedData( sharedSplashID ) != 0) {
if (debug) displayMessage( shareMsg );
}
free( sharedSplashID );
}
return 0;
}
int isEndSplash()
{
_TCHAR* end;
if (getSharedData( sharedSplashID, &end ) == 0) {
if (_tcscmp( end, ENDSPLASH ) == 0) {
free( end );
setSharedData( sharedSplashID, _T_INSTALL("") );
writeLog(_T_INSTALL("[i] Hide SPLASH_FILE"));
return 1;
}
free( end );
}
return 0;
}
/* Return 1 if the current process is the process that starts the java VM
* Return 0 if it is an process used to display a splash screen or to write
* data to a shared memory segment.
* The main process is the only one that reads the .ini file.
*/
static int isMainInstall( int argc, _TCHAR **argv )
{
/* It is the main program if the argument 3 is neither SHOWSPLASH|ENDSPLASH nor EXITDATA */
// if (argc < 4) return 1;
// return (_tcsicmp( argv[3], SHOWSPLASH ) != 0 && _tcsicmp( argv[3], ENDSPLASH ) != 0 && _tcsicmp( argv[3], EXITDATA ) != 0);
return (exitDataArg == NULL) && (endSplashArg == NULL);
}
/*
* 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 ];
}
/* If the option is recognized by the launcher */
if (option != NULL)
{
/* If the option requires a value and there is one, extract the value. */
if (option->value != NULL && (index+1) < *pArgc)
*option->value = argv[ index+1 ];
/* If the option requires a flag to be set, set it. */
if (option->flag != NULL)
*option->flag = 1;
remArgs = option->remove;
}
/* All of the remaining arguments are user VM args. */
else if (_tcsicmp( argv[ index ], VMARGS ) == 0)
{
userVMarg = &argv[ index+1 ];
argv[ index ] = NULL;
*pArgc = index;
}
/* 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;
}
}
}
/*
* Create a new array containing user arguments from the config file first and
* from the command line second.
* Allocate an array large enough to host all the strings passed in from
* the argument configArgv and argv. That array is passed back to the
* argv argument. That array must be freed with the regular free().
* Note that both arg lists are expected to contain the argument 0 from the C
* main method. That argument contains the path/executable name. It is
* only copied once in the resulting list.
*
* Returns 0 if success.
*/
static int createUserArgs(int configArgc, _TCHAR **configArgv, int *argc, _TCHAR ***argv)
{
_TCHAR** newArray = (_TCHAR **)malloc((configArgc + *argc) * sizeof(_TCHAR *));
memcpy(newArray, configArgv, configArgc * sizeof(_TCHAR *));
/* Skip the argument zero (program path and name) */
memcpy(newArray + configArgc, *argv + 1, (*argc - 1) * sizeof(_TCHAR *));
/* Null terminate the new list of arguments and return it. */
*argv = newArray;
*argc += configArgc - 1;
(*argv)[*argc] = NULL;
return 0;
}
/*
* Free the memory allocated by parseArgList().
*/
static void freeArgList( _TCHAR** data ) {
if (data == NULL) return;
free( data [0] );
free( data );
}
/*
* Parse the data into a list of arguments separarted by \n.
*
* The list of strings returned by this function must be freed with
* freeArgList().
*/
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_INSTALL('\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_INSTALL('\n') )) != NULL) {
execArg[ dst++ ] = ch1;
ch2[ 0 ] = _T_INSTALL('\0');
ch1 = ch2 + 1;
}
if (ch1 != data + length) execArg[ dst++ ] = ch1;
execArg[ dst++ ] = NULL;
return execArg;
}
/*
* Find the absolute pathname to where a command resides.
*
* The string returned by the function must be freed.
*/
#define EXTRA 20
_TCHAR* findCommand( _TCHAR* command )
{
_TCHAR* cmdPath;
int length;
_TCHAR* ch;
_TCHAR* dir;
_TCHAR* path;
struct _stat stats;
/* If the command was an abolute pathname, use it as is. */
if (command[0] == dirSeparator ||
(_tcslen( command ) > 2 && command[1] == _T_INSTALL(':')))
{
length = _tcslen( command );
cmdPath = malloc( (length + EXTRA) * sizeof(_TCHAR) ); /* add extra space for a possible ".exe" extension */
_tcscpy( cmdPath, command );
}
else
{
/* If the command string contains a path separator */
if (_tcschr( command, dirSeparator ) != NULL)
{
/* It must be relative to the current directory. */
length = MAX_PATH_LENGTH + EXTRA + _tcslen( command );
cmdPath = malloc( length * sizeof (_TCHAR));
_tgetcwd( cmdPath, length );
if (cmdPath[ _tcslen( cmdPath ) - 1 ] != dirSeparator)
{
length = _tcslen( cmdPath );
cmdPath[ length ] = dirSeparator;
cmdPath[ length+1 ] = _T_INSTALL('\0');
}
_tcscat( cmdPath, command );
}
/* else the command must be in the PATH somewhere */
else
{
/* Get the directory PATH where executables reside. */
path = _tgetenv( _T_INSTALL("PATH") );
if (!path)
{
return NULL;
}
else
{
length = _tcslen( path ) + _tcslen( command ) + MAX_PATH_LENGTH;
cmdPath = malloc( length * sizeof(_TCHAR));
/* Foreach directory in the PATH */
dir = path;
while (dir != NULL && *dir != _T_INSTALL('\0'))
{
ch = _tcschr( dir, pathSeparator );
if (ch == NULL)
{
_tcscpy( cmdPath, dir );
}
else
{
length = ch - dir;
_tcsncpy( cmdPath, dir, length );
cmdPath[ length ] = _T_INSTALL('\0');
ch++;
}
dir = ch; /* advance for the next iteration */
#ifdef _WIN32
/* Remove quotes */
if (_tcschr( cmdPath, _T_INSTALL('"') ) != NULL)
{
int i = 0, j = 0, c;
length = _tcslen( cmdPath );
while (i < length) {
c = cmdPath[ i++ ];
if (c == _T_INSTALL('"')) continue;
cmdPath[ j++ ] = c;
}
cmdPath[ j ] = _T_INSTALL('\0');
}
#endif
/* Determine if the executable resides in this directory. */
if (cmdPath[0] == _T_INSTALL('.') &&
(_tcslen(cmdPath) == 1 || (_tcslen(cmdPath) == 2 && cmdPath[1] == dirSeparator)))
{
_tgetcwd( cmdPath, MAX_PATH_LENGTH );
}
if (cmdPath[ _tcslen( cmdPath ) - 1 ] != dirSeparator)
{
length = _tcslen( cmdPath );
cmdPath[ length ] = dirSeparator;
cmdPath[ length+1 ] = _T_INSTALL('\0');
}
_tcscat( cmdPath, command );
/* If the file is not a directory and can be executed */
if (_tstat( cmdPath, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0)
{
/* Stop searching */
dir = NULL;
}
}
}
}
}
#ifdef _WIN32
/* If the command does not exist */
if (_tstat( cmdPath, &stats ) != 0 || (stats.st_mode & S_IFREG) == 0)
{
/* If the command does not end with .exe, append it an try again. */
length = _tcslen( cmdPath );
if (length > 4 && _tcsicmp( &cmdPath[ length - 4 ], _T_INSTALL(".exe") ) != 0)
_tcscat( cmdPath, _T_INSTALL(".exe") );
}
#endif
/* Verify the resulting command actually exists. */
if (_tstat( cmdPath, &stats ) != 0 || (stats.st_mode & S_IFREG) == 0)
{
free( cmdPath );
cmdPath = NULL;
}
/* Return the absolute command pathname. */
return cmdPath;
}
/*
* 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.
*/
static _TCHAR** getVMCommand( int argc, _TCHAR* argv[] )
{
_TCHAR** defVMarg;
int nDefVMarg = 0;
int nReqVMarg = 0;
int nUserVMarg = 0;
int totalArgs;
_TCHAR** execArg;
int src;
int dst;
/* Calculate the number of user VM arguments. */
if (userVMarg != NULL)
{
while (userVMarg[ nUserVMarg ] != NULL)
nUserVMarg++;
}
/* Calculate the number of default VM arguments. */
defVMarg = getArgVM( javaVM );
while (defVMarg[ nDefVMarg ] != NULL)
nDefVMarg++;
/* Calculate the number of required VM arguments. */
while (reqVMarg[ nReqVMarg ] != NULL)
nReqVMarg++;
/* Allocate the arg list for the exec call.
* (VM + userVMargs + defaultVMargs + requiredVMargs + OS <os> + WS <ws> + ARCH <arch> + LAUNCHER <launcher> + NAME <officialName> +
* + [SHOWSPLASH <cmd> | ENDSPLASH <cmd>] + EXITDATA <cmd> + argv[] + VM + <vm> + VMARGS + userVMargs + defaultVMargs + requiredVMargs
* + NULL)
*/
totalArgs = 1 + nUserVMarg + nDefVMarg + nReqVMarg + 2 + 2 + 2 + 2 + 2 + 2 + 2 + argc + 2 + 1 + nUserVMarg + nDefVMarg + nReqVMarg + 1;
execArg = malloc( totalArgs * sizeof( _TCHAR* ) );
dst = 0;
execArg[ dst++ ] = javaVM;
/* If the user specified "-vmargs", add them instead of the default VM args. */
if (userVMarg != NULL)
{
for (src = 0; src < nUserVMarg; src++)
execArg[ dst++ ] = userVMarg[ src ];
}
else
{
for (src = 0; src < nDefVMarg; src++)
execArg[ dst++ ] = defVMarg[ src ];
}
/* For each required VM arg */
for (src = 0; src < nReqVMarg; src++)
execArg[ dst++ ] = *(reqVMarg[ src ]);
/* Append the required options. */
execArg[ dst++ ] = OS;
execArg[ dst++ ] = osArg;
execArg[ dst++ ] = WS;
execArg[ dst++ ] = wsArg;
execArg[ dst++ ] = OSARCH;
execArg[ dst++ ] = osArchArg;
/* Append the launcher command */
execArg[ dst++ ] = LAUNCHER;
execArg[ dst++ ] = program;
/* Append the name command */
execArg[ dst++ ] = NAME;
execArg[ dst++ ] = officialName;
/* Append the show splash window command, if defined. */
if (!noSplash)
{
if ( sharedSplashID == NULL )
{
execArg[ dst++ ] = SHOWSPLASH;
execArg[ dst++ ] = splashTimeout;
} else {
execArg[ dst++ ] = ENDSPLASH;
execArg[ dst++ ] = sharedSplashID;
}
}
/* Append the exit data command. */
if (sharedID) {
execArg[ dst++ ] = EXITDATA;
execArg[ dst++ ] = sharedID;
}
/* Append the remaining user defined arguments. */
for (src = 1; src < argc; src++)
{
execArg[ dst++ ] = argv[ src ];
}
/* Append VM and VMARGS to be able to relaunch using exit data. */
execArg[ dst++ ] = VM;
execArg[ dst++ ] = javaVM;
execArg[ dst++ ] = VMARGS;
/* If the user specified "-vmargs", add them instead of the default VM args. */
if (userVMarg != NULL)
{
for (src = 0; src < nUserVMarg; src++)
execArg[ dst++ ] = userVMarg[ src ];
}
else
{
for (src = 0; src < nDefVMarg; src++)
execArg[ dst++ ] = defVMarg[ src ];
}
/* For each required VM arg */
for (src = 0; src < nReqVMarg; src++)
execArg[ dst++ ] = *(reqVMarg[ src ]);
execArg[ dst++ ] = NULL;
return execArg;
}
/* 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.
*/
static _TCHAR* formatVmCommandMsg( _TCHAR* args[] )
{
int index;
int length;
_TCHAR* ch;
_TCHAR* message;
/* Determine the length of the message buffer. */
length = 0;
for (index = 0; args[index] != NULL; index++)
{
length += _tcslen(args[index]) + 1;
}
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;
for (index = 0; args[index] != NULL; index++)
{
if (args[index][0] == _T_INSTALL('-') && *(ch-1) == _T_INSTALL(' '))
*(ch-1) = _T_INSTALL('\n');
_tcscpy( ch, args[index] );
ch += _tcslen( args[index] );
*ch++ = _T_INSTALL(' ');
}
*ch = _T_INSTALL('\0');
return message;
}
/*
* Determine the default official application name
*
*/
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_INSTALL('.'));
if (extension != NULL)
{
*extension = _T_INSTALL('\0');
}
}
#endif
/* Upper case the first character */
#ifndef LINUX
{
*ch = _totupper(*ch);
}
#else
{
if (*ch >= 'a' && *ch <= 'z')
{
*ch -= 32;
}
}
#endif
return ch;
}
_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_INSTALL('\0');
return programDir;
}
free( programDir );
return NULL;
}