void CreateExecutionEnvironment(int *_argc, char ***_argv, char jrepath[], jint so_jrepath, char jvmpath[], jint so_jvmpath, char **original_argv) { char * jvmtype; int i = 0; char** pargv = *_argv; int running = CURRENT_DATA_MODEL; int wanted = running; for (i = 0; i < *_argc ; i++) { if (strcmp(pargv[i], "-J-d64") == 0 || strcmp(pargv[i], "-d64") == 0) { wanted = 64; continue; } if (strcmp(pargv[i], "-J-d32") == 0 || strcmp(pargv[i], "-d32") == 0) { wanted = 32; continue; } } if (running != wanted) { fprintf(stderr, "This Java instance does not support a %d-bit JVM.\nPlease install the desired version.\n", wanted); exit(1); } /* Find out where the JRE is that we will be using. */ if (!GetJREPath(jrepath, so_jrepath)) { ReportErrorMessage("Error: could not find Java 2 Runtime Environment.", JNI_TRUE); exit(2); } /* Find the specified JVM type */ if (ReadKnownVMs(jrepath, (char*)GetArch(), JNI_FALSE) < 1) { ReportErrorMessage("Error: no known VMs. (check for corrupt jvm.cfg file)", JNI_TRUE); exit(1); } jvmtype = CheckJvmType(_argc, _argv, JNI_FALSE); jvmpath[0] = '\0'; if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) { char * message=NULL; const char * format = "Error: no `%s' JVM at `%s'."; message = (char *)JLI_MemAlloc((strlen(format)+strlen(jvmtype)+ strlen(jvmpath)) * sizeof(char)); sprintf(message,format, jvmtype, jvmpath); ReportErrorMessage(message, JNI_TRUE); exit(4); } /* If we got here, jvmpath has been correctly initialized. */ }
int CreateExecutionEnvironment(int *_argc, char ***_argv, char jrepath[], jint so_jrepath, char jvmpath[], jint so_jvmpath, char **original_argv) { char * jvmtype; /* Find out where the JRE is that we will be using. */ if (!GetJREPath(jrepath, so_jrepath)) { ReportErrorMessage("Could not find a suitable Java 2 Runtime Environment.", JNI_TRUE); return 1; } /* Find the specified JVM type */ if (ReadKnownVMs(jrepath, (char*)GetArch(), JNI_FALSE) < 1) { ReportErrorMessage("Error: no known VMs. (check for corrupt jvm.cfg file)", JNI_TRUE); return 1; } jvmtype = CheckJvmType(_argc, _argv, JNI_FALSE); jvmpath[0] = '\0'; if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) { char * message=NULL; const char * format = "Error: no `%s' JVM at `%s'."; message = (char *)MemAlloc((strlen(format)+strlen(jvmtype)+ strlen(jvmpath)) * sizeof(char)); sprintf(message,format, jvmtype, jvmpath); ReportErrorMessage(message, JNI_TRUE); return 1; } /* If we got here, jvmpath has been correctly initialized. */ return 0; }
/* * For tools convert 'javac -J-ms32m' to 'java -ms32m ...' */ static void TranslateDashJArgs(int *pargc, char ***pargv) { const int NUM_ARGS = (sizeof(java_args) / sizeof(char *)); int argc = *pargc; char **argv = *pargv; int nargc = argc + NUM_ARGS; char **nargv = MemAlloc((nargc + 1) * sizeof(char *)); int i; *pargc = nargc; *pargv = nargv; /* Copy the VM arguments (i.e. prefixed with -J) */ for (i = 0; i < NUM_ARGS; i++) { char *arg = java_args[i]; if (arg[0] == '-' && arg[1] == 'J') { *nargv++ = arg + 2; } } for (i = 0; i < argc; i++) { char *arg = argv[i]; if (arg[0] == '-' && arg[1] == 'J') { if (arg[2] == '\0') { ReportErrorMessage("Error: the -J option should not be " "followed by a space.", JNI_TRUE); exit(1); } *nargv++ = arg + 2; } } /* Copy the rest of the arguments */ for (i = 0; i < NUM_ARGS; i++) { char *arg = java_args[i]; if (arg[0] != '-' || arg[1] != 'J') { *nargv++ = arg; } } for (i = 0; i < argc; i++) { char *arg = argv[i]; if (arg[0] != '-' || arg[1] != 'J') { *nargv++ = arg; } } *nargv = 0; }
/* * For our tools, we try to add 3 VM options: * -Denv.class.path=<envcp> * -Dapplication.home=<apphome> * -Djava.class.path=<appcp> * <envcp> is the user's setting of CLASSPATH -- for instance the user * tells javac where to find binary classes through this environment * variable. Notice that users will be able to compile against our * tools classes (sun.tools.javac.Main) only if they explicitly add * tools.jar to CLASSPATH. * <apphome> is the directory where the application is installed. * <appcp> is the classpath to where our apps' classfiles are. */ static jboolean AddApplicationOptions() { const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *)); char *s, *envcp, *appcp, *apphome; char home[MAXPATHLEN]; /* application home */ char separator[] = { PATH_SEPARATOR, '\0' }; int size, i; int strlenHome; s = getenv("CLASSPATH"); if (s) { /* 40 for -Denv.class.path= */ envcp = (char *)MemAlloc(strlen(s) + 40); sprintf(envcp, "-Denv.class.path=%s", s); AddOption(envcp, NULL); } if (!GetApplicationHome(home, sizeof(home))) { ReportErrorMessage("Can't determine application home", JNI_TRUE); return JNI_FALSE; } /* 40 for '-Dapplication.home=' */ apphome = (char *)MemAlloc(strlen(home) + 40); sprintf(apphome, "-Dapplication.home=%s", home); AddOption(apphome, NULL); /* How big is the application's classpath? */ size = 40; /* 40: "-Djava.class.path=" */ strlenHome = (int)strlen(home); for (i = 0; i < NUM_APP_CLASSPATH; i++) { size += strlenHome + (int)strlen(app_classpath[i]) + 1; /* 1: separator */ } appcp = (char *)MemAlloc(size + 1); strcpy(appcp, "-Djava.class.path="); for (i = 0; i < NUM_APP_CLASSPATH; i++) { strcat(appcp, home); /* c:\program files\myapp */ strcat(appcp, app_classpath[i]); /* \lib\myapp.jar */ strcat(appcp, separator); /* ; */ } appcp[strlen(appcp)-1] = '\0'; /* remove trailing path separator */ AddOption(appcp, NULL); return JNI_TRUE; }
/* * Given a path to a jre to execute, this routine checks if this process * is indeed that jre. If not, it exec's that jre. * * We want to actually check the paths rather than just the version string * built into the executable, so that given version specification will yield * the exact same Java environment, regardless of the version of the arbitrary * launcher we start with. */ void ExecJRE(char *jre, char **argv) { int len; char *progname; char path[MAXPATHLEN + 1]; /* * Determine the executable we are building (or in the rare case, running). */ #ifdef JAVA_ARGS /* javac, jar and friends. */ progname = "java"; #else /* java, oldjava, javaw and friends */ #ifdef PROGNAME progname = PROGNAME; #else { char *s; progname = *argv; if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { progname = s + 1; } } #endif /* PROGNAME */ #endif /* JAVA_ARGS */ /* * Resolve the real path to the currently running launcher. */ len = GetModuleFileName(NULL, path, MAXPATHLEN + 1); if (len == 0 || len > MAXPATHLEN) { ReportSysErrorMessage2( "Unable to resolve path to current %s executable: %s", progname, JNI_TRUE); exit(1); } if (_launcher_debug) { printf("ExecJRE: old: %s\n", path); printf("ExecJRE: new: %s\n", jre); } /* * If the path to the selected JRE directory is a match to the initial * portion of the path to the currently executing JRE, we have a winner! * If so, just return. (strnicmp() is the Windows equiv. of strncasecmp().) */ if (strnicmp(jre, path, strlen(jre)) == 0) return; /* I am the droid you were looking for */ /* * If this isn't the selected version, exec the selected version. */ (void)strcat(strcat(strcpy(path, jre), "\\bin\\"), progname); (void)strcat(path, ".exe"); /* * Although Windows has an execv() entrypoint, it doesn't actually * overlay a process: it can only create a new process and terminate * the old process. Therefore, any processes waiting on the initial * process wake up and they shouldn't. Hence, a chain of pseudo-zombie * processes must be retained to maintain the proper wait semantics. * Fortunately the image size of the launcher isn't too large at this * time. * * If it weren't for this semantic flaw, the code below would be ... * * execv(path, argv); * ReportErrorMessage2("Exec of %s failed\n", path, JNI_TRUE); * exit(1); * * The incorrect exec semantics could be addressed by: * * exit((int)spawnv(_P_WAIT, path, argv)); * * Unfortunately, a bug in Windows spawn/exec impementation prevents * this from completely working. All the Windows POSIX process creation * interfaces are implemented as wrappers around the native Windows * function CreateProcess(). CreateProcess() takes a single string * to specify command line options and arguments, so the POSIX routine * wrappers build a single string from the argv[] array and in the * process, any quoting information is lost. * * The solution to this to get the original command line, to process it * to remove the new multiple JRE options (if any) as was done for argv * in the common SelectVersion() routine and finally to pass it directly * to the native CreateProcess() Windows process control interface. */ { char *cmdline; char *p; char *np; char *ocl; char *ccl; char *unquoted; DWORD exitCode; STARTUPINFO si; PROCESS_INFORMATION pi; /* * The following code block gets and processes the original command * line, replacing the argv[0] equivalent in the command line with * the path to the new executable and removing the appropriate * Multiple JRE support options. Note that similar logic exists * in the platform independent SelectVersion routine, but is * replicated here due to the syntax of CreateProcess(). * * The magic "+ 4" characters added to the command line length are * 2 possible quotes around the path (argv[0]), a space after the * path and a terminating null character. */ ocl = GetCommandLine(); np = ccl = JLI_StringDup(ocl); p = nextarg(&np); /* Discard argv[0] */ cmdline = (char *)JLI_MemAlloc(strlen(path) + strlen(np) + 4); if (strchr(path, (int)' ') == NULL && strchr(path, (int)'\t') == NULL) cmdline = strcpy(cmdline, path); else cmdline = strcat(strcat(strcpy(cmdline, "\""), path), "\""); while (*np != (char)0) { /* While more command-line */ p = nextarg(&np); if (*p != (char)0) { /* If a token was isolated */ unquoted = unquote(p); if (*unquoted == '-') { /* Looks like an option */ if (strcmp(unquoted, "-classpath") == 0 || strcmp(unquoted, "-cp") == 0) { /* Unique cp syntax */ cmdline = strcat(strcat(cmdline, " "), p); p = nextarg(&np); if (*p != (char)0) /* If a token was isolated */ cmdline = strcat(strcat(cmdline, " "), p); } else if (strncmp(unquoted, "-version:", 9) != 0 && strcmp(unquoted, "-jre-restrict-search") != 0 && strcmp(unquoted, "-no-jre-restrict-search") != 0) { cmdline = strcat(strcat(cmdline, " "), p); } } else { /* End of options */ cmdline = strcat(strcat(cmdline, " "), p); cmdline = strcat(strcat(cmdline, " "), np); JLI_MemFree((void *)unquoted); break; } JLI_MemFree((void *)unquoted); } } JLI_MemFree((void *)ccl); if (_launcher_debug) { np = ccl = JLI_StringDup(cmdline); p = nextarg(&np); printf("ReExec Command: %s (%s)\n", path, p); printf("ReExec Args: %s\n", np); JLI_MemFree((void *)ccl); } (void)fflush(stdout); (void)fflush(stderr); /* * The following code is modeled after a model presented in the * Microsoft Technical Article "Moving Unix Applications to * Windows NT" (March 6, 1994) and "Creating Processes" on MSDN * (Februrary 2005). It approximates UNIX spawn semantics with * the parent waiting for termination of the child. */ memset(&si, 0, sizeof(si)); si.cb =sizeof(STARTUPINFO); memset(&pi, 0, sizeof(pi)); if (!CreateProcess((LPCTSTR)path, /* executable name */ (LPTSTR)cmdline, /* command line */ (LPSECURITY_ATTRIBUTES)NULL, /* process security attr. */ (LPSECURITY_ATTRIBUTES)NULL, /* thread security attr. */ (BOOL)TRUE, /* inherits system handles */ (DWORD)0, /* creation flags */ (LPVOID)NULL, /* environment block */ (LPCTSTR)NULL, /* current directory */ (LPSTARTUPINFO)&si, /* (in) startup information */ (LPPROCESS_INFORMATION)&pi)) { /* (out) process information */ ReportSysErrorMessage2("CreateProcess(%s, ...) failed: %s", path, JNI_TRUE); exit(1); } if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) { if (GetExitCodeProcess(pi.hProcess, &exitCode) == FALSE) exitCode = 1; } else { ReportErrorMessage("WaitForSingleObject() failed.", JNI_TRUE); exitCode = 1; } CloseHandle(pi.hThread); CloseHandle(pi.hProcess); exit(exitCode); } }
/* * The SelectVersion() routine ensures that an appropriate version of * the JRE is running. The specification for the appropriate version * is obtained from either the manifest of a jar file (preferred) or * from command line options. */ static void SelectVersion(int argc, char **argv, char **main_class) { char *arg; char **new_argv; char **new_argp; char *operand; char *version = NULL; char *jre = NULL; int jarflag = 0; int restrict_search = -1; /* -1 implies not known */ manifest_info info; char env_entry[MAXNAMELEN + 24] = ENV_ENTRY "="; char *env_in; int res; /* * If the version has already been selected, set *main_class * with the value passed through the environment (if any) and * simply return. */ if ((env_in = getenv(ENV_ENTRY)) != NULL) { if (*env_in != '\0') *main_class = strdup(env_in); return; } /* * Scan through the arguments for options relevant to multiple JRE * support. For reference, the command line syntax is defined as: * * SYNOPSIS * java [options] class [argument...] * * java [options] -jar file.jar [argument...] * * As the scan is performed, make a copy of the argument list with * the version specification options (new to 1.5) removed, so that * a version less than 1.5 can be exec'd. */ new_argv = MemAlloc((argc + 1) * sizeof(char*)); new_argv[0] = argv[0]; new_argp = &new_argv[1]; argc--; argv++; while ((arg = *argv) != 0 && *arg == '-') { if (strncmp(arg, "-version:", 9) == 0) { version = arg + 9; } else if (strcmp(arg, "-jre-restrict-search") == 0) { restrict_search = 1; } else if (strcmp(arg, "-no-jre-restrict-search") == 0) { restrict_search = 0; } else { if (strcmp(arg, "-jar") == 0) jarflag = 1; /* deal with "unfortunate" classpath syntax */ if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) { if (argc >= 1) { *new_argp++ = arg; argc--; argv++; arg = *argv; } } *new_argp++ = arg; } argc--; argv++; } if (argc <= 0) { /* No operand? Possibly legit with -[full]version */ operand = NULL; } else { argc--; *new_argp++ = operand = *argv++; } while (argc-- > 0) /* Copy over [argument...] */ *new_argp++ = *argv++; *new_argp = NULL; /* * If there is a jar file, read the manifest. If the jarfile can't be * read, the manifest can't be read from the jar file, or the manifest * is corrupt, issue the appropriate error messages and exit. * * Even if there isn't a jar file, construct a manifest_info structure * containing the command line information. Its a convenient way to carry * this data around. */ if (jarflag && operand) { if ((res = parse_manifest(operand, &info)) != 0) { if (res == -1) ReportErrorMessage2("Unable to access jarfile %s", operand, JNI_TRUE); else ReportErrorMessage2("Invalid or corrupt jarfile %s", operand, JNI_TRUE); exit(1); } } else { info.manifest_version = NULL; info.main_class = NULL; info.jre_version = NULL; info.jre_restrict_search = 0; } /* * The JRE-Version and JRE-Restrict-Search values (if any) from the * manifest are overwritten by any specified on the command line. */ if (version != NULL) info.jre_version = version; if (restrict_search != -1) info.jre_restrict_search = restrict_search; /* * "Valid" returns (other than unrecoverable errors) follow. Set * main_class as a side-effect of this routine. */ if (info.main_class != NULL) *main_class = strdup(info.main_class); /* * If no version selection information is found either on the command * line or in the manifest, simply return. */ if (info.jre_version == NULL) { free_manifest(); free(new_argv); return; } /* * Check for correct syntax of the version specification (JSR 56). */ if (!valid_version_string(info.jre_version)) { ReportErrorMessage2("Syntax error in version specification \"%s\"", info.jre_version, JNI_TRUE); exit(1); } /* * Find the appropriate JVM on the system. Just to be as forgiving as * possible, if the standard algorithms don't locate an appropriate * jre, check to see if the one running will satisfy the requirements. * This can happen on systems which haven't been set-up for multiple * JRE support. */ jre = LocateJRE(&info); if (_launcher_debug) printf("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n", (info.jre_version?info.jre_version:"null"), (info.jre_restrict_search?"true":"false"), (jre?jre:"null")); if (jre == NULL) { if (acceptable_release(FULL_VERSION, info.jre_version)) { free_manifest(); free(new_argv); return; } else { ReportErrorMessage2( "Unable to locate JRE meeting specification \"%s\"", info.jre_version, JNI_TRUE); exit(1); } } /* * If I'm not the chosen one, exec the chosen one. Returning from * ExecJRE indicates that I am indeed the chosen one. * * The private environment variable _JAVA_VERSION_SET is used to * prevent the chosen one from re-reading the manifest file and * using the values found within to override the (potential) command * line flags stripped from argv (because the target may not * understand them). Passing the MainClass value is an optimization * to avoid locating, expanding and parsing the manifest extra * times. */ if (info.main_class != NULL) { if (strlen(info.main_class) <= MAXNAMELEN) { (void)strcat(env_entry, info.main_class); } else { ReportErrorMessage("Error: main-class: attribute exceeds system limits\n", JNI_TRUE); exit(1); } } (void)putenv(env_entry); ExecJRE(jre, new_argv); free_manifest(); free(new_argv); return; }
/* * Checks the command line options to find which JVM type was * specified. If no command line option was given for the JVM type, * the default type is used. The environment variable * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also * checked as ways of specifying which JVM type to invoke. */ char * CheckJvmType(int *pargc, char ***argv, jboolean speculative) { int i, argi; int argc; char **newArgv; int newArgvIdx = 0; int isVMType; int jvmidx = -1; char *jvmtype = getenv("JDK_ALTERNATE_VM"); argc = *pargc; /* To make things simpler we always copy the argv array */ newArgv = MemAlloc((argc + 1) * sizeof(char *)); /* The program name is always present */ newArgv[newArgvIdx++] = (*argv)[0]; for (argi = 1; argi < argc; argi++) { char *arg = (*argv)[argi]; isVMType = 0; #ifdef JAVA_ARGS if (arg[0] != '-') { newArgv[newArgvIdx++] = arg; continue; } #else if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) { newArgv[newArgvIdx++] = arg; argi++; if (argi < argc) { newArgv[newArgvIdx++] = (*argv)[argi]; } continue; } if (arg[0] != '-') break; #endif /* Did the user pass an explicit VM type? */ i = KnownVMIndex(arg); if (i >= 0) { jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */ isVMType = 1; *pargc = *pargc - 1; } /* Did the user specify an "alternate" VM? */ else if (strncmp(arg, "-XXaltjvm=", 10) == 0 || strncmp(arg, "-J-XXaltjvm=", 12) == 0) { isVMType = 1; jvmtype = arg+((arg[1]=='X')? 10 : 12); jvmidx = -1; } if (!isVMType) { newArgv[newArgvIdx++] = arg; } } /* * Finish copying the arguments if we aborted the above loop. * NOTE that if we aborted via "break" then we did NOT copy the * last argument above, and in addition argi will be less than * argc. */ while (argi < argc) { newArgv[newArgvIdx++] = (*argv)[argi]; argi++; } /* argv is null-terminated */ newArgv[newArgvIdx] = 0; /* Copy back argv */ *argv = newArgv; *pargc = newArgvIdx; /* use the default VM type if not specified (no alias processing) */ if (jvmtype == NULL) return knownVMs[0].name+1; /* if using an alternate VM, no alias processing */ if (jvmidx < 0) return jvmtype; /* Resolve aliases first */ { int loopCount = 0; while (knownVMs[jvmidx].flag == VM_ALIASED_TO) { int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias); if (loopCount > knownVMsCount) { if (!speculative) { ReportErrorMessage("Error: Corrupt jvm.cfg file; cycle in alias list.", JNI_TRUE); exit(1); } else { return "ERROR"; /* break; */ } } if (nextIdx < 0) { if (!speculative) { ReportErrorMessage2("Error: Unable to resolve VM alias %s", knownVMs[jvmidx].alias, JNI_TRUE); exit(1); } else { return "ERROR"; } } jvmidx = nextIdx; jvmtype = knownVMs[jvmidx].name+1; loopCount++; } } switch (knownVMs[jvmidx].flag) { case VM_WARN: if (!speculative) { fprintf(stderr, "Warning: %s VM not supported; %s VM will be used\n", jvmtype, knownVMs[0].name + 1); } jvmtype = knownVMs[jvmidx=0].name + 1; /* fall through */ case VM_KNOWN: break; case VM_ERROR: if (!speculative) { ReportErrorMessage2("Error: %s VM not supported", jvmtype, JNI_TRUE); exit(1); } else { return "ERROR"; } } return jvmtype; }
/* * Entry point. */ int main(int argc, char ** argv) { JavaVM *vm = 0; JNIEnv *env = 0; char *jarfile = 0; char *classname = 0; char *s = 0; char *main_class = NULL; jstring mainClassName; jclass mainClass; jmethodID mainID; jobjectArray mainArgs; int ret; InvocationFunctions ifn; jlong start, end; char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN]; char ** original_argv = argv; /* * Error message to print or display; by default the message will * only be displayed in a window. */ char * message = "Fatal exception occurred. Program will exit."; jboolean messageDest = JNI_FALSE; if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) { _launcher_debug = JNI_TRUE; printf("----_JAVA_LAUNCHER_DEBUG----\n"); } /* * Make sure the specified version of the JRE is running. * * There are three things to note about the SelectVersion() routine: * 1) If the version running isn't correct, this routine doesn't * return (either the correct version has been exec'd or an error * was issued). * 2) Argc and Argv in this scope are *not* altered by this routine. * It is the responsibility of subsequent code to ignore the * arguments handled by this routine. * 3) As a side-effect, the variable "main_class" is guaranteed to * be set (if it should ever be set). This isn't exactly the * poster child for structured programming, but it is a small * price to pay for not processing a jar file operand twice. */ SelectVersion(argc, argv, &main_class); /* copy original argv */ { int i; original_argv = (char**)MemAlloc(sizeof(char*)*(argc+1)); for(i = 0; i < argc+1; i++) original_argv[i] = argv[i]; } CreateExecutionEnvironment(&argc, &argv, jrepath, sizeof(jrepath), jvmpath, sizeof(jvmpath), original_argv); ifn.CreateJavaVM = 0; ifn.GetDefaultJavaVMInitArgs = 0; if (_launcher_debug) start = CounterGet(); if (!LoadJavaVM(jvmpath, &ifn)) { exit(6); } if (_launcher_debug) { end = CounterGet(); printf("%ld micro seconds to LoadJavaVM\n", (long)(jint)Counter2Micros(end-start)); } #ifdef JAVA_ARGS /* javac, jar and friends. */ progname = "java"; #else /* java, oldjava, javaw and friends */ #ifdef PROGNAME progname = PROGNAME; #else progname = *argv; if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { progname = s + 1; } #endif /* PROGNAME */ #endif /* JAVA_ARGS */ ++argv; --argc; #ifdef JAVA_ARGS /* Preprocess wrapper arguments */ TranslateDashJArgs(&argc, &argv); if (!AddApplicationOptions()) { exit(1); } #endif /* Set default CLASSPATH */ if ((s = getenv("CLASSPATH")) == 0) { s = "."; } #ifndef JAVA_ARGS SetClassPath(s); #endif /* * Parse command line options; if the return value of * ParseArguments is false, the program should exit. */ if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) { exit(ret); } /* Override class path if -jar flag was specified */ if (jarfile != 0) { SetClassPath(jarfile); } /* set the -Dsun.java.command pseudo property */ SetJavaCommandLineProp(classname, jarfile, argc, argv); /* Set the -Dsun.java.launcher pseudo property */ SetJavaLauncherProp(); /* * Done with all command line processing and potential re-execs so * clean up the environment. */ (void)UnsetEnv(ENV_ENTRY); /* Initialize the virtual machine */ if (_launcher_debug) start = CounterGet(); if (!InitializeJVM(&vm, &env, &ifn)) { ReportErrorMessage("Could not create the Java virtual machine.", JNI_TRUE); exit(1); } if (printVersion || showVersion) { PrintJavaVersion(env); if ((*env)->ExceptionOccurred(env)) { ReportExceptionDescription(env); goto leave; } if (printVersion) { ret = 0; message = NULL; goto leave; } if (showVersion) { fprintf(stderr, "\n"); } } /* If the user specified neither a class name nor a JAR file */ if (jarfile == 0 && classname == 0) { PrintUsage(); message = NULL; goto leave; } FreeKnownVMs(); /* after last possible PrintUsage() */ if (_launcher_debug) { end = CounterGet(); printf("%ld micro seconds to InitializeJVM\n", (long)(jint)Counter2Micros(end-start)); } /* At this stage, argc/argv have the applications' arguments */ if (_launcher_debug) { int i = 0; printf("Main-Class is '%s'\n", classname ? classname : ""); printf("Apps' argc is %d\n", argc); for (; i < argc; i++) { printf(" argv[%2d] = '%s'\n", i, argv[i]); } } ret = 1; /* Get the application's main class */ if (jarfile != 0) { mainClassName = GetMainClassName(env, jarfile); if ((*env)->ExceptionOccurred(env)) { ReportExceptionDescription(env); goto leave; } if (mainClassName == NULL) { const char * format = "Failed to load Main-Class manifest " "attribute from\n%s"; message = (char*)MemAlloc((strlen(format) + strlen(jarfile)) * sizeof(char)); sprintf(message, format, jarfile); messageDest = JNI_TRUE; goto leave; } classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); if (classname == NULL) { ReportExceptionDescription(env); goto leave; } mainClass = LoadClass(env, classname); if(mainClass == NULL) { /* exception occured */ ReportExceptionDescription(env); message = "Could not find the main class. Program will exit."; goto leave; } (*env)->ReleaseStringUTFChars(env, mainClassName, classname); } else { mainClassName = NewPlatformString(env, classname); if (mainClassName == NULL) { const char * format = "Failed to load Main Class: %s"; message = (char *)MemAlloc((strlen(format) + strlen(classname)) * sizeof(char) ); sprintf(message, format, classname); messageDest = JNI_TRUE; goto leave; } classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); if (classname == NULL) { ReportExceptionDescription(env); goto leave; } mainClass = LoadClass(env, classname); if(mainClass == NULL) { /* exception occured */ ReportExceptionDescription(env); message = "Could not find the main class. Program will exit."; goto leave; } (*env)->ReleaseStringUTFChars(env, mainClassName, classname); } /* Get the application's main method */ mainID = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V"); if (mainID == NULL) { if ((*env)->ExceptionOccurred(env)) { ReportExceptionDescription(env); } else { message = "No main method found in specified class."; messageDest = JNI_TRUE; } goto leave; } { /* Make sure the main method is public */ jint mods; jmethodID mid; jobject obj = (*env)->ToReflectedMethod(env, mainClass, mainID, JNI_TRUE); if( obj == NULL) { /* exception occurred */ ReportExceptionDescription(env); goto leave; } mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, obj), "getModifiers", "()I"); if ((*env)->ExceptionOccurred(env)) { ReportExceptionDescription(env); goto leave; } mods = (*env)->CallIntMethod(env, obj, mid); if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */ message = "Main method not public."; messageDest = JNI_TRUE; goto leave; } } /* Build argument array */ mainArgs = NewPlatformStringArray(env, argv, argc); if (mainArgs == NULL) { ReportExceptionDescription(env); goto leave; } /* Invoke main method. */ (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); if ((*env)->ExceptionOccurred(env)) { /* * Formerly, we used to call the "uncaughtException" method of * the main thread group, but this was later shown to be * unnecessary since the default definition merely printed out * the same exception stack trace as ExceptionDescribe and * could never actually be overridden by application programs. */ ReportExceptionDescription(env); goto leave; } /* * Detach the current thread so that it appears to have exited when * the application's main method exits. */ if ((*vm)->DetachCurrentThread(vm) != 0) { message = "Could not detach main thread."; messageDest = JNI_TRUE; goto leave; } ret = 0; message = NULL; leave: (*vm)->DestroyJavaVM(vm); if(message != NULL && !noExitErrorMessage) ReportErrorMessage(message, messageDest); return ret; }
void CreateExecutionEnvironment(int *_argc, char ***_argv, char jrepath[], jint so_jrepath, char jvmpath[], jint so_jvmpath, char **original_argv) { #ifndef GAMMA char * jvmtype; /* Find out where the JRE is that we will be using. */ if (!GetJREPath(jrepath, so_jrepath)) { ReportErrorMessage("Error: could not find Java SE Runtime Environment.", JNI_TRUE); exit(2); } /* Do this before we read jvm.cfg */ EnsureJreInstallation(jrepath); /* Find the specified JVM type */ if (ReadKnownVMs(jrepath, (char*)GetArch(), JNI_FALSE) < 1) { ReportErrorMessage("Error: no known VMs. (check for corrupt jvm.cfg file)", JNI_TRUE); exit(1); } jvmtype = CheckJvmType(_argc, _argv, JNI_FALSE); jvmpath[0] = '\0'; if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) { char * message=NULL; const char * format = "Error: no `%s' JVM at `%s'."; message = (char *)JLI_MemAlloc((strlen(format)+strlen(jvmtype)+ strlen(jvmpath)) * sizeof(char)); sprintf(message,format, jvmtype, jvmpath); ReportErrorMessage(message, JNI_TRUE); exit(4); } /* If we got here, jvmpath has been correctly initialized. */ #else /* ifndef GAMMA */ /* * gamma launcher is simpler in that it doesn't handle VM flavors, data * model, etc. Assuming everything is set-up correctly * all we need to do here is to return correct path names. See also * GetJVMPath() and GetApplicationHome(). */ { if (!GetJREPath(jrepath, so_jrepath) ) { ReportErrorMessage("Error: could not find Java SE Runtime Environment.", JNI_TRUE); exit(2); } if (!GetJVMPath(jrepath, NULL, jvmpath, so_jvmpath)) { char * message=NULL; const char * format = "Error: no JVM at `%s'."; message = (char *)JLI_MemAlloc((strlen(format)+ strlen(jvmpath)) * sizeof(char)); sprintf(message, format, jvmpath); ReportErrorMessage(message, JNI_TRUE); exit(4); } } #endif /* ifndef GAMMA */ }
/* * Given a path to a jre to execute, this routine checks if this process * is indeed that jre. If not, it exec's that jre. * * We want to actually check the paths rather than just the version string * built into the executable, so that given version specification will yield * the exact same Java environment, regardless of the version of the arbitrary * launcher we start with. */ void ExecJRE(char *jre, char **argv) { char *progname; char path[MAXPATHLEN]; /* * Resolve the real path to the currently running launcher. */ if (GetModuleFileName(NULL, path, MAXPATHLEN) == 0) { ReportErrorMessage("Unable to resolve path to current executable", JNI_TRUE); exit(1); } /* * If the path to the selected JRE directory is a match to the initial * portion of the path to the currently executing JRE, we have a winner! * If so, just return. (strnicmp() is the Windows equiv. of strncasecmp().) */ if (strnicmp(jre, path, strlen(jre)) == 0) return; /* I am the droid you were looking for */ /* * Determine the executable we are building (or in the rare case, running). */ #ifdef JAVA_ARGS /* javac, jar and friends. */ progname = "java"; #else /* java, oldjava, javaw and friends */ #ifdef PROGNAME progname = PROGNAME; #else progname = *argv; if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { progname = s + 1; } #endif /* PROGNAME */ #endif /* JAVA_ARGS */ /* * If this isn't the selected version, exec the selected version. */ (void)strcat(strcat(strcpy(path, jre), "\\bin\\"), progname); argv[0] = progname; if (_launcher_debug) { int i; printf("execv(\"%s\"", path); for (i = 0; argv[i] != NULL; i++) printf(", \"%s\"", argv[i]); printf(")\n"); } /* * Although Windows has an execv() entrypoint, it really doesn't * know how to overlay a process: it can only create a new * process. This sounds well and good except that any processes * waiting on the process wake up and they shouldn't. Hence we need * to keep a chain of pseudo-zombie processes around just to * maintain the proper wait semantics. Fortunately the image size * of the launcher isn't too large at this time. * * In a more reasonable world, the code below would be ... * * execv(path, argv); * ReportErrorMessage2("Exec of %s failed\n", path, JNI_TRUE); * exit(1); * * Also note that typecast from the output of spawn to the parameter * of exit shouldn't be required. Whatever type these are, they should * match. However, in Visual C++ .NET, spawn is declared to be of * type intptr_t while the parameter to exit remains type int. Hence, * on the IA64 environment where an int is 32 bits and an intptr_t is * 64 bits, this is a narrowing cast which is reported as an error if * not explicit. */ exit((int)spawnv(_P_WAIT, path, argv)); }
/*----------------------------------------------------------------------------*/ int main(int argc, char **argv, char *envp) { char szMsg[128]; int Index, ReturnCode ; TID tidPager; ULONG ulRC; PAGEMSGINFO pInfo; printf("QuickPage/2 - OS/2 Operating System.\n"); printf("Version 1.0 - Aug 29 1995.\n"); #ifdef DEMO_ONLY printf("*************************\n"); printf("* EVALUATION COPY *\n"); printf("*************************\n"); #endif printf("Copyright (C) OS/Tools Incorporated 1995 - All Rights Reserved.\n"); bPopUp = FALSE; ConfigFileDefined = FALSE; LogFileDefined = FALSE; PinDefined = FALSE; DisplayHelp = FALSE; if (argc == 1) DisplayHelp = TRUE; memset(&pInfo, 0, sizeof(PAGEMSGINFO)); memset(&szConfigFile, 0, sizeof(szConfigFile)); memset(&szLogFile, 0, sizeof(szLogFile)); /*-----------------------------------------------------*/ /* First pass of parameters passed. */ /*-----------------------------------------------------*/ for(Index = 1; Index < argc; Index++) { ProcessParameters(argv[Index], &pInfo, TRUE); } if( ConfigFileDefined ) { ReturnCode = ProcessConfigFile(szConfigFile, &pInfo); if(ReturnCode) { ReportErrorMessage( (int)ReturnCode ); exit(ReturnCode); } } /*-----------------------------------------------------*/ /* Second pass of parameters passed to override */ /* default configuration in PAGEDEF.CFG */ /*-----------------------------------------------------*/ for(Index = 1; Index < argc; Index++) { ProcessParameters(argv[Index], &pInfo, FALSE); } if ( DisplayHelp ) { DisplaySyntax(); exit(ID_INCORRECT_SYNTAX); } if(pInfo.Message[0] == 0) strcpy(pInfo.Message, "No Text"); /*-----------------------------------------------------*/ /* When an individual PIN is passed as parameter and */ /* a CFG file is also defined, all other PINs defined */ /* in the CFG file are ignored. */ /*-----------------------------------------------------*/ if(PinDefined) { for(Index = 1; Index < MAX_PAGES_PER_CALL; Index++) memset(&pInfo.pSubscriberInfo[Index].PinID, 0, sizeof(pInfo.pSubscriberInfo[Index].PinID)); } printf("\n"); ReportErrorMessage( ID_BEGIN_COMMAND ); if( LogFileDefined || szLogFile ) { sprintf(szMsg, "QPI150 Page In Progress"); if(pInfo.SinglePage) { if(atoi(pInfo.pSubscriberInfo[0].PinID) != 0) { strcat(szMsg, " To PIN "); strcat(szMsg, pInfo.pSubscriberInfo[0].PinID); } } else { if(pInfo.GroupName[0] != 0) { strcat(szMsg, " To "); strcat(szMsg, pInfo.GroupName); } } if(pInfo.ServicePNum[0] != 0) { strcat(szMsg, ". Dialing "); strcat(szMsg, pInfo.ServicePNum); } strcat(szMsg, "...\n"); printf(szMsg); WriteMessageToLogFile( szLogFile, szMsg ); } ulRC = SendAlphaMessage((ULONG)&pInfo); ReportErrorMessage( (int)ulRC ); exit(ulRC); }
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPreviousInst, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wndClass; wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = "FOnline"; if (!RegisterClass(&wndClass)) { char* msg = FormatLastWin32Error(); ReportErrorMessage("Win32 error.", "Could not register window class: %s", msg); free(msg); return -1; } if (!OpenLogFile("FOnlineClient.log")) { ReportErrorMessage("IO error.", "Could not open log file."); return -1; } LoadSettings(); size_t modeWidth = screen_width[opt_screen_mode]; size_t modeHeight = screen_height[opt_screen_mode]; HWND hWnd = CreateWindow( "FOnline", "Fallout Online", WS_OVERLAPPEDWINDOW & (~WS_MAXIMIZEBOX) & (~WS_SIZEBOX) & (~WS_SYSMENU), 0,0,modeWidth + 5, modeHeight + 25, NULL, NULL, hInstance, NULL ); if (hWnd == NULL) { char* msg = FormatLastWin32Error(); ReportErrorMessage("Win32 error.", "Could not create window: %s", msg); free(msg); return -1; } ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); FONLINE_LOG("Starting FOnline...\n"); srand(GetTickCount()); engine = new FOnlineEngine; if (!engine->Init(hWnd)) { FONLINE_LOG("Could not initialize the engine.\n"); DestroyWindow(hWnd); return 0; } MSG msg; while(!cmn_Quit) { if(!cmn_lost) { if(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { engine->Render(); if (opt_sleep) Sleep(opt_sleep); } } else { GetMessage(&msg, NULL, NULL, NULL); TranslateMessage(&msg); DispatchMessage(&msg); } } FONLINE_LOG("\nFOnline Closed\n"); CloseLogFile(); delete engine; //SimpleLeakDetector::PrintAllLeaks(); _CrtDumpMemoryLeaks(); return 0; }