1 | /*
|
---|
2 | * Copyright (c) 2001, 2002 IBM Corp and others. All rights reserved.
|
---|
3 | * This file is made available under the terms of the Common Public License v1.0
|
---|
4 | * which accompanies this distribution, and is available at
|
---|
5 | * http://www.eclipse.org/legal/cpl-v10.html
|
---|
6 | *
|
---|
7 | * Contributors:
|
---|
8 | * Kevin Cornell (Rational Software Corporation)
|
---|
9 | */
|
---|
10 |
|
---|
11 |
|
---|
12 | /* Eclipse Program Launcher
|
---|
13 | *
|
---|
14 | * This program performs the launching of the eclipse program along
|
---|
15 | * with the splash window. If the splash window is to be displayed,
|
---|
16 | * the java application will receive two extra arguments:
|
---|
17 | * -showsplash <splashCommand>
|
---|
18 | *
|
---|
19 | * When the Java program starts, it should determine if a different
|
---|
20 | * version of the splash bitmaps are to be used (uses the feature mechanism).
|
---|
21 | * If feature specific bitmaps are to be used, the root directory where
|
---|
22 | * those bitmaps reside (e.g., <rootDir>/splash/<bitmapFile>) should be
|
---|
23 | * appended (in double quotes) to the splash command. If a directory is
|
---|
24 | * not appended, the Eclipse install directory is used.
|
---|
25 | *
|
---|
26 | * The Java program initiates the displaying of the splash window
|
---|
27 | * by executing the splash command as follows:
|
---|
28 | *
|
---|
29 | * String command = splashCommand;
|
---|
30 | * String directory = getFeatureRootDirectory();
|
---|
31 | * if (directory != null)
|
---|
32 | * command += " \"" + directory + "\"";
|
---|
33 | * Process splashProcess = Runtime.getRuntime().exec( command );
|
---|
34 | *
|
---|
35 | * When the Java program initialization is complete, the splash window
|
---|
36 | * is brought down by destroying the splash process as follows:
|
---|
37 | *
|
---|
38 | * splashProcess.destroy();
|
---|
39 | *
|
---|
40 | * Therefore, when the splash window is visible, there are actually three
|
---|
41 | * processes running:
|
---|
42 | * 1) the main launcher process
|
---|
43 | * 2) the Java VM process (Eclipse)
|
---|
44 | * 3) the splash window process.
|
---|
45 | *
|
---|
46 | * The Java application does not need to know the format of the
|
---|
47 | * <splashCommand> argument but the command format is:
|
---|
48 | * <fullPathOfLauncherProgram> -showsplash <magicNumber>
|
---|
49 | *
|
---|
50 | * In other words, another eclipse launcher program is run with
|
---|
51 | * the arguments "-showsplash" and some magic number. On Windows
|
---|
52 | * and Motif, the magic number is the ID of the top window that
|
---|
53 | * the main launcher program creates for its message processing loop.
|
---|
54 | *
|
---|
55 | * When the splash window process starts, it creates its own window
|
---|
56 | * for the bitmap and then sends a message back to the main launcher
|
---|
57 | * program (using the magic number) with either its bitmap window ID
|
---|
58 | * (Windows) or its process ID (Motif and Photon). The main launcher
|
---|
59 | * process then waits for the Java VM to exit. If the splash window
|
---|
60 | * is still being displayed or the splash process is still running,
|
---|
61 | * the main launcher process terminates it.
|
---|
62 | *
|
---|
63 | * If the Java VM exits with a specific exit code, the main launcher
|
---|
64 | * simply restarts the VM again with the same arguments.
|
---|
65 | *
|
---|
66 | * The options that can be specified by the user to the launcher:
|
---|
67 | * -vm <javaVM> the Java VM to be used
|
---|
68 | * -application <class> the starting workbench application class
|
---|
69 | * -os <opSys> the operating system being run on
|
---|
70 | * -arch <osArch> the hardware architecture of the OS: x86, sparc, hp9000
|
---|
71 | * -ws <gui> the window system to be used: win32, motif, gtk, ...
|
---|
72 | * -nosplash do not display the splash screen
|
---|
73 | * -vmargs <userVMarg> ... a list of arguments for the VM itself
|
---|
74 | *
|
---|
75 | * The -vmargs option and all user specified VM arguments must appear
|
---|
76 | * at the end of the command line, after all arguments that are
|
---|
77 | * being passed to Java application.
|
---|
78 | *
|
---|
79 | * The argument order for the new Java VM process is as follows:
|
---|
80 | *
|
---|
81 | * <javaVM> <wsVMargs> <userVMargs> <wsSpecificArgs> -application <class>
|
---|
82 | * [-showsplash <splashCommand>] <userArgs>
|
---|
83 | *
|
---|
84 | * If the -nosplash option is given to the launcher, the java
|
---|
85 | * application will not receive the "-showsplash" option or its
|
---|
86 | * associated command.
|
---|
87 | */
|
---|
88 |
|
---|
89 | #include <stdio.h>
|
---|
90 | #include <stdlib.h>
|
---|
91 | #include <string.h>
|
---|
92 | #include <sys/types.h>
|
---|
93 | #include <sys/stat.h>
|
---|
94 |
|
---|
95 | #ifdef _WIN32
|
---|
96 | #include <windows.h>
|
---|
97 | #include <direct.h>
|
---|
98 | #define getcwd _getcwd
|
---|
99 | #define strcasecmp _stricmp
|
---|
100 |
|
---|
101 | //@@@OS2BEGIN
|
---|
102 | #endif
|
---|
103 | #ifdef __OS2__
|
---|
104 | # include <direct.h>
|
---|
105 | # define getcwd _getcwd
|
---|
106 | # define strcasecmp stricmp
|
---|
107 | //@@@OS2END
|
---|
108 |
|
---|
109 | #else /* Linux and UNIX */
|
---|
110 | #include <unistd.h>
|
---|
111 | #endif
|
---|
112 |
|
---|
113 | #include "eclipseOS.h"
|
---|
114 |
|
---|
115 | #define MAX_PATH_LENGTH 2000
|
---|
116 |
|
---|
117 | /* Global Data */
|
---|
118 | static char* program = NULL; /* full pathname of the program */
|
---|
119 | static char* homeDir = NULL; /* directory where program resides */
|
---|
120 | static char* javaVM = NULL; /* full pathname of the Java VM to run */
|
---|
121 |
|
---|
122 | /* Define the special exit codes returned from Eclipse. */
|
---|
123 | static int startupProblemExitCode = 13;
|
---|
124 | static int vmVersionExitCode = 14;
|
---|
125 | static int isRunningExitCode = 15;
|
---|
126 | static int restartExitCode = 23;
|
---|
127 |
|
---|
128 | /* Define the maximum time (in seconds) for the splash window to remain visible. */
|
---|
129 | static char* splashTimeout = "600"; /* 10 minutes */
|
---|
130 |
|
---|
131 | /* Define the required VM arguments (all platforms). */
|
---|
132 | #define startupJarName "startup.jar"
|
---|
133 | static char* reqVMarg[] = { "-cp", startupJarName, "org.eclipse.core.launcher.Main", NULL };
|
---|
134 |
|
---|
135 | /* Define error messages. (non-NLS) */
|
---|
136 | static char* exitMsg = "JVM terminated. Exit code=%d\n%s";
|
---|
137 | static char* goVMMsg = "Start VM: %s\n";
|
---|
138 | static char* pathMsg = "%s\n'%s' in your current PATH";
|
---|
139 | static char* showMsg = "Could not load splash bitmap:\n%s";
|
---|
140 | static char* noVMMsg =
|
---|
141 | "A Java Runtime Environment (JRE) or Java Development Kit (JDK)\n\
|
---|
142 | must be available in order to run Eclipse. No Java virtual machine\n\
|
---|
143 | was found after searching the following locations:\n\
|
---|
144 | %s";
|
---|
145 |
|
---|
146 | static char* homeMsg =
|
---|
147 | "The Eclipse executable launcher was unable to locate its \n\
|
---|
148 | companion startup.jar file (in the same directory as the executable).";
|
---|
149 |
|
---|
150 | static char* startupProblemMsg =
|
---|
151 | "Problems during startup. Check the \".log\" file\n\
|
---|
152 | in the \".metadata\" directory of your workspace.";
|
---|
153 |
|
---|
154 | static char* vmVersionMsg = "Please use a newer VM. Eclipse requires at least 1.3.0.";
|
---|
155 |
|
---|
156 | static char* isRunningMsg =
|
---|
157 | "Another session is already running in the associated workspace.\n\
|
---|
158 | If this is not the case, please delete the \".lock\" file in the\n\
|
---|
159 | workspace \".metadata\" directory and try starting the platform again.";
|
---|
160 |
|
---|
161 |
|
---|
162 | /* Define constants for the options recognized by the launcher. */
|
---|
163 | #define CONSOLELOG "-consoleLog"
|
---|
164 | #define DEBUG "-debug"
|
---|
165 | #define OS "-os"
|
---|
166 | #define OSARCH "-arch"
|
---|
167 | #define NOSPLASH "-nosplash"
|
---|
168 | #define SHOWSPLASH "-showsplash"
|
---|
169 | #define VM "-vm"
|
---|
170 | #define WS "-ws"
|
---|
171 | #define VMARGS "-vmargs" /* special option processing required */
|
---|
172 |
|
---|
173 | /* Define the variables to receive the option values. */
|
---|
174 | static int needConsole = 0; /* True: user wants a console */
|
---|
175 | static int debug = 0; /* True: output debugging info */
|
---|
176 | static int noSplash = 0; /* True: do not show splash win */
|
---|
177 | static char* osArg = "os2";/*DEFAULT_OS; */
|
---|
178 | static char* osArchArg = "x86";/*DEFAULT_OS_ARCH; */
|
---|
179 | static char* showSplashArg = NULL; /* showsplash data (main launcher window) */
|
---|
180 | static char* vmName = NULL; /* Java VM that the user wants to run */
|
---|
181 | static char* wsArg = "pm";/* DEFAULT_WS;*/ /* the SWT supported GUI to be used */
|
---|
182 | static char** userVMarg = NULL; /* user specific args for the Java VM */
|
---|
183 |
|
---|
184 |
|
---|
185 | /* Define a table for processing command line options. */
|
---|
186 | typedef struct
|
---|
187 | {
|
---|
188 | char* name; /* the option recognized by the launcher */
|
---|
189 | char** value; /* the variable where the option value is saved */
|
---|
190 | int* flag; /* the variable that is set if the option is defined */
|
---|
191 | int remove; /* the number of argments to remove from the list */
|
---|
192 | } Option;
|
---|
193 |
|
---|
194 | static Option options[] = {
|
---|
195 | { CONSOLELOG, NULL, &needConsole, 0 },
|
---|
196 | { DEBUG, NULL, &debug, 0 },
|
---|
197 | { NOSPLASH, NULL, &noSplash, 1 },
|
---|
198 | { OS, &osArg, NULL, 2 },
|
---|
199 | { OSARCH, &osArchArg, NULL, 2 },
|
---|
200 | { SHOWSPLASH, &showSplashArg, NULL, 2 },
|
---|
201 | { VM, &vmName, NULL, 2 },
|
---|
202 | { WS, &wsArg, NULL, 2 } };
|
---|
203 | static int optionsSize = (sizeof(options) / sizeof(options[0]));
|
---|
204 |
|
---|
205 | /* Local methods */
|
---|
206 | static void parseArgs( int* argc, char* argv[] );
|
---|
207 | static char** getVMCommand( int argc, char* argv[] );
|
---|
208 | char* findCommand( char* command );
|
---|
209 | static char* formatVmCommandMsg( char* args[] );
|
---|
210 | static char* getInstallDir();
|
---|
211 |
|
---|
212 |
|
---|
213 | int main( int argc, char* argv[] )
|
---|
214 | {
|
---|
215 | char* splashBitmap;
|
---|
216 | char* ch;
|
---|
217 | char* shippedVM = NULL;
|
---|
218 | char* vmSearchPath = NULL;
|
---|
219 | char** vmCommand;
|
---|
220 | char* vmCommandMsg = NULL;
|
---|
221 | char* errorMsg;
|
---|
222 | int exitCode;
|
---|
223 |
|
---|
224 | /* Strip off any extroneous <CR> from the last argument. If a shell script
|
---|
225 | on Linux is created in DOS format (lines end with <CR><LF>), the C-shell
|
---|
226 | does not strip off the <CR> and hence the argument is bogus and may
|
---|
227 | not be recognized by the launcher or eclipse itself. */
|
---|
228 | ch = strchr( argv[ argc - 1 ], (int) '\r' );
|
---|
229 | if (ch != NULL)
|
---|
230 | {
|
---|
231 | *ch = '\0';
|
---|
232 | }
|
---|
233 |
|
---|
234 | /* Determine the full pathname of this program. */
|
---|
235 | program = findCommand( argv[0] );
|
---|
236 | if (program == NULL)
|
---|
237 | {
|
---|
238 | #ifdef _WIN32
|
---|
239 | program = malloc( MAX_PATH_LENGTH + 1 );
|
---|
240 | GetModuleFileName( NULL, program, MAX_PATH_LENGTH );
|
---|
241 | #else
|
---|
242 | program = malloc( strlen( argv[0] ) + 1 );
|
---|
243 | strcpy( program, argv[0] );
|
---|
244 | #endif
|
---|
245 | }
|
---|
246 |
|
---|
247 | /* Parse command line arguments (looking for the VM to use). */
|
---|
248 | parseArgs( &argc, argv );
|
---|
249 |
|
---|
250 | /* Initialize the window system. */
|
---|
251 | initWindowSystem( &argc, argv, (showSplashArg != NULL) );
|
---|
252 |
|
---|
253 | /* Find the home directory where the Eclipse is installed. */
|
---|
254 | homeDir = getInstallDir();
|
---|
255 | if (homeDir == NULL)
|
---|
256 | {
|
---|
257 | displayMessage( homeMsg );
|
---|
258 | exit( 1 );
|
---|
259 | }
|
---|
260 |
|
---|
261 | /* If the showsplash option was given */
|
---|
262 | if (showSplashArg != NULL)
|
---|
263 | {
|
---|
264 | /* If an extra argument was given, pass it as the image to display. */
|
---|
265 | splashBitmap = (argc > 1 ? argv[1] : NULL);
|
---|
266 | exitCode = showSplash( showSplashArg, homeDir, splashBitmap );
|
---|
267 | if (exitCode && debug)
|
---|
268 | {
|
---|
269 | if (splashBitmap == NULL)
|
---|
270 | splashBitmap = homeDir;
|
---|
271 | errorMsg = (char*) malloc( strlen(showMsg) + strlen(splashBitmap) + 10 );
|
---|
272 | sprintf( errorMsg, showMsg, splashBitmap );
|
---|
273 | displayMessage( errorMsg );
|
---|
274 | free( errorMsg );
|
---|
275 | }
|
---|
276 | exit( exitCode );
|
---|
277 | }
|
---|
278 |
|
---|
279 | /* If the user did not specify a VM to be used */
|
---|
280 | if (vmName == NULL)
|
---|
281 | {
|
---|
282 | /* Determine which type of VM should be used. */
|
---|
283 | vmName = ((debug || needConsole) ? consoleVM : defaultVM);
|
---|
284 |
|
---|
285 | /* Try to find the VM shipped with eclipse. */
|
---|
286 | shippedVM = malloc( strlen( homeDir ) + strlen( vmName ) + 10 );
|
---|
287 | sprintf( shippedVM, "%s%s%s", homeDir, shippedVMDir, vmName );
|
---|
288 | javaVM = findCommand( shippedVM );
|
---|
289 |
|
---|
290 | /* Format a message to indicate the default VM search path. */
|
---|
291 | vmSearchPath = malloc( strlen( pathMsg ) + strlen( shippedVM ) + strlen( vmName ) + 10 );
|
---|
292 | sprintf( vmSearchPath, pathMsg, shippedVM, vmName );
|
---|
293 | free( shippedVM );
|
---|
294 | shippedVM = NULL;
|
---|
295 | }
|
---|
296 |
|
---|
297 | /* If a Java VM has not been found yet */
|
---|
298 | if (javaVM == NULL)
|
---|
299 | {
|
---|
300 | /* Either verify the VM specified by the user or
|
---|
301 | attempt to find the VM in the user's PATH. */
|
---|
302 | javaVM = findCommand( vmName );
|
---|
303 |
|
---|
304 | /* If the VM was not found, display a message and exit. */
|
---|
305 | if (javaVM == NULL)
|
---|
306 | {
|
---|
307 | if (vmSearchPath != NULL) vmName = vmSearchPath; /* used default VM searching */
|
---|
308 | errorMsg = (char*) malloc( strlen(noVMMsg) + strlen(vmName) + 10 );
|
---|
309 | sprintf( errorMsg, noVMMsg, vmName );
|
---|
310 | displayMessage( errorMsg );
|
---|
311 | free( errorMsg );
|
---|
312 | exit(1);
|
---|
313 | }
|
---|
314 | }
|
---|
315 |
|
---|
316 | /* Get the command to start the Java VM. */
|
---|
317 | vmCommand = getVMCommand( argc, argv );
|
---|
318 | vmCommandMsg = formatVmCommandMsg( vmCommand );
|
---|
319 |
|
---|
320 | /* While the Java VM should be restarted */
|
---|
321 | exitCode = restartExitCode;
|
---|
322 | while (exitCode == restartExitCode)
|
---|
323 | {
|
---|
324 | /* Start the Java virtual machine and wait for it to exit. */
|
---|
325 | if (debug) printf( goVMMsg, vmCommandMsg );
|
---|
326 | exitCode = startJavaVM( vmCommand );
|
---|
327 |
|
---|
328 | /* If the JVM exited abnormally (and was not a restart) */
|
---|
329 | if (exitCode != 0 && exitCode != restartExitCode)
|
---|
330 | {
|
---|
331 | /* Format and output an error message. */
|
---|
332 | if (exitCode == startupProblemExitCode)
|
---|
333 | {
|
---|
334 | displayMessage( startupProblemMsg );
|
---|
335 | }
|
---|
336 | else if (exitCode == vmVersionExitCode)
|
---|
337 | {
|
---|
338 | displayMessage( vmVersionMsg );
|
---|
339 | }
|
---|
340 | else if (exitCode == isRunningExitCode)
|
---|
341 | {
|
---|
342 | displayMessage( isRunningMsg );
|
---|
343 | }
|
---|
344 | else
|
---|
345 | {
|
---|
346 | errorMsg = (char*) malloc( strlen(exitMsg) + strlen(vmCommandMsg) + 10 );
|
---|
347 | sprintf( errorMsg, exitMsg, exitCode, vmCommandMsg );
|
---|
348 | displayMessage( errorMsg );
|
---|
349 | free( errorMsg );
|
---|
350 | }
|
---|
351 | }
|
---|
352 | }
|
---|
353 |
|
---|
354 | /* Cleanup time. */
|
---|
355 | free( homeDir );
|
---|
356 | free( program );
|
---|
357 | free( vmCommandMsg );
|
---|
358 | if (vmSearchPath != NULL) free( vmSearchPath );
|
---|
359 |
|
---|
360 | return 0;
|
---|
361 | }
|
---|
362 |
|
---|
363 |
|
---|
364 | /*
|
---|
365 | * Parse arguments of the command.
|
---|
366 | */
|
---|
367 | static void parseArgs( int* pArgc, char* argv[] )
|
---|
368 | {
|
---|
369 | Option* option;
|
---|
370 | int remArgs;
|
---|
371 | int index;
|
---|
372 | int i;
|
---|
373 |
|
---|
374 | /* Ensure the list of user argument is NULL terminated. */
|
---|
375 | argv[ *pArgc ] = NULL;
|
---|
376 |
|
---|
377 | /* For each user defined argument (excluding the program) */
|
---|
378 | for (index = 1; index < *pArgc; index++){
|
---|
379 | remArgs = 0;
|
---|
380 |
|
---|
381 | /* Find the corresponding argument is a option supported by the launcher */
|
---|
382 | option = NULL;
|
---|
383 | for (i = 0; option == NULL && i < optionsSize; i++)
|
---|
384 | {
|
---|
385 | if (strcasecmp( argv[ index ], options[ i ].name ) == 0)
|
---|
386 | option = &options[ i ];
|
---|
387 | }
|
---|
388 |
|
---|
389 | /* If the option is recognized by the launcher */
|
---|
390 | if (option != NULL)
|
---|
391 | {
|
---|
392 | /* If the option requires a value and there is one, extract the value. */
|
---|
393 | if (option->value != NULL && (index+1) < *pArgc)
|
---|
394 | *option->value = argv[ index+1 ];
|
---|
395 |
|
---|
396 | /* If the option requires a flag to be set, set it. */
|
---|
397 | if (option->flag != NULL)
|
---|
398 | *option->flag = 1;
|
---|
399 | remArgs = option->remove;
|
---|
400 | }
|
---|
401 |
|
---|
402 | /* All of the remaining arguments are user VM args. */
|
---|
403 | else if (strcasecmp( argv[ index ], VMARGS ) == 0)
|
---|
404 | {
|
---|
405 | userVMarg = &argv[ index+1 ];
|
---|
406 | argv[ index ] = NULL;
|
---|
407 | *pArgc = index;
|
---|
408 | }
|
---|
409 |
|
---|
410 | /* Remove any matched arguments from the list. */
|
---|
411 | if (remArgs > 0)
|
---|
412 | {
|
---|
413 | for (i = (index + remArgs); i <= *pArgc; i++)
|
---|
414 | {
|
---|
415 | argv[ i - remArgs ] = argv[ i ];
|
---|
416 | }
|
---|
417 | index--;
|
---|
418 | *pArgc -= remArgs;
|
---|
419 | }
|
---|
420 | }
|
---|
421 | }
|
---|
422 |
|
---|
423 | /*
|
---|
424 | * Find the absolute pathname to where a command resides.
|
---|
425 | *
|
---|
426 | * The string returned by the function must be freed.
|
---|
427 | */
|
---|
428 | #define EXTRA 20
|
---|
429 | char* findCommand( char* command )
|
---|
430 | {
|
---|
431 | char* cmdPath;
|
---|
432 | int length;
|
---|
433 | char* ch;
|
---|
434 | char* dir;
|
---|
435 | char* path;
|
---|
436 | struct stat stats;
|
---|
437 |
|
---|
438 | /* If the command was an abolute pathname, use it as is. */
|
---|
439 | if (command[0] == dirSeparator ||
|
---|
440 | (strlen( command ) > 2 && command[1] == ':'))
|
---|
441 | {
|
---|
442 | length = strlen( command );
|
---|
443 | cmdPath = malloc( length + EXTRA ); /* add extra space for a possible ".exe" extension */
|
---|
444 | strcpy( cmdPath, command );
|
---|
445 | }
|
---|
446 |
|
---|
447 | else
|
---|
448 | {
|
---|
449 | /* If the command string contains a path separator */
|
---|
450 | if (strchr( command, (int) dirSeparator ) != NULL)
|
---|
451 | {
|
---|
452 | /* It must be relative to the current directory. */
|
---|
453 | length = MAX_PATH_LENGTH + EXTRA + strlen( command );
|
---|
454 | cmdPath = malloc( length );
|
---|
455 | getcwd( cmdPath, length );
|
---|
456 | if (cmdPath[ strlen( cmdPath ) - 1 ] != dirSeparator)
|
---|
457 | {
|
---|
458 | length = strlen( cmdPath );
|
---|
459 | cmdPath[ length ] = dirSeparator;
|
---|
460 | cmdPath[ length+1 ] = '\0';
|
---|
461 | }
|
---|
462 | strcat( cmdPath, command );
|
---|
463 | }
|
---|
464 |
|
---|
465 | /* else the command must be in the PATH somewhere */
|
---|
466 | else
|
---|
467 | {
|
---|
468 | /* Get the directory PATH where executables reside. */
|
---|
469 | path = getenv( "PATH" );
|
---|
470 | length = strlen( path ) + strlen( command ) + MAX_PATH_LENGTH;
|
---|
471 | cmdPath = malloc( length );
|
---|
472 |
|
---|
473 | /* Foreach directory in the PATH */
|
---|
474 | dir = path;
|
---|
475 | while (dir != NULL && *dir != '\0')
|
---|
476 | {
|
---|
477 | ch = strchr( dir, (int)pathSeparator );
|
---|
478 | if (ch == NULL)
|
---|
479 | {
|
---|
480 | strcpy( cmdPath, dir );
|
---|
481 | }
|
---|
482 | else
|
---|
483 | {
|
---|
484 | length = ch - dir;
|
---|
485 | strncpy( cmdPath, dir, length );
|
---|
486 | cmdPath[ length ] = '\0';
|
---|
487 | ch++;
|
---|
488 | }
|
---|
489 | dir = ch; /* advance for the next iteration */
|
---|
490 |
|
---|
491 | /* Determine if the executable resides in this directory. */
|
---|
492 | if (cmdPath[0] == '.' &&
|
---|
493 | (strlen(cmdPath) == 1 || (strlen(cmdPath) == 2 && cmdPath[1] == dirSeparator)))
|
---|
494 | {
|
---|
495 | getcwd( cmdPath, MAX_PATH_LENGTH );
|
---|
496 | }
|
---|
497 | if (cmdPath[ strlen( cmdPath ) - 1 ] != dirSeparator)
|
---|
498 | {
|
---|
499 | length = strlen( cmdPath );
|
---|
500 | cmdPath[ length ] = dirSeparator;
|
---|
501 | cmdPath[ length+1 ] = '\0';
|
---|
502 | }
|
---|
503 | strcat( cmdPath, command );
|
---|
504 |
|
---|
505 | /* If the file is not a directory and can be executed */
|
---|
506 | if (stat( cmdPath, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0)
|
---|
507 | {
|
---|
508 | /* Stop searching */
|
---|
509 | dir = NULL;
|
---|
510 | }
|
---|
511 | }
|
---|
512 | }
|
---|
513 | }
|
---|
514 |
|
---|
515 | #ifdef _WIN32
|
---|
516 | /* If the command does not exist */
|
---|
517 | if (stat( cmdPath, &stats ) != 0 || (stats.st_mode & S_IFREG) == 0)
|
---|
518 | {
|
---|
519 | /* If the command does not end with .exe, append it an try again. */
|
---|
520 | length = strlen( cmdPath );
|
---|
521 | if (length > 4 && strcasecmp( &cmdPath[ length - 4 ], ".exe" ) != 0)
|
---|
522 | strcat( cmdPath, ".exe" );
|
---|
523 | }
|
---|
524 | #endif
|
---|
525 |
|
---|
526 | /* Verify the resulting command actually exists. */
|
---|
527 | if (stat( cmdPath, &stats ) != 0 || (stats.st_mode & S_IFREG) == 0)
|
---|
528 | {
|
---|
529 | free( cmdPath );
|
---|
530 | cmdPath = NULL;
|
---|
531 | }
|
---|
532 |
|
---|
533 | /* Return the absolute command pathname. */
|
---|
534 | return cmdPath;
|
---|
535 | }
|
---|
536 |
|
---|
537 |
|
---|
538 |
|
---|
539 | /*
|
---|
540 | * Get the command and arguments to start the Java VM.
|
---|
541 | *
|
---|
542 | * Memory allocated by this function is assumed to be
|
---|
543 | * deallocated when the program terminates.
|
---|
544 | *
|
---|
545 | * Some of the arguments returned by this function were
|
---|
546 | * passed directly from the main( argv ) array so they
|
---|
547 | * should not be deallocated.
|
---|
548 | */
|
---|
549 | static char** getVMCommand( int argc, char* argv[] )
|
---|
550 | {
|
---|
551 | char** defVMarg;
|
---|
552 | int nDefVMarg = 0;
|
---|
553 | int nReqVMarg = 0;
|
---|
554 | int nUserVMarg = 0;
|
---|
555 | int totalArgs;
|
---|
556 | char** execArg;
|
---|
557 | char* jarFile = NULL;
|
---|
558 | char* splashExec;
|
---|
559 | int src;
|
---|
560 | int dst;
|
---|
561 |
|
---|
562 | /* Calculate the number of user VM arguments. */
|
---|
563 | if (userVMarg != NULL)
|
---|
564 | {
|
---|
565 | while (userVMarg[ nUserVMarg ] != NULL)
|
---|
566 | nUserVMarg++;
|
---|
567 | }
|
---|
568 |
|
---|
569 | /* Calculate the number of default VM arguments. */
|
---|
570 | defVMarg = getArgVM( javaVM );
|
---|
571 | while (defVMarg[ nDefVMarg ] != NULL)
|
---|
572 | nDefVMarg++;
|
---|
573 |
|
---|
574 | /* Calculate the number of required VM arguments. */
|
---|
575 | while (reqVMarg[ nReqVMarg ] != NULL)
|
---|
576 | nReqVMarg++;
|
---|
577 |
|
---|
578 | /* Allocate the arg list for the exec call.
|
---|
579 | (VM + user VM args + default VM args + required VM args + -os OS + -ws GUI + -osArch arch
|
---|
580 | + SHOWSPLASH X + argv[] + NULL) */
|
---|
581 | totalArgs = 1 + nUserVMarg + nDefVMarg + nReqVMarg + 2 + 2 + 2 + 2 + argc + 1;
|
---|
582 | execArg = (char**) malloc( totalArgs * sizeof( char* ) );
|
---|
583 | dst = 0;
|
---|
584 | execArg[ dst++ ] = javaVM;
|
---|
585 |
|
---|
586 | /* If the user specified "-vmargs", add them instead of the default VM args. */
|
---|
587 | if (userVMarg != NULL)
|
---|
588 | {
|
---|
589 | for (src = 0; src < nUserVMarg; src++)
|
---|
590 | execArg[ dst++ ] = userVMarg[ src ];
|
---|
591 | }
|
---|
592 | else
|
---|
593 | {
|
---|
594 | for (src = 0; src < nDefVMarg; src++)
|
---|
595 | execArg[ dst++ ] = defVMarg[ src ];
|
---|
596 | }
|
---|
597 |
|
---|
598 |
|
---|
599 | /* For each required VM arg */
|
---|
600 | for (src = 0; src < nReqVMarg; src++)
|
---|
601 | {
|
---|
602 | /* If the argument is not the startup jar, use it as is. */
|
---|
603 | if (strcmp( reqVMarg[ src ], startupJarName ) != 0)
|
---|
604 | {
|
---|
605 | execArg[ dst++ ] = reqVMarg[ src ];
|
---|
606 | }
|
---|
607 |
|
---|
608 | /* else use the absolute path of the jar file. */
|
---|
609 | else
|
---|
610 | {
|
---|
611 | jarFile = malloc( strlen( homeDir ) + strlen( startupJarName ) + 1 );
|
---|
612 | strcpy( jarFile, homeDir );
|
---|
613 | strcat( jarFile, startupJarName );
|
---|
614 | execArg[ dst++ ] = jarFile;
|
---|
615 | }
|
---|
616 | }
|
---|
617 |
|
---|
618 | /* Append the required options. */
|
---|
619 | execArg[ dst++ ] = OS;
|
---|
620 | execArg[ dst++ ] = osArg;
|
---|
621 | execArg[ dst++ ] = WS;
|
---|
622 | execArg[ dst++ ] = wsArg;
|
---|
623 | execArg[ dst++ ] = OSARCH;
|
---|
624 | execArg[ dst++ ] = osArchArg;
|
---|
625 |
|
---|
626 | /* Append the show splash window command, if defined. */
|
---|
627 | if (!noSplash)
|
---|
628 | {
|
---|
629 | execArg[ dst++ ] = SHOWSPLASH;
|
---|
630 | splashExec = malloc( strlen( program ) + strlen( splashTimeout ) + 20 );
|
---|
631 | sprintf( splashExec, "%s %s %s", program, SHOWSPLASH, splashTimeout );
|
---|
632 | execArg[ dst++ ] = splashExec;
|
---|
633 | }
|
---|
634 |
|
---|
635 | /* Append the remaining user defined argments. */
|
---|
636 | for (src = 1; src < argc; src++)
|
---|
637 | {
|
---|
638 | execArg[ dst++ ] = argv[ src ];
|
---|
639 | }
|
---|
640 | execArg[ dst++ ] = NULL;
|
---|
641 |
|
---|
642 | return execArg;
|
---|
643 | }
|
---|
644 |
|
---|
645 | /* Format the JVM start command for error messages
|
---|
646 | *
|
---|
647 | * This method formats a string with the JVM start command (and all arguments)
|
---|
648 | * that can be used in displaying error messages. The string returned from this
|
---|
649 | * method is probably not NLS compliant and must be deallocated by the caller.
|
---|
650 | */
|
---|
651 | static char* formatVmCommandMsg( char* args[] )
|
---|
652 | {
|
---|
653 | int index;
|
---|
654 | int length;
|
---|
655 | char* ch;
|
---|
656 | char* message;
|
---|
657 |
|
---|
658 | /* Determine the length of the message buffer. */
|
---|
659 | length = 0;
|
---|
660 | for (index = 0; args[index] != NULL; index++)
|
---|
661 | {
|
---|
662 | length += strlen(args[index]) + 1;
|
---|
663 | }
|
---|
664 | message = (char*) malloc( length + 5 );
|
---|
665 |
|
---|
666 | /* Format the message such that options (args starting with '-') begin
|
---|
667 | on a new line. Otherwise, the Motif MessageBox does not automatically wrap
|
---|
668 | the messages and the message window can extend beyond both sides of the display. */
|
---|
669 | ch = message;
|
---|
670 | for (index = 0; args[index] != NULL; index++)
|
---|
671 | {
|
---|
672 | if (args[index][0] == '-' && *(ch-1) == ' ')
|
---|
673 | *(ch-1) = '\n';
|
---|
674 | strcpy( ch, args[index] );
|
---|
675 | ch += strlen( args[index] );
|
---|
676 | *ch++ = ' ';
|
---|
677 | }
|
---|
678 | *ch = '\0';
|
---|
679 |
|
---|
680 | return message;
|
---|
681 | }
|
---|
682 |
|
---|
683 | /* Determine the Installation Directory
|
---|
684 | *
|
---|
685 | * This function takes the directory where program executable resides and
|
---|
686 | * determines the installation directory. The installation directory must
|
---|
687 | * contain the startup JAR file and the executable must be either in the
|
---|
688 | * install directory or in a subdirectory.
|
---|
689 | */
|
---|
690 | static char* getInstallDir( )
|
---|
691 | {
|
---|
692 | char* ch;
|
---|
693 | char* installDir;
|
---|
694 | char path[ MAX_PATH_LENGTH ];
|
---|
695 | struct stat stats;
|
---|
696 |
|
---|
697 | /* Start with the directory where the executable resides. */
|
---|
698 | installDir = (char*) malloc( strlen( program ) + 1 );
|
---|
699 | strcpy( installDir, program );
|
---|
700 | ch = strrchr( installDir, (int)dirSeparator );
|
---|
701 |
|
---|
702 | /* For each directory in the hierarchy */
|
---|
703 | while (ch != NULL)
|
---|
704 | {
|
---|
705 | /* Format the pathname of the startup jar file. */
|
---|
706 | *(ch+1) = '\0';
|
---|
707 | sprintf( path, "%s%s", installDir, startupJarName );
|
---|
708 |
|
---|
709 | /* If the jar file exists */
|
---|
710 | if (stat( path, &stats ) == 0 && (stats.st_mode & S_IFREG) != 0)
|
---|
711 | {
|
---|
712 | return installDir;
|
---|
713 | }
|
---|
714 | else
|
---|
715 | {
|
---|
716 | /* Try the next directory up in the hierarchy. */
|
---|
717 | *ch = '\0';
|
---|
718 | ch = strrchr( installDir, (int)dirSeparator );
|
---|
719 | }
|
---|
720 | }
|
---|
721 |
|
---|
722 | free( installDir );
|
---|
723 | return NULL;
|
---|
724 | }
|
---|
725 |
|
---|
726 |
|
---|