sla@2327: /* sla@2327: * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. sla@2327: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. sla@2327: * sla@2327: * This code is free software; you can redistribute it and/or modify it sla@2327: * under the terms of the GNU General Public License version 2 only, as sla@2327: * published by the Free Software Foundation. sla@2327: * sla@2327: * This code is distributed in the hope that it will be useful, but WITHOUT sla@2327: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or sla@2327: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License sla@2327: * version 2 for more details (a copy is included in the LICENSE file that sla@2327: * accompanied this code). sla@2327: * sla@2327: * You should have received a copy of the GNU General Public License version sla@2327: * 2 along with this work; if not, write to the Free Software Foundation, sla@2327: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. sla@2327: * sla@2327: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA sla@2327: * or visit www.oracle.com if you need additional information or have any sla@2327: * questions. sla@2327: * sla@2327: */ sla@2327: sla@2327: sla@2327: #include "java.h" sla@2327: #include sla@2327: #include sla@2327: #include sla@2327: #include sla@2369: #include sla@2327: #include sla@2327: #include sla@2327: #include sla@2327: #include sla@2327: #include sla@2327: #include sla@2327: #include sla@2327: sla@2327: #ifndef GAMMA sla@2327: #include "manifest_info.h" sla@2327: #include "version_comp.h" sla@2327: #endif sla@2327: sla@2327: #ifdef __linux__ sla@2327: #include sla@2327: #else sla@2327: #include sla@2327: #endif sla@2327: sla@2327: #define JVM_DLL "libjvm.so" sla@2327: #define JAVA_DLL "libjava.so" sla@2327: sla@2327: #ifndef GAMMA /* launcher.make defines ARCH */ sla@2327: /* sla@2327: * If a processor / os combination has the ability to run binaries of sla@2327: * two data models and cohabitation of jre/jdk bits with both data sla@2327: * models is supported, then DUAL_MODE is defined. When DUAL_MODE is sla@2327: * defined, the architecture names for the narrow and wide version of sla@2327: * the architecture are defined in LIBARCH64NAME and LIBARCH32NAME. Currently sla@2327: * only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux sla@2327: * i586/amd64 could be defined as DUAL_MODE but that is not the sla@2327: * current policy. sla@2327: */ sla@2327: sla@2327: #ifndef LIBARCHNAME sla@2327: # error "The macro LIBARCHNAME was not defined on the compile line" sla@2327: #endif sla@2327: sla@2327: #ifdef __sun sla@2327: # define DUAL_MODE sla@2327: # ifndef LIBARCH32NAME sla@2327: # error "The macro LIBARCH32NAME was not defined on the compile line" sla@2327: # endif sla@2327: # ifndef LIBARCH64NAME sla@2327: # error "The macro LIBARCH64NAME was not defined on the compile line" sla@2327: # endif sla@2327: # include sla@2327: # include sla@2327: # include sla@2327: #endif sla@2327: sla@2327: #endif /* ifndef GAMMA */ sla@2327: sla@2327: /* pointer to environment */ sla@2327: extern char **environ; sla@2327: sla@2327: #ifndef GAMMA sla@2327: /* sla@2327: * A collection of useful strings. One should think of these as #define sla@2327: * entries, but actual strings can be more efficient (with many compilers). sla@2327: */ sla@2327: #ifdef __linux__ sla@2327: static const char *system_dir = "/usr/java"; sla@2327: static const char *user_dir = "/java"; sla@2327: #else /* Solaris */ sla@2327: static const char *system_dir = "/usr/jdk"; sla@2327: static const char *user_dir = "/jdk"; sla@2327: #endif sla@2327: sla@2327: #endif /* ifndef GAMMA */ sla@2327: sla@2327: /* sla@2327: * Flowchart of launcher execs and options processing on unix sla@2327: * sla@2327: * The selection of the proper vm shared library to open depends on sla@2327: * several classes of command line options, including vm "flavor" sla@2327: * options (-client, -server) and the data model options, -d32 and sla@2327: * -d64, as well as a version specification which may have come from sla@2327: * the command line or from the manifest of an executable jar file. sla@2327: * The vm selection options are not passed to the running sla@2327: * virtual machine; they must be screened out by the launcher. sla@2327: * sla@2327: * The version specification (if any) is processed first by the sla@2327: * platform independent routine SelectVersion. This may result in sla@2327: * the exec of the specified launcher version. sla@2327: * sla@2327: * Typically, the launcher execs at least once to ensure a suitable sla@2327: * LD_LIBRARY_PATH is in effect for the process. The first exec sla@2327: * screens out all the data model options; leaving the choice of data sla@2327: * model implicit in the binary selected to run. However, in case no sla@2327: * exec is done, the data model options are screened out before the vm sla@2327: * is invoked. sla@2327: * sla@2327: * incoming argv ------------------------------ sla@2327: * | | sla@2327: * \|/ | sla@2327: * CheckJVMType | sla@2327: * (removes -client, -server, etc.) | sla@2327: * \|/ sla@2327: * CreateExecutionEnvironment sla@2327: * (removes -d32 and -d64, sla@2327: * determines desired data model, sla@2327: * sets up LD_LIBRARY_PATH, sla@2327: * and exec's) sla@2327: * | sla@2327: * -------------------------------------------- sla@2327: * | sla@2327: * \|/ sla@2327: * exec child 1 incoming argv ----------------- sla@2327: * | | sla@2327: * \|/ | sla@2327: * CheckJVMType | sla@2327: * (removes -client, -server, etc.) | sla@2327: * | \|/ sla@2327: * | CreateExecutionEnvironment sla@2327: * | (verifies desired data model sla@2327: * | is running and acceptable sla@2327: * | LD_LIBRARY_PATH; sla@2327: * | no-op in child) sla@2327: * | sla@2327: * \|/ sla@2327: * TranslateDashJArgs... sla@2327: * (Prepare to pass args to vm) sla@2327: * | sla@2327: * | sla@2327: * | sla@2327: * \|/ sla@2327: * ParseArguments sla@2327: * (ignores -d32 and -d64, sla@2327: * processes version options, sla@2327: * creates argument list for vm, sla@2327: * etc.) sla@2327: * sla@2327: */ sla@2327: sla@2327: static char *SetExecname(char **argv); sla@2327: static char * GetExecname(); sla@2327: static jboolean GetJVMPath(const char *jrepath, const char *jvmtype, sla@2327: char *jvmpath, jint jvmpathsize, char * arch); sla@2327: static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative); sla@2327: sla@2327: #ifndef GAMMA sla@2327: const char * sla@2327: GetArch() sla@2327: { sla@2327: return LIBARCHNAME; sla@2327: } sla@2327: #endif /* ifndef GAMMA */ sla@2327: sla@2327: void sla@2327: CreateExecutionEnvironment(int *_argcp, sla@2327: char ***_argvp, sla@2327: char jrepath[], sla@2327: jint so_jrepath, sla@2327: char jvmpath[], sla@2327: jint so_jvmpath, sla@2327: char **original_argv) { sla@2327: /* sla@2327: * First, determine if we are running the desired data model. If we sla@2327: * are running the desired data model, all the error messages sla@2327: * associated with calling GetJREPath, ReadKnownVMs, etc. should be sla@2327: * output. However, if we are not running the desired data model, sla@2327: * some of the errors should be suppressed since it is more sla@2327: * informative to issue an error message based on whether or not the sla@2327: * os/processor combination has dual mode capabilities. sla@2327: */ sla@2327: sla@2327: char *execname = NULL; sla@2327: int original_argc = *_argcp; sla@2327: jboolean jvmpathExists; sla@2327: sla@2327: /* Compute the name of the executable */ sla@2327: execname = SetExecname(*_argvp); sla@2327: sla@2327: #ifndef GAMMA sla@2327: /* Set the LD_LIBRARY_PATH environment variable, check data model sla@2327: flags, and exec process, if needed */ sla@2327: { sla@2327: char *arch = (char *)GetArch(); /* like sparc or sparcv9 */ sla@2327: char * jvmtype = NULL; sla@2327: int argc = *_argcp; sla@2327: char **argv = original_argv; sla@2327: sla@2327: char *runpath = NULL; /* existing effective LD_LIBRARY_PATH sla@2327: setting */ sla@2327: sla@2327: int running = /* What data model is being ILP32 => sla@2327: 32 bit vm; LP64 => 64 bit vm */ sla@2327: #ifdef _LP64 sla@2327: 64; sla@2327: #else sla@2327: 32; sla@2327: #endif sla@2327: sla@2327: int wanted = running; /* What data mode is being sla@2327: asked for? Current model is sla@2327: fine unless another model sla@2327: is asked for */ sla@2327: sla@2327: char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */ sla@2327: char* newpath = NULL; /* path on new LD_LIBRARY_PATH */ sla@2327: char* lastslash = NULL; sla@2327: sla@2327: char** newenvp = NULL; /* current environment */ sla@2327: sla@2327: char** newargv = NULL; sla@2327: int newargc = 0; sla@2327: #ifdef __sun sla@2327: char* dmpath = NULL; /* data model specific LD_LIBRARY_PATH, sla@2327: Solaris only */ sla@2327: #endif sla@2327: sla@2327: /* sla@2327: * Starting in 1.5, all unix platforms accept the -d32 and -d64 sla@2327: * options. On platforms where only one data-model is supported sla@2327: * (e.g. ia-64 Linux), using the flag for the other data model is sla@2327: * an error and will terminate the program. sla@2327: */ sla@2327: sla@2327: { /* open new scope to declare local variables */ sla@2327: int i; sla@2327: sla@2327: newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv)); sla@2327: newargv[newargc++] = argv[0]; sla@2327: sla@2327: /* scan for data model arguments and remove from argument list; sla@2327: last occurrence determines desired data model */ sla@2327: for (i=1; i < argc; i++) { sla@2327: sla@2327: if (strcmp(argv[i], "-J-d64") == 0 || strcmp(argv[i], "-d64") == 0) { sla@2327: wanted = 64; sla@2327: continue; sla@2327: } sla@2327: if (strcmp(argv[i], "-J-d32") == 0 || strcmp(argv[i], "-d32") == 0) { sla@2327: wanted = 32; sla@2327: continue; sla@2327: } sla@2327: newargv[newargc++] = argv[i]; sla@2327: sla@2327: #ifdef JAVA_ARGS sla@2327: if (argv[i][0] != '-') sla@2327: continue; sla@2327: #else sla@2327: if (strcmp(argv[i], "-classpath") == 0 || strcmp(argv[i], "-cp") == 0) { sla@2327: i++; sla@2327: if (i >= argc) break; sla@2327: newargv[newargc++] = argv[i]; sla@2327: continue; sla@2327: } sla@2327: if (argv[i][0] != '-') { i++; break; } sla@2327: #endif sla@2327: } sla@2327: sla@2327: /* copy rest of args [i .. argc) */ sla@2327: while (i < argc) { sla@2327: newargv[newargc++] = argv[i++]; sla@2327: } sla@2327: newargv[newargc] = NULL; sla@2327: sla@2327: /* sla@2327: * newargv has all proper arguments here sla@2327: */ sla@2327: sla@2327: argc = newargc; sla@2327: argv = newargv; sla@2327: } sla@2327: sla@2327: /* If the data model is not changing, it is an error if the sla@2327: jvmpath does not exist */ sla@2327: if (wanted == running) { sla@2327: /* Find out where the JRE is that we will be using. */ sla@2327: if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) { sla@2327: fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n"); sla@2327: exit(2); sla@2327: } sla@2327: sla@2327: /* Find the specified JVM type */ sla@2327: if (ReadKnownVMs(jrepath, arch, JNI_FALSE) < 1) { sla@2327: fprintf(stderr, "Error: no known VMs. (check for corrupt jvm.cfg file)\n"); sla@2327: exit(1); sla@2327: } sla@2327: sla@2327: jvmpath[0] = '\0'; sla@2327: jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE); sla@2327: sla@2327: if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) { sla@2327: fprintf(stderr, "Error: no `%s' JVM at `%s'.\n", jvmtype, jvmpath); sla@2327: exit(4); sla@2327: } sla@2327: } else { /* do the same speculatively or exit */ sla@2327: #ifdef DUAL_MODE sla@2327: if (running != wanted) { sla@2327: /* Find out where the JRE is that we will be using. */ sla@2327: if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE)) { sla@2327: goto EndDataModelSpeculate; sla@2327: } sla@2327: sla@2327: /* sla@2327: * Read in jvm.cfg for target data model and process vm sla@2327: * selection options. sla@2327: */ sla@2327: if (ReadKnownVMs(jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE) < 1) { sla@2327: goto EndDataModelSpeculate; sla@2327: } sla@2327: jvmpath[0] = '\0'; sla@2327: jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE); sla@2327: /* exec child can do error checking on the existence of the path */ sla@2327: jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, sla@2327: ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME)); sla@2327: sla@2327: } sla@2327: EndDataModelSpeculate: /* give up and let other code report error message */ sla@2327: ; sla@2327: #else sla@2327: fprintf(stderr, "Running a %d-bit JVM is not supported on this platform.\n", wanted); sla@2327: exit(1); sla@2327: #endif sla@2327: } sla@2327: sla@2327: /* sla@2327: * We will set the LD_LIBRARY_PATH as follows: sla@2327: * sla@2327: * o $JVMPATH (directory portion only) sla@2327: * o $JRE/lib/$LIBARCHNAME sla@2327: * o $JRE/../lib/$LIBARCHNAME sla@2327: * sla@2327: * followed by the user's previous effective LD_LIBRARY_PATH, if sla@2327: * any. sla@2327: */ sla@2327: sla@2327: #ifdef __sun sla@2327: /* sla@2327: * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH sla@2327: * variables: sla@2327: * sla@2327: * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if sla@2327: * data-model specific variables are not set. sla@2327: * sla@2327: * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH sla@2327: * for 64-bit binaries. sla@2327: * sla@2327: * 3. LD_LIBRARY_PATH_32 -- overrides and replaces LD_LIBRARY_PATH sla@2327: * for 32-bit binaries. sla@2327: * sla@2327: * The vm uses LD_LIBRARY_PATH to set the java.library.path system sla@2327: * property. To shield the vm from the complication of multiple sla@2327: * LD_LIBRARY_PATH variables, if the appropriate data model sla@2327: * specific variable is set, we will act as if LD_LIBRARY_PATH had sla@2327: * the value of the data model specific variant and the data model sla@2327: * specific variant will be unset. Note that the variable for the sla@2327: * *wanted* data model must be used (if it is set), not simply the sla@2327: * current running data model. sla@2327: */ sla@2327: sla@2327: switch(wanted) { sla@2327: case 0: sla@2327: if(running == 32) { sla@2327: dmpath = getenv("LD_LIBRARY_PATH_32"); sla@2327: wanted = 32; sla@2327: } sla@2327: else { sla@2327: dmpath = getenv("LD_LIBRARY_PATH_64"); sla@2327: wanted = 64; sla@2327: } sla@2327: break; sla@2327: sla@2327: case 32: sla@2327: dmpath = getenv("LD_LIBRARY_PATH_32"); sla@2327: break; sla@2327: sla@2327: case 64: sla@2327: dmpath = getenv("LD_LIBRARY_PATH_64"); sla@2327: break; sla@2327: sla@2327: default: sla@2327: fprintf(stderr, "Improper value at line %d.", __LINE__); sla@2327: exit(1); /* unknown value in wanted */ sla@2327: break; sla@2327: } sla@2327: sla@2327: /* sla@2327: * If dmpath is NULL, the relevant data model specific variable is sla@2327: * not set and normal LD_LIBRARY_PATH should be used. sla@2327: */ sla@2327: if( dmpath == NULL) { sla@2327: runpath = getenv("LD_LIBRARY_PATH"); sla@2327: } sla@2327: else { sla@2327: runpath = dmpath; sla@2327: } sla@2327: #else sla@2327: /* sla@2327: * If not on Solaris, assume only a single LD_LIBRARY_PATH sla@2327: * variable. sla@2327: */ sla@2327: runpath = getenv("LD_LIBRARY_PATH"); sla@2327: #endif /* __sun */ sla@2327: sla@2327: #ifdef __linux sla@2327: /* sla@2327: * On linux, if a binary is running as sgid or suid, glibc sets sla@2327: * LD_LIBRARY_PATH to the empty string for security purposes. (In sla@2327: * contrast, on Solaris the LD_LIBRARY_PATH variable for a sla@2327: * privileged binary does not lose its settings; but the dynamic sla@2327: * linker does apply more scrutiny to the path.) The launcher uses sla@2327: * the value of LD_LIBRARY_PATH to prevent an exec loop. sla@2327: * Therefore, if we are running sgid or suid, this function's sla@2327: * setting of LD_LIBRARY_PATH will be ineffective and we should sla@2327: * return from the function now. Getting the right libraries to sla@2327: * be found must be handled through other mechanisms. sla@2327: */ sla@2327: if((getgid() != getegid()) || (getuid() != geteuid()) ) { sla@2327: return; sla@2327: } sla@2327: #endif sla@2327: sla@2327: /* runpath contains current effective LD_LIBRARY_PATH setting */ sla@2327: sla@2327: jvmpath = JLI_StringDup(jvmpath); sla@2327: new_runpath = JLI_MemAlloc( ((runpath!=NULL)?strlen(runpath):0) + sla@2327: 2*strlen(jrepath) + 2*strlen(arch) + sla@2327: strlen(jvmpath) + 52); sla@2327: newpath = new_runpath + strlen("LD_LIBRARY_PATH="); sla@2327: sla@2327: sla@2327: /* sla@2327: * Create desired LD_LIBRARY_PATH value for target data model. sla@2327: */ sla@2327: { sla@2327: /* remove the name of the .so from the JVM path */ sla@2327: lastslash = strrchr(jvmpath, '/'); sla@2327: if (lastslash) sla@2327: *lastslash = '\0'; sla@2327: sla@2327: sla@2327: /* jvmpath, ((running != wanted)?((wanted==64)?"/"LIBARCH64NAME:"/.."):""), */ sla@2327: sla@2327: sprintf(new_runpath, "LD_LIBRARY_PATH=" sla@2327: "%s:" sla@2327: "%s/lib/%s:" sla@2327: "%s/../lib/%s", sla@2327: jvmpath, sla@2327: #ifdef DUAL_MODE sla@2327: jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), sla@2327: jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME) sla@2327: #else sla@2327: jrepath, arch, sla@2327: jrepath, arch sla@2327: #endif sla@2327: ); sla@2327: sla@2327: sla@2327: /* sla@2327: * Check to make sure that the prefix of the current path is the sla@2327: * desired environment variable setting. sla@2327: */ sla@2327: if (runpath != NULL && sla@2327: strncmp(newpath, runpath, strlen(newpath))==0 && sla@2327: (runpath[strlen(newpath)] == 0 || runpath[strlen(newpath)] == ':') && sla@2327: (running == wanted) /* data model does not have to be changed */ sla@2327: #ifdef __sun sla@2327: && (dmpath == NULL) /* data model specific variables not set */ sla@2327: #endif sla@2327: ) { sla@2327: sla@2327: return; sla@2327: sla@2327: } sla@2327: } sla@2327: sla@2327: /* sla@2327: * Place the desired environment setting onto the prefix of sla@2327: * LD_LIBRARY_PATH. Note that this prevents any possible infinite sla@2327: * loop of execv() because we test for the prefix, above. sla@2327: */ sla@2327: if (runpath != 0) { sla@2327: strcat(new_runpath, ":"); sla@2327: strcat(new_runpath, runpath); sla@2327: } sla@2327: sla@2327: if( putenv(new_runpath) != 0) { sla@2327: exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set sla@2327: properly */ sla@2327: } sla@2327: sla@2327: /* sla@2327: * Unix systems document that they look at LD_LIBRARY_PATH only sla@2327: * once at startup, so we have to re-exec the current executable sla@2327: * to get the changed environment variable to have an effect. sla@2327: */ sla@2327: sla@2327: #ifdef __sun sla@2327: /* sla@2327: * If dmpath is not NULL, remove the data model specific string sla@2327: * in the environment for the exec'ed child. sla@2327: */ sla@2327: sla@2327: if( dmpath != NULL) sla@2327: (void)UnsetEnv((wanted==32)?"LD_LIBRARY_PATH_32":"LD_LIBRARY_PATH_64"); sla@2327: #endif sla@2327: sla@2327: newenvp = environ; sla@2327: sla@2327: { sla@2327: char *newexec = execname; sla@2327: #ifdef DUAL_MODE sla@2327: /* sla@2327: * If the data model is being changed, the path to the sla@2327: * executable must be updated accordingly; the executable name sla@2327: * and directory the executable resides in are separate. In the sla@2327: * case of 32 => 64, the new bits are assumed to reside in, e.g. sla@2327: * "olddir/LIBARCH64NAME/execname"; in the case of 64 => 32, sla@2327: * the bits are assumed to be in "olddir/../execname". For example, sla@2327: * sla@2327: * olddir/sparcv9/execname sla@2327: * olddir/amd64/execname sla@2327: * sla@2327: * for Solaris SPARC and Linux amd64, respectively. sla@2327: */ sla@2327: sla@2327: if (running != wanted) { sla@2327: char *oldexec = strcpy(JLI_MemAlloc(strlen(execname) + 1), execname); sla@2327: char *olddir = oldexec; sla@2327: char *oldbase = strrchr(oldexec, '/'); sla@2327: sla@2327: sla@2327: newexec = JLI_MemAlloc(strlen(execname) + 20); sla@2327: *oldbase++ = 0; sla@2327: sprintf(newexec, "%s/%s/%s", olddir, sla@2327: ((wanted==64) ? LIBARCH64NAME : ".."), oldbase); sla@2327: argv[0] = newexec; sla@2327: } sla@2327: #endif sla@2327: sla@2327: (void)fflush(stdout); sla@2327: (void)fflush(stderr); sla@2327: execve(newexec, argv, newenvp); sla@2327: perror("execve()"); sla@2327: sla@2327: fprintf(stderr, "Error trying to exec %s.\n", newexec); sla@2327: fprintf(stderr, "Check if file exists and permissions are set correctly.\n"); sla@2327: sla@2327: #ifdef DUAL_MODE sla@2327: if (running != wanted) { sla@2327: fprintf(stderr, "Failed to start a %d-bit JVM process from a %d-bit JVM.\n", sla@2327: wanted, running); sla@2327: # ifdef __sun sla@2327: sla@2327: # ifdef __sparc sla@2327: fprintf(stderr, "Verify all necessary J2SE components have been installed.\n" ); sla@2327: fprintf(stderr, sla@2327: "(Solaris SPARC 64-bit components must be installed after 32-bit components.)\n" ); sla@2327: # else sla@2327: fprintf(stderr, "Either 64-bit processes are not supported by this platform\n"); sla@2327: fprintf(stderr, "or the 64-bit components have not been installed.\n"); sla@2327: # endif sla@2327: } sla@2327: # endif sla@2327: #endif sla@2327: sla@2327: } sla@2327: sla@2327: exit(1); sla@2327: } sla@2327: sla@2327: #else /* ifndef GAMMA */ sla@2327: sla@2327: /* sla@2327: * gamma launcher is simpler in that it doesn't handle VM flavors, data sla@2327: * model, LD_LIBRARY_PATH, etc. Assuming everything is set-up correctly sla@2327: * all we need to do here is to return correct path names. See also sla@2327: * GetJVMPath() and GetApplicationHome(). sla@2327: */ sla@2327: sla@2327: { char *arch = (char *) ARCH; /* like sparc or sparcv9 */ sla@2327: char *p; sla@2327: sla@2327: if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) { sla@2327: fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n"); sla@2327: exit(2); sla@2327: } sla@2327: sla@2327: if (!GetJVMPath(jrepath, NULL, jvmpath, so_jvmpath, arch )) { sla@2327: fprintf(stderr, "Error: no JVM at `%s'.\n", jvmpath); sla@2327: exit(4); sla@2327: } sla@2327: } sla@2327: sla@2327: #endif /* ifndef GAMMA */ sla@2327: } sla@2327: sla@2327: sla@2327: /* sla@2327: * On Solaris VM choosing is done by the launcher (java.c). sla@2327: */ sla@2327: static jboolean sla@2327: GetJVMPath(const char *jrepath, const char *jvmtype, sla@2327: char *jvmpath, jint jvmpathsize, char * arch) sla@2327: { sla@2327: struct stat s; sla@2327: sla@2327: #ifndef GAMMA sla@2327: if (strchr(jvmtype, '/')) { sla@2327: sprintf(jvmpath, "%s/" JVM_DLL, jvmtype); sla@2327: } else { sla@2327: sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype); sla@2327: } sla@2327: #else sla@2327: /* sla@2327: * For gamma launcher, JVM is either built-in or in the same directory. sla@2327: * Either way we return "/libjvm.so" where is the sla@2327: * directory where gamma launcher is located. sla@2327: */ sla@2327: sla@2327: char *p; sla@2327: sla@2327: snprintf(jvmpath, jvmpathsize, "%s", GetExecname()); sla@2327: p = strrchr(jvmpath, '/'); sla@2327: if (p) { sla@2327: /* replace executable name with libjvm.so */ sla@2327: snprintf(p + 1, jvmpathsize - (p + 1 - jvmpath), "%s", JVM_DLL); sla@2327: } else { sla@2327: /* this case shouldn't happen */ sla@2327: snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL); sla@2327: } sla@2327: #endif /* ifndef GAMMA */ sla@2327: sla@2327: if (_launcher_debug) sla@2327: printf("Does `%s' exist ... ", jvmpath); sla@2327: sla@2327: if (stat(jvmpath, &s) == 0) { sla@2327: if (_launcher_debug) sla@2327: printf("yes.\n"); sla@2327: return JNI_TRUE; sla@2327: } else { sla@2327: if (_launcher_debug) sla@2327: printf("no.\n"); sla@2327: return JNI_FALSE; sla@2327: } sla@2327: } sla@2327: sla@2327: /* sla@2327: * Find path to JRE based on .exe's location or registry settings. sla@2327: */ sla@2327: static jboolean sla@2327: GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative) sla@2327: { sla@2327: char libjava[MAXPATHLEN]; sla@2327: sla@2327: if (GetApplicationHome(path, pathsize)) { sla@2327: /* Is JRE co-located with the application? */ sla@2327: sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch); sla@2327: if (access(libjava, F_OK) == 0) { sla@2327: goto found; sla@2327: } sla@2327: sla@2327: /* Does the app ship a private JRE in /jre directory? */ sla@2327: sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch); sla@2327: if (access(libjava, F_OK) == 0) { sla@2327: strcat(path, "/jre"); sla@2327: goto found; sla@2327: } sla@2327: } sla@2327: sla@2327: if (!speculative) sla@2327: fprintf(stderr, "Error: could not find " JAVA_DLL "\n"); sla@2327: return JNI_FALSE; sla@2327: sla@2327: found: sla@2327: if (_launcher_debug) sla@2327: printf("JRE path is %s\n", path); sla@2327: return JNI_TRUE; sla@2327: } sla@2327: sla@2327: jboolean sla@2327: LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) sla@2327: { sla@2327: #ifdef GAMMA sla@2327: /* JVM is directly linked with gamma launcher; no dlopen() */ sla@2327: ifn->CreateJavaVM = JNI_CreateJavaVM; sla@2327: ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs; sla@2327: return JNI_TRUE; sla@2327: #else sla@2327: Dl_info dlinfo; sla@2327: void *libjvm; sla@2327: sla@2327: if (_launcher_debug) { sla@2327: printf("JVM path is %s\n", jvmpath); sla@2327: } sla@2327: sla@2327: libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL); sla@2327: if (libjvm == NULL) { sla@2327: #if defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */ sla@2327: FILE * fp; sla@2327: Elf32_Ehdr elf_head; sla@2327: int count; sla@2327: int location; sla@2327: sla@2327: fp = fopen(jvmpath, "r"); sla@2327: if(fp == NULL) sla@2327: goto error; sla@2327: sla@2327: /* read in elf header */ sla@2327: count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp); sla@2327: fclose(fp); sla@2327: if(count < 1) sla@2327: goto error; sla@2327: sla@2327: /* sla@2327: * Check for running a server vm (compiled with -xarch=v8plus) sla@2327: * on a stock v8 processor. In this case, the machine type in sla@2327: * the elf header would not be included the architecture list sla@2327: * provided by the isalist command, which is turn is gotten from sla@2327: * sysinfo. This case cannot occur on 64-bit hardware and thus sla@2327: * does not have to be checked for in binaries with an LP64 data sla@2327: * model. sla@2327: */ sla@2327: if(elf_head.e_machine == EM_SPARC32PLUS) { sla@2327: char buf[257]; /* recommended buffer size from sysinfo man sla@2327: page */ sla@2327: long length; sla@2327: char* location; sla@2327: sla@2327: length = sysinfo(SI_ISALIST, buf, 257); sla@2327: if(length > 0) { sla@2327: location = strstr(buf, "sparcv8plus "); sla@2327: if(location == NULL) { sla@2327: fprintf(stderr, "SPARC V8 processor detected; Server compiler requires V9 or better.\n"); sla@2327: fprintf(stderr, "Use Client compiler on V8 processors.\n"); sla@2327: fprintf(stderr, "Could not create the Java virtual machine.\n"); sla@2327: return JNI_FALSE; sla@2327: } sla@2327: } sla@2327: } sla@2327: #endif sla@2327: fprintf(stderr, "dl failure on line %d", __LINE__); sla@2327: goto error; sla@2327: } sla@2327: sla@2327: ifn->CreateJavaVM = (CreateJavaVM_t) sla@2327: dlsym(libjvm, "JNI_CreateJavaVM"); sla@2327: if (ifn->CreateJavaVM == NULL) sla@2327: goto error; sla@2327: sla@2327: ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t) sla@2327: dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs"); sla@2327: if (ifn->GetDefaultJavaVMInitArgs == NULL) sla@2327: goto error; sla@2327: sla@2327: return JNI_TRUE; sla@2327: sla@2327: error: sla@2327: fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror()); sla@2327: return JNI_FALSE; sla@2327: #endif /* ifndef GAMMA */ sla@2327: } sla@2327: sla@2327: /* sla@2327: * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put sla@2327: * "/foo" into buf. sla@2327: */ sla@2327: jboolean sla@2327: GetApplicationHome(char *buf, jint bufsize) sla@2327: { sla@2327: #ifdef __linux__ sla@2327: char *execname = GetExecname(); sla@2327: if (execname) { sla@2327: strncpy(buf, execname, bufsize-1); sla@2327: buf[bufsize-1] = '\0'; sla@2327: } else { sla@2327: return JNI_FALSE; sla@2327: } sla@2327: #else sla@2327: Dl_info dlinfo; sla@2327: sla@2327: dladdr((void *)GetApplicationHome, &dlinfo); sla@2327: if (realpath(dlinfo.dli_fname, buf) == NULL) { sla@2327: fprintf(stderr, "Error: realpath(`%s') failed.\n", dlinfo.dli_fname); sla@2327: return JNI_FALSE; sla@2327: } sla@2327: #endif sla@2327: sla@2327: #ifdef GAMMA sla@2327: { sla@2369: /* gamma launcher uses JAVA_HOME environment variable to find JDK/JRE */ sla@2369: char* java_home_var = getenv("JAVA_HOME"); sla@2327: if (java_home_var == NULL) { sla@2369: printf("JAVA_HOME must point to a valid JDK/JRE to run gamma\n"); sla@2327: return JNI_FALSE; sla@2327: } sla@2327: snprintf(buf, bufsize, "%s", java_home_var); sla@2327: } sla@2327: #else sla@2327: if (strrchr(buf, '/') == 0) { sla@2327: buf[0] = '\0'; sla@2327: return JNI_FALSE; sla@2327: } sla@2327: *(strrchr(buf, '/')) = '\0'; /* executable file */ sla@2327: if (strlen(buf) < 4 || strrchr(buf, '/') == 0) { sla@2327: buf[0] = '\0'; sla@2327: return JNI_FALSE; sla@2327: } sla@2327: if (strcmp("/bin", buf + strlen(buf) - 4) != 0) sla@2327: *(strrchr(buf, '/')) = '\0'; /* sparcv9 or amd64 */ sla@2327: if (strlen(buf) < 4 || strcmp("/bin", buf + strlen(buf) - 4) != 0) { sla@2327: buf[0] = '\0'; sla@2327: return JNI_FALSE; sla@2327: } sla@2327: *(strrchr(buf, '/')) = '\0'; /* bin */ sla@2327: #endif /* ifndef GAMMA */ sla@2327: sla@2327: return JNI_TRUE; sla@2327: } sla@2327: sla@2327: sla@2327: /* sla@2327: * Return true if the named program exists sla@2327: */ sla@2327: static int sla@2327: ProgramExists(char *name) sla@2327: { sla@2327: struct stat sb; sla@2327: if (stat(name, &sb) != 0) return 0; sla@2327: if (S_ISDIR(sb.st_mode)) return 0; sla@2327: return (sb.st_mode & S_IEXEC) != 0; sla@2327: } sla@2327: sla@2327: sla@2327: /* sla@2327: * Find a command in a directory, returning the path. sla@2327: */ sla@2327: static char * sla@2327: Resolve(char *indir, char *cmd) sla@2327: { sla@2327: char name[PATH_MAX + 2], *real; sla@2327: sla@2327: if ((strlen(indir) + strlen(cmd) + 1) > PATH_MAX) return 0; sla@2327: sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd); sla@2327: if (!ProgramExists(name)) return 0; sla@2327: real = JLI_MemAlloc(PATH_MAX + 2); sla@2327: if (!realpath(name, real)) sla@2327: strcpy(real, name); sla@2327: return real; sla@2327: } sla@2327: sla@2327: sla@2327: /* sla@2327: * Find a path for the executable sla@2327: */ sla@2327: static char * sla@2327: FindExecName(char *program) sla@2327: { sla@2327: char cwdbuf[PATH_MAX+2]; sla@2327: char *path; sla@2327: char *tmp_path; sla@2327: char *f; sla@2327: char *result = NULL; sla@2327: sla@2327: /* absolute path? */ sla@2327: if (*program == FILE_SEPARATOR || sla@2327: (FILE_SEPARATOR=='\\' && strrchr(program, ':'))) sla@2327: return Resolve("", program+1); sla@2327: sla@2327: /* relative path? */ sla@2327: if (strrchr(program, FILE_SEPARATOR) != 0) { sla@2327: char buf[PATH_MAX+2]; sla@2327: return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program); sla@2327: } sla@2327: sla@2327: /* from search path? */ sla@2327: path = getenv("PATH"); sla@2327: if (!path || !*path) path = "."; sla@2327: tmp_path = JLI_MemAlloc(strlen(path) + 2); sla@2327: strcpy(tmp_path, path); sla@2327: sla@2327: for (f=tmp_path; *f && result==0; ) { sla@2327: char *s = f; sla@2327: while (*f && (*f != PATH_SEPARATOR)) ++f; sla@2327: if (*f) *f++ = 0; sla@2327: if (*s == FILE_SEPARATOR) sla@2327: result = Resolve(s, program); sla@2327: else { sla@2327: /* relative path element */ sla@2327: char dir[2*PATH_MAX]; sla@2327: sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)), sla@2327: FILE_SEPARATOR, s); sla@2327: result = Resolve(dir, program); sla@2327: } sla@2327: if (result != 0) break; sla@2327: } sla@2327: sla@2327: JLI_MemFree(tmp_path); sla@2327: return result; sla@2327: } sla@2327: sla@2327: sla@2327: /* Store the name of the executable once computed */ sla@2327: static char *execname = NULL; sla@2327: sla@2327: /* sla@2327: * Compute the name of the executable sla@2327: * sla@2327: * In order to re-exec securely we need the absolute path of the sla@2327: * executable. On Solaris getexecname(3c) may not return an absolute sla@2327: * path so we use dladdr to get the filename of the executable and sla@2327: * then use realpath to derive an absolute path. From Solaris 9 sla@2327: * onwards the filename returned in DL_info structure from dladdr is sla@2327: * an absolute pathname so technically realpath isn't required. sla@2327: * On Linux we read the executable name from /proc/self/exe. sla@2327: * As a fallback, and for platforms other than Solaris and Linux, sla@2327: * we use FindExecName to compute the executable name. sla@2327: */ sla@2327: static char * sla@2327: SetExecname(char **argv) sla@2327: { sla@2327: char* exec_path = NULL; sla@2327: sla@2327: if (execname != NULL) /* Already determined */ sla@2327: return (execname); sla@2327: sla@2327: #if defined(__sun) sla@2327: { sla@2327: Dl_info dlinfo; sla@2327: if (dladdr((void*)&SetExecname, &dlinfo)) { sla@2327: char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1); sla@2327: if (resolved != NULL) { sla@2327: exec_path = realpath(dlinfo.dli_fname, resolved); sla@2327: if (exec_path == NULL) { sla@2327: JLI_MemFree(resolved); sla@2327: } sla@2327: } sla@2327: } sla@2327: } sla@2327: #elif defined(__linux__) sla@2327: { sla@2327: const char* self = "/proc/self/exe"; sla@2327: char buf[PATH_MAX+1]; sla@2327: int len = readlink(self, buf, PATH_MAX); sla@2327: if (len >= 0) { sla@2327: buf[len] = '\0'; /* readlink doesn't nul terminate */ sla@2327: exec_path = JLI_StringDup(buf); sla@2327: } sla@2327: } sla@2327: #else /* !__sun && !__linux */ sla@2327: { sla@2327: /* Not implemented */ sla@2327: } sla@2327: #endif sla@2327: sla@2327: if (exec_path == NULL) { sla@2327: exec_path = FindExecName(argv[0]); sla@2327: } sla@2327: execname = exec_path; sla@2327: return exec_path; sla@2327: } sla@2327: sla@2327: /* sla@2327: * Return the name of the executable. Used in java_md.c to find the JRE area. sla@2327: */ sla@2327: static char * sla@2327: GetExecname() { sla@2327: return execname; sla@2327: } sla@2327: sla@2327: void ReportErrorMessage(char * message, jboolean always) { sla@2327: if (always) { sla@2327: fprintf(stderr, "%s\n", message); sla@2327: } sla@2327: } sla@2327: sla@2327: void ReportErrorMessage2(char * format, char * string, jboolean always) { sla@2327: if (always) { sla@2327: fprintf(stderr, format, string); sla@2327: fprintf(stderr, "\n"); sla@2327: } sla@2327: } sla@2327: sla@2327: void ReportExceptionDescription(JNIEnv * env) { sla@2327: (*env)->ExceptionDescribe(env); sla@2327: } sla@2327: sla@2327: /* sla@2327: * Return JNI_TRUE for an option string that has no effect but should sla@2327: * _not_ be passed on to the vm; return JNI_FALSE otherwise. On sla@2327: * Solaris SPARC, this screening needs to be done if: sla@2327: * 1) LD_LIBRARY_PATH does _not_ need to be reset and sla@2327: * 2) -d32 or -d64 is passed to a binary with a matching data model sla@2327: * (the exec in SetLibraryPath removes -d options and points the sla@2327: * exec to the proper binary). When this exec is not done, these options sla@2327: * would end up getting passed onto the vm. sla@2327: */ sla@2327: jboolean RemovableMachineDependentOption(char * option) { sla@2327: /* sla@2327: * Unconditionally remove both -d32 and -d64 options since only sla@2327: * the last such options has an effect; e.g. sla@2327: * java -d32 -d64 -d32 -version sla@2327: * is equivalent to sla@2327: * java -d32 -version sla@2327: */ sla@2327: sla@2327: if( (strcmp(option, "-d32") == 0 ) || sla@2327: (strcmp(option, "-d64") == 0 )) sla@2327: return JNI_TRUE; sla@2327: else sla@2327: return JNI_FALSE; sla@2327: } sla@2327: sla@2327: void PrintMachineDependentOptions() { sla@2327: fprintf(stdout, sla@2327: " -d32 use a 32-bit data model if available\n" sla@2327: "\n" sla@2327: " -d64 use a 64-bit data model if available\n"); sla@2327: return; sla@2327: } sla@2327: sla@2327: #ifndef GAMMA sla@2327: /* sla@2327: * The following methods (down to ServerClassMachine()) answer sla@2327: * the question about whether a machine is a "server-class" sla@2327: * machine. A server-class machine is loosely defined as one sla@2327: * with 2 or more processors and 2 gigabytes or more physical sla@2327: * memory. The definition of a processor is a physical package, sla@2327: * not a hyperthreaded chip masquerading as a multi-processor. sla@2327: * The definition of memory is also somewhat fuzzy, since x86 sla@2327: * machines seem not to report all the memory in their DIMMs, we sla@2327: * think because of memory mapping of graphics cards, etc. sla@2327: * sla@2327: * This code is somewhat more confused with #ifdef's than we'd sla@2327: * like because this file is used by both Solaris and Linux sla@2327: * platforms, and so needs to be parameterized for SPARC and sla@2327: * i586 hardware. The other Linux platforms (amd64 and ia64) sla@2327: * don't even ask this question, because they only come with sla@2327: * server JVMs. */ sla@2327: sla@2327: # define KB (1024UL) sla@2327: # define MB (1024UL * KB) sla@2327: # define GB (1024UL * MB) sla@2327: sla@2327: /* Compute physical memory by asking the OS */ sla@2327: uint64_t sla@2327: physical_memory(void) { sla@2327: const uint64_t pages = (uint64_t) sysconf(_SC_PHYS_PAGES); sla@2327: const uint64_t page_size = (uint64_t) sysconf(_SC_PAGESIZE); sla@2327: const uint64_t result = pages * page_size; sla@2327: # define UINT64_FORMAT "%" PRIu64 sla@2327: sla@2327: if (_launcher_debug) { sla@2327: printf("pages: " UINT64_FORMAT sla@2327: " page_size: " UINT64_FORMAT sla@2327: " physical memory: " UINT64_FORMAT " (%.3fGB)\n", sla@2327: pages, page_size, result, result / (double) GB); sla@2327: } sla@2327: return result; sla@2327: } sla@2327: sla@2327: #if defined(__sun) && defined(__sparc) sla@2327: sla@2327: /* Methods for solaris-sparc: these are easy. */ sla@2327: sla@2327: /* Ask the OS how many processors there are. */ sla@2327: unsigned long sla@2327: physical_processors(void) { sla@2327: const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF); sla@2327: sla@2327: if (_launcher_debug) { sla@2327: printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors); sla@2327: } sla@2327: return sys_processors; sla@2327: } sla@2327: sla@2327: /* The solaris-sparc version of the "server-class" predicate. */ sla@2327: jboolean sla@2327: solaris_sparc_ServerClassMachine(void) { sla@2327: jboolean result = JNI_FALSE; sla@2327: /* How big is a server class machine? */ sla@2327: const unsigned long server_processors = 2UL; sla@2327: const uint64_t server_memory = 2UL * GB; sla@2327: const uint64_t actual_memory = physical_memory(); sla@2327: sla@2327: /* Is this a server class machine? */ sla@2327: if (actual_memory >= server_memory) { sla@2327: const unsigned long actual_processors = physical_processors(); sla@2327: if (actual_processors >= server_processors) { sla@2327: result = JNI_TRUE; sla@2327: } sla@2327: } sla@2327: if (_launcher_debug) { sla@2327: printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n", sla@2327: (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE")); sla@2327: } sla@2327: return result; sla@2327: } sla@2327: sla@2327: #endif /* __sun && __sparc */ sla@2327: sla@2327: #if defined(__sun) && defined(i586) sla@2327: sla@2327: /* sla@2327: * A utility method for asking the CPU about itself. sla@2327: * There's a corresponding version of linux-i586 sla@2327: * because the compilers are different. sla@2327: */ sla@2327: void sla@2327: get_cpuid(uint32_t arg, sla@2327: uint32_t* eaxp, sla@2327: uint32_t* ebxp, sla@2327: uint32_t* ecxp, sla@2327: uint32_t* edxp) { sla@2327: #ifdef _LP64 sla@2327: asm( sla@2327: /* rbx is a callee-saved register */ sla@2327: " movq %rbx, %r11 \n" sla@2327: /* rdx and rcx are 3rd and 4th argument registers */ sla@2327: " movq %rdx, %r10 \n" sla@2327: " movq %rcx, %r9 \n" sla@2327: " movl %edi, %eax \n" sla@2327: " cpuid \n" sla@2327: " movl %eax, (%rsi)\n" sla@2327: " movl %ebx, (%r10)\n" sla@2327: " movl %ecx, (%r9) \n" sla@2327: " movl %edx, (%r8) \n" sla@2327: /* Restore rbx */ sla@2327: " movq %r11, %rbx"); sla@2327: #else sla@2327: /* EBX is a callee-saved register */ sla@2327: asm(" pushl %ebx"); sla@2327: /* Need ESI for storing through arguments */ sla@2327: asm(" pushl %esi"); sla@2327: asm(" movl 8(%ebp), %eax \n" sla@2327: " cpuid \n" sla@2327: " movl 12(%ebp), %esi \n" sla@2327: " movl %eax, (%esi) \n" sla@2327: " movl 16(%ebp), %esi \n" sla@2327: " movl %ebx, (%esi) \n" sla@2327: " movl 20(%ebp), %esi \n" sla@2327: " movl %ecx, (%esi) \n" sla@2327: " movl 24(%ebp), %esi \n" sla@2327: " movl %edx, (%esi) "); sla@2327: /* Restore ESI and EBX */ sla@2327: asm(" popl %esi"); sla@2327: /* Restore EBX */ sla@2327: asm(" popl %ebx"); sla@2327: #endif sla@2327: } sla@2327: sla@2327: #endif /* __sun && i586 */ sla@2327: sla@2327: #if defined(__linux__) && defined(i586) sla@2327: sla@2327: /* sla@2327: * A utility method for asking the CPU about itself. sla@2327: * There's a corresponding version of solaris-i586 sla@2327: * because the compilers are different. sla@2327: */ sla@2327: void sla@2327: get_cpuid(uint32_t arg, sla@2327: uint32_t* eaxp, sla@2327: uint32_t* ebxp, sla@2327: uint32_t* ecxp, sla@2327: uint32_t* edxp) { sla@2327: #ifdef _LP64 sla@2327: __asm__ volatile (/* Instructions */ sla@2327: " movl %4, %%eax \n" sla@2327: " cpuid \n" sla@2327: " movl %%eax, (%0)\n" sla@2327: " movl %%ebx, (%1)\n" sla@2327: " movl %%ecx, (%2)\n" sla@2327: " movl %%edx, (%3)\n" sla@2327: : /* Outputs */ sla@2327: : /* Inputs */ sla@2327: "r" (eaxp), sla@2327: "r" (ebxp), sla@2327: "r" (ecxp), sla@2327: "r" (edxp), sla@2327: "r" (arg) sla@2327: : /* Clobbers */ sla@2327: "%rax", "%rbx", "%rcx", "%rdx", "memory" sla@2327: ); sla@2327: #else sla@2327: uint32_t value_of_eax = 0; sla@2327: uint32_t value_of_ebx = 0; sla@2327: uint32_t value_of_ecx = 0; sla@2327: uint32_t value_of_edx = 0; sla@2327: __asm__ volatile (/* Instructions */ sla@2327: /* ebx is callee-save, so push it */ sla@2327: " pushl %%ebx \n" sla@2327: " movl %4, %%eax \n" sla@2327: " cpuid \n" sla@2327: " movl %%eax, %0 \n" sla@2327: " movl %%ebx, %1 \n" sla@2327: " movl %%ecx, %2 \n" sla@2327: " movl %%edx, %3 \n" sla@2327: /* restore ebx */ sla@2327: " popl %%ebx \n" sla@2327: sla@2327: : /* Outputs */ sla@2327: "=m" (value_of_eax), sla@2327: "=m" (value_of_ebx), sla@2327: "=m" (value_of_ecx), sla@2327: "=m" (value_of_edx) sla@2327: : /* Inputs */ sla@2327: "m" (arg) sla@2327: : /* Clobbers */ sla@2327: "%eax", "%ecx", "%edx" sla@2327: ); sla@2327: *eaxp = value_of_eax; sla@2327: *ebxp = value_of_ebx; sla@2327: *ecxp = value_of_ecx; sla@2327: *edxp = value_of_edx; sla@2327: #endif sla@2327: } sla@2327: sla@2327: #endif /* __linux__ && i586 */ sla@2327: sla@2327: #ifdef i586 sla@2327: /* sla@2327: * Routines shared by solaris-i586 and linux-i586. sla@2327: */ sla@2327: sla@2327: enum HyperThreadingSupport_enum { sla@2327: hts_supported = 1, sla@2327: hts_too_soon_to_tell = 0, sla@2327: hts_not_supported = -1, sla@2327: hts_not_pentium4 = -2, sla@2327: hts_not_intel = -3 sla@2327: }; sla@2327: typedef enum HyperThreadingSupport_enum HyperThreadingSupport; sla@2327: sla@2327: /* Determine if hyperthreading is supported */ sla@2327: HyperThreadingSupport sla@2327: hyperthreading_support(void) { sla@2327: HyperThreadingSupport result = hts_too_soon_to_tell; sla@2327: /* Bits 11 through 8 is family processor id */ sla@2327: # define FAMILY_ID_SHIFT 8 sla@2327: # define FAMILY_ID_MASK 0xf sla@2327: /* Bits 23 through 20 is extended family processor id */ sla@2327: # define EXT_FAMILY_ID_SHIFT 20 sla@2327: # define EXT_FAMILY_ID_MASK 0xf sla@2327: /* Pentium 4 family processor id */ sla@2327: # define PENTIUM4_FAMILY_ID 0xf sla@2327: /* Bit 28 indicates Hyper-Threading Technology support */ sla@2327: # define HT_BIT_SHIFT 28 sla@2327: # define HT_BIT_MASK 1 sla@2327: uint32_t vendor_id[3] = { 0U, 0U, 0U }; sla@2327: uint32_t value_of_eax = 0U; sla@2327: uint32_t value_of_edx = 0U; sla@2327: uint32_t dummy = 0U; sla@2327: sla@2327: /* Yes, this is supposed to be [0], [2], [1] */ sla@2327: get_cpuid(0, &dummy, &vendor_id[0], &vendor_id[2], &vendor_id[1]); sla@2327: if (_launcher_debug) { sla@2327: printf("vendor: %c %c %c %c %c %c %c %c %c %c %c %c \n", sla@2327: ((vendor_id[0] >> 0) & 0xff), sla@2327: ((vendor_id[0] >> 8) & 0xff), sla@2327: ((vendor_id[0] >> 16) & 0xff), sla@2327: ((vendor_id[0] >> 24) & 0xff), sla@2327: ((vendor_id[1] >> 0) & 0xff), sla@2327: ((vendor_id[1] >> 8) & 0xff), sla@2327: ((vendor_id[1] >> 16) & 0xff), sla@2327: ((vendor_id[1] >> 24) & 0xff), sla@2327: ((vendor_id[2] >> 0) & 0xff), sla@2327: ((vendor_id[2] >> 8) & 0xff), sla@2327: ((vendor_id[2] >> 16) & 0xff), sla@2327: ((vendor_id[2] >> 24) & 0xff)); sla@2327: } sla@2327: get_cpuid(1, &value_of_eax, &dummy, &dummy, &value_of_edx); sla@2327: if (_launcher_debug) { sla@2327: printf("value_of_eax: 0x%x value_of_edx: 0x%x\n", sla@2327: value_of_eax, value_of_edx); sla@2327: } sla@2327: if ((((value_of_eax >> FAMILY_ID_SHIFT) & FAMILY_ID_MASK) == PENTIUM4_FAMILY_ID) || sla@2327: (((value_of_eax >> EXT_FAMILY_ID_SHIFT) & EXT_FAMILY_ID_MASK) != 0)) { sla@2327: if ((((vendor_id[0] >> 0) & 0xff) == 'G') && sla@2327: (((vendor_id[0] >> 8) & 0xff) == 'e') && sla@2327: (((vendor_id[0] >> 16) & 0xff) == 'n') && sla@2327: (((vendor_id[0] >> 24) & 0xff) == 'u') && sla@2327: (((vendor_id[1] >> 0) & 0xff) == 'i') && sla@2327: (((vendor_id[1] >> 8) & 0xff) == 'n') && sla@2327: (((vendor_id[1] >> 16) & 0xff) == 'e') && sla@2327: (((vendor_id[1] >> 24) & 0xff) == 'I') && sla@2327: (((vendor_id[2] >> 0) & 0xff) == 'n') && sla@2327: (((vendor_id[2] >> 8) & 0xff) == 't') && sla@2327: (((vendor_id[2] >> 16) & 0xff) == 'e') && sla@2327: (((vendor_id[2] >> 24) & 0xff) == 'l')) { sla@2327: if (((value_of_edx >> HT_BIT_SHIFT) & HT_BIT_MASK) == HT_BIT_MASK) { sla@2327: if (_launcher_debug) { sla@2327: printf("Hyperthreading supported\n"); sla@2327: } sla@2327: result = hts_supported; sla@2327: } else { sla@2327: if (_launcher_debug) { sla@2327: printf("Hyperthreading not supported\n"); sla@2327: } sla@2327: result = hts_not_supported; sla@2327: } sla@2327: } else { sla@2327: if (_launcher_debug) { sla@2327: printf("Not GenuineIntel\n"); sla@2327: } sla@2327: result = hts_not_intel; sla@2327: } sla@2327: } else { sla@2327: if (_launcher_debug) { sla@2327: printf("not Pentium 4 or extended\n"); sla@2327: } sla@2327: result = hts_not_pentium4; sla@2327: } sla@2327: return result; sla@2327: } sla@2327: sla@2327: /* Determine how many logical processors there are per CPU */ sla@2327: unsigned int sla@2327: logical_processors_per_package(void) { sla@2327: /* sla@2327: * After CPUID with EAX==1, register EBX bits 23 through 16 sla@2327: * indicate the number of logical processors per package sla@2327: */ sla@2327: # define NUM_LOGICAL_SHIFT 16 sla@2327: # define NUM_LOGICAL_MASK 0xff sla@2327: unsigned int result = 1U; sla@2327: const HyperThreadingSupport hyperthreading = hyperthreading_support(); sla@2327: sla@2327: if (hyperthreading == hts_supported) { sla@2327: uint32_t value_of_ebx = 0U; sla@2327: uint32_t dummy = 0U; sla@2327: sla@2327: get_cpuid(1, &dummy, &value_of_ebx, &dummy, &dummy); sla@2327: result = (value_of_ebx >> NUM_LOGICAL_SHIFT) & NUM_LOGICAL_MASK; sla@2327: if (_launcher_debug) { sla@2327: printf("logical processors per package: %u\n", result); sla@2327: } sla@2327: } sla@2327: return result; sla@2327: } sla@2327: sla@2327: /* Compute the number of physical processors, not logical processors */ sla@2327: unsigned long sla@2327: physical_processors(void) { sla@2327: const long sys_processors = sysconf(_SC_NPROCESSORS_CONF); sla@2327: unsigned long result = sys_processors; sla@2327: sla@2327: if (_launcher_debug) { sla@2327: printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors); sla@2327: } sla@2327: if (sys_processors > 1) { sla@2327: unsigned int logical_processors = logical_processors_per_package(); sla@2327: if (logical_processors > 1) { sla@2327: result = (unsigned long) sys_processors / logical_processors; sla@2327: } sla@2327: } sla@2327: if (_launcher_debug) { sla@2327: printf("physical processors: %lu\n", result); sla@2327: } sla@2327: return result; sla@2327: } sla@2327: sla@2327: #endif /* i586 */ sla@2327: sla@2327: #if defined(__sun) && defined(i586) sla@2327: sla@2327: /* The definition of a server-class machine for solaris-i586/amd64 */ sla@2327: jboolean sla@2327: solaris_i586_ServerClassMachine(void) { sla@2327: jboolean result = JNI_FALSE; sla@2327: /* How big is a server class machine? */ sla@2327: const unsigned long server_processors = 2UL; sla@2327: const uint64_t server_memory = 2UL * GB; sla@2327: /* sla@2327: * We seem not to get our full complement of memory. sla@2327: * We allow some part (1/8?) of the memory to be "missing", sla@2327: * based on the sizes of DIMMs, and maybe graphics cards. sla@2327: */ sla@2327: const uint64_t missing_memory = 256UL * MB; sla@2327: const uint64_t actual_memory = physical_memory(); sla@2327: sla@2327: /* Is this a server class machine? */ sla@2327: if (actual_memory >= (server_memory - missing_memory)) { sla@2327: const unsigned long actual_processors = physical_processors(); sla@2327: if (actual_processors >= server_processors) { sla@2327: result = JNI_TRUE; sla@2327: } sla@2327: } sla@2327: if (_launcher_debug) { sla@2327: printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n", sla@2327: (result == JNI_TRUE ? "true" : "false")); sla@2327: } sla@2327: return result; sla@2327: } sla@2327: sla@2327: #endif /* __sun && i586 */ sla@2327: sla@2327: #if defined(__linux__) && defined(i586) sla@2327: sla@2327: /* The definition of a server-class machine for linux-i586 */ sla@2327: jboolean sla@2327: linux_i586_ServerClassMachine(void) { sla@2327: jboolean result = JNI_FALSE; sla@2327: /* How big is a server class machine? */ sla@2327: const unsigned long server_processors = 2UL; sla@2327: const uint64_t server_memory = 2UL * GB; sla@2327: /* sla@2327: * We seem not to get our full complement of memory. sla@2327: * We allow some part (1/8?) of the memory to be "missing", sla@2327: * based on the sizes of DIMMs, and maybe graphics cards. sla@2327: */ sla@2327: const uint64_t missing_memory = 256UL * MB; sla@2327: const uint64_t actual_memory = physical_memory(); sla@2327: sla@2327: /* Is this a server class machine? */ sla@2327: if (actual_memory >= (server_memory - missing_memory)) { sla@2327: const unsigned long actual_processors = physical_processors(); sla@2327: if (actual_processors >= server_processors) { sla@2327: result = JNI_TRUE; sla@2327: } sla@2327: } sla@2327: if (_launcher_debug) { sla@2327: printf("linux_" LIBARCHNAME "_ServerClassMachine: %s\n", sla@2327: (result == JNI_TRUE ? "true" : "false")); sla@2327: } sla@2327: return result; sla@2327: } sla@2327: sla@2327: #endif /* __linux__ && i586 */ sla@2327: sla@2327: /* Dispatch to the platform-specific definition of "server-class" */ sla@2327: jboolean sla@2327: ServerClassMachine(void) { sla@2327: jboolean result = JNI_FALSE; sla@2327: #if defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE) sla@2327: result = JNI_FALSE; sla@2327: #elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE) sla@2327: result = JNI_TRUE; sla@2327: #elif defined(__sun) && defined(__sparc) sla@2327: result = solaris_sparc_ServerClassMachine(); sla@2327: #elif defined(__sun) && defined(i586) sla@2327: result = solaris_i586_ServerClassMachine(); sla@2327: #elif defined(__linux__) && defined(i586) sla@2327: result = linux_i586_ServerClassMachine(); sla@2327: #else sla@2327: if (_launcher_debug) { sla@2327: printf("ServerClassMachine: returns default value of %s\n", sla@2327: (result == JNI_TRUE ? "true" : "false")); sla@2327: } sla@2327: #endif sla@2327: return result; sla@2327: } sla@2327: sla@2327: /* sla@2327: * Since using the file system as a registry is a bit risky, perform sla@2327: * additional sanity checks on the identified directory to validate sla@2327: * it as a valid jre/sdk. sla@2327: * sla@2327: * Return 0 if the tests fail; otherwise return non-zero (true). sla@2327: * sla@2327: * Note that checking for anything more than the existence of an sla@2327: * executable object at bin/java relative to the path being checked sla@2327: * will break the regression tests. sla@2327: */ sla@2327: static int sla@2327: CheckSanity(char *path, char *dir) sla@2327: { sla@2327: char buffer[PATH_MAX]; sla@2327: sla@2327: if (strlen(path) + strlen(dir) + 11 > PATH_MAX) sla@2327: return (0); /* Silently reject "impossibly" long paths */ sla@2327: sla@2327: (void)strcat(strcat(strcat(strcpy(buffer, path), "/"), dir), "/bin/java"); sla@2327: return ((access(buffer, X_OK) == 0) ? 1 : 0); sla@2327: } sla@2327: sla@2327: /* sla@2327: * Determine if there is an acceptable JRE in the directory dirname. sla@2327: * Upon locating the "best" one, return a fully qualified path to sla@2327: * it. "Best" is defined as the most advanced JRE meeting the sla@2327: * constraints contained in the manifest_info. If no JRE in this sla@2327: * directory meets the constraints, return NULL. sla@2327: * sla@2327: * Note that we don't check for errors in reading the directory sla@2327: * (which would be done by checking errno). This is because it sla@2327: * doesn't matter if we get an error reading the directory, or sla@2327: * we just don't find anything interesting in the directory. We sla@2327: * just return NULL in either case. sla@2327: * sla@2327: * The historical names of j2sdk and j2re were changed to jdk and sla@2327: * jre respecively as part of the 1.5 rebranding effort. Since the sla@2327: * former names are legacy on Linux, they must be recognized for sla@2327: * all time. Fortunately, this is a minor cost. sla@2327: */ sla@2327: static char sla@2327: *ProcessDir(manifest_info *info, char *dirname) sla@2327: { sla@2327: DIR *dirp; sla@2327: struct dirent *dp; sla@2327: char *best = NULL; sla@2327: int offset; sla@2327: int best_offset = 0; sla@2327: char *ret_str = NULL; sla@2327: char buffer[PATH_MAX]; sla@2327: sla@2327: if ((dirp = opendir(dirname)) == NULL) sla@2327: return (NULL); sla@2327: sla@2327: do { sla@2327: if ((dp = readdir(dirp)) != NULL) { sla@2327: offset = 0; sla@2327: if ((strncmp(dp->d_name, "jre", 3) == 0) || sla@2327: (strncmp(dp->d_name, "jdk", 3) == 0)) sla@2327: offset = 3; sla@2327: else if (strncmp(dp->d_name, "j2re", 4) == 0) sla@2327: offset = 4; sla@2327: else if (strncmp(dp->d_name, "j2sdk", 5) == 0) sla@2327: offset = 5; sla@2327: if (offset > 0) { sla@2327: if ((JLI_AcceptableRelease(dp->d_name + offset, sla@2327: info->jre_version)) && CheckSanity(dirname, dp->d_name)) sla@2327: if ((best == NULL) || (JLI_ExactVersionId( sla@2327: dp->d_name + offset, best + best_offset) > 0)) { sla@2327: if (best != NULL) sla@2327: JLI_MemFree(best); sla@2327: best = JLI_StringDup(dp->d_name); sla@2327: best_offset = offset; sla@2327: } sla@2327: } sla@2327: } sla@2327: } while (dp != NULL); sla@2327: (void) closedir(dirp); sla@2327: if (best == NULL) sla@2327: return (NULL); sla@2327: else { sla@2327: ret_str = JLI_MemAlloc(strlen(dirname) + strlen(best) + 2); sla@2327: ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best); sla@2327: JLI_MemFree(best); sla@2327: return (ret_str); sla@2327: } sla@2327: } sla@2327: sla@2327: /* sla@2327: * This is the global entry point. It examines the host for the optimal sla@2327: * JRE to be used by scanning a set of directories. The set of directories sla@2327: * is platform dependent and can be overridden by the environment sla@2327: * variable JAVA_VERSION_PATH. sla@2327: * sla@2327: * This routine itself simply determines the set of appropriate sla@2327: * directories before passing control onto ProcessDir(). sla@2327: */ sla@2327: char* sla@2327: LocateJRE(manifest_info* info) sla@2327: { sla@2327: char *path; sla@2327: char *home; sla@2327: char *target = NULL; sla@2327: char *dp; sla@2327: char *cp; sla@2327: sla@2327: /* sla@2327: * Start by getting JAVA_VERSION_PATH sla@2327: */ sla@2327: if (info->jre_restrict_search) sla@2327: path = JLI_StringDup(system_dir); sla@2327: else if ((path = getenv("JAVA_VERSION_PATH")) != NULL) sla@2327: path = JLI_StringDup(path); sla@2327: else sla@2327: if ((home = getenv("HOME")) != NULL) { sla@2327: path = (char *)JLI_MemAlloc(strlen(home) + strlen(system_dir) + sla@2327: strlen(user_dir) + 2); sla@2327: path = strcat(strcat(strcat(strcpy(path, home), sla@2327: user_dir), ":"), system_dir); sla@2327: } else sla@2327: path = JLI_StringDup(system_dir); sla@2327: sla@2327: /* sla@2327: * Step through each directory on the path. Terminate the scan with sla@2327: * the first directory with an acceptable JRE. sla@2327: */ sla@2327: cp = dp = path; sla@2327: while (dp != NULL) { sla@2327: cp = strchr(dp, (int)':'); sla@2327: if (cp != NULL) sla@2327: *cp = (char)NULL; sla@2327: if ((target = ProcessDir(info, dp)) != NULL) sla@2327: break; sla@2327: dp = cp; sla@2327: if (dp != NULL) sla@2327: dp++; sla@2327: } sla@2327: JLI_MemFree(path); sla@2327: return (target); sla@2327: } sla@2327: sla@2327: /* sla@2327: * Given a path to a jre to execute, this routine checks if this process sla@2327: * is indeed that jre. If not, it exec's that jre. sla@2327: * sla@2327: * We want to actually check the paths rather than just the version string sla@2327: * built into the executable, so that given version specification (and sla@2327: * JAVA_VERSION_PATH) will yield the exact same Java environment, regardless sla@2327: * of the version of the arbitrary launcher we start with. sla@2327: */ sla@2327: void sla@2327: ExecJRE(char *jre, char **argv) sla@2327: { sla@2327: char wanted[PATH_MAX]; sla@2327: char *execname; sla@2327: char *progname; sla@2327: sla@2327: /* sla@2327: * Resolve the real path to the directory containing the selected JRE. sla@2327: */ sla@2327: if (realpath(jre, wanted) == NULL) { sla@2327: fprintf(stderr, "Unable to resolve %s\n", jre); sla@2327: exit(1); sla@2327: } sla@2327: sla@2327: /* sla@2327: * Resolve the real path to the currently running launcher. sla@2327: */ sla@2327: execname = SetExecname(argv); sla@2327: if (execname == NULL) { sla@2327: fprintf(stderr, "Unable to resolve current executable\n"); sla@2327: exit(1); sla@2327: } sla@2327: sla@2327: /* sla@2327: * If the path to the selected JRE directory is a match to the initial sla@2327: * portion of the path to the currently executing JRE, we have a winner! sla@2327: * If so, just return. sla@2327: */ sla@2327: if (strncmp(wanted, execname, strlen(wanted)) == 0) sla@2327: return; /* I am the droid you were looking for */ sla@2327: sla@2327: /* sla@2327: * If this isn't the selected version, exec the selected version. sla@2327: */ sla@2327: #ifdef JAVA_ARGS /* javac, jar and friends. */ sla@2327: progname = "java"; sla@2327: #else /* java, oldjava, javaw and friends */ sla@2327: #ifdef PROGNAME sla@2327: progname = PROGNAME; sla@2327: #else sla@2327: progname = *argv; sla@2327: if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { sla@2327: progname = s + 1; sla@2327: } sla@2327: #endif /* PROGNAME */ sla@2327: #endif /* JAVA_ARGS */ sla@2327: sla@2327: /* sla@2327: * This should never happen (because of the selection code in SelectJRE), sla@2327: * but check for "impossibly" long path names just because buffer overruns sla@2327: * can be so deadly. sla@2327: */ sla@2327: if (strlen(wanted) + strlen(progname) + 6 > PATH_MAX) { sla@2327: fprintf(stderr, "Path length exceeds maximum length (PATH_MAX)\n"); sla@2327: exit(1); sla@2327: } sla@2327: sla@2327: /* sla@2327: * Construct the path and exec it. sla@2327: */ sla@2327: (void)strcat(strcat(wanted, "/bin/"), progname); sla@2327: argv[0] = progname; sla@2327: if (_launcher_debug) { sla@2327: int i; sla@2327: printf("ReExec Command: %s (%s)\n", wanted, argv[0]); sla@2327: printf("ReExec Args:"); sla@2327: for (i = 1; argv[i] != NULL; i++) sla@2327: printf(" %s", argv[i]); sla@2327: printf("\n"); sla@2327: } sla@2327: (void)fflush(stdout); sla@2327: (void)fflush(stderr); sla@2327: execv(wanted, argv); sla@2327: perror("execv()"); sla@2327: fprintf(stderr, "Exec of %s failed\n", wanted); sla@2327: exit(1); sla@2327: } sla@2327: #endif /* ifndef GAMMA */ sla@2327: sla@2327: /* sla@2327: * "Borrowed" from Solaris 10 where the unsetenv() function is being added sla@2327: * to libc thanks to SUSv3 (Standard Unix Specification, version 3). As sla@2327: * such, in the fullness of time this will appear in libc on all relevant sla@2327: * Solaris/Linux platforms and maybe even the Windows platform. At that sla@2327: * time, this stub can be removed. sla@2327: * sla@2327: * This implementation removes the environment locking for multithreaded sla@2327: * applications. (We don't have access to these mutexes within libc and sla@2327: * the launcher isn't multithreaded.) Note that what remains is platform sla@2327: * independent, because it only relies on attributes that a POSIX environment sla@2327: * defines. sla@2327: * sla@2327: * Returns 0 on success, -1 on failure. sla@2327: * sla@2327: * Also removed was the setting of errno. The only value of errno set sla@2327: * was EINVAL ("Invalid Argument"). sla@2327: */ sla@2327: sla@2327: /* sla@2327: * s1(environ) is name=value sla@2327: * s2(name) is name(not the form of name=value). sla@2327: * if names match, return value of 1, else return 0 sla@2327: */ sla@2327: static int sla@2327: match_noeq(const char *s1, const char *s2) sla@2327: { sla@2327: while (*s1 == *s2++) { sla@2327: if (*s1++ == '=') sla@2327: return (1); sla@2327: } sla@2327: if (*s1 == '=' && s2[-1] == '\0') sla@2327: return (1); sla@2327: return (0); sla@2327: } sla@2327: sla@2327: /* sla@2327: * added for SUSv3 standard sla@2327: * sla@2327: * Delete entry from environ. sla@2327: * Do not free() memory! Other threads may be using it. sla@2327: * Keep it around forever. sla@2327: */ sla@2327: static int sla@2327: borrowed_unsetenv(const char *name) sla@2327: { sla@2327: long idx; /* index into environ */ sla@2327: sla@2327: if (name == NULL || *name == '\0' || sla@2327: strchr(name, '=') != NULL) { sla@2327: return (-1); sla@2327: } sla@2327: sla@2327: for (idx = 0; environ[idx] != NULL; idx++) { sla@2327: if (match_noeq(environ[idx], name)) sla@2327: break; sla@2327: } sla@2327: if (environ[idx] == NULL) { sla@2327: /* name not found but still a success */ sla@2327: return (0); sla@2327: } sla@2327: /* squeeze up one entry */ sla@2327: do { sla@2327: environ[idx] = environ[idx+1]; sla@2327: } while (environ[++idx] != NULL); sla@2327: sla@2327: return (0); sla@2327: } sla@2327: /* --- End of "borrowed" code --- */ sla@2327: sla@2327: /* sla@2327: * Wrapper for unsetenv() function. sla@2327: */ sla@2327: int sla@2327: UnsetEnv(char *name) sla@2327: { sla@2327: return(borrowed_unsetenv(name)); sla@2327: } sla@2327: sla@2327: /* --- Splash Screen shared library support --- */ sla@2327: sla@2327: static const char* SPLASHSCREEN_SO = "libsplashscreen.so"; sla@2327: sla@2327: static void* hSplashLib = NULL; sla@2327: sla@2327: void* SplashProcAddress(const char* name) { sla@2327: if (!hSplashLib) { sla@2327: hSplashLib = dlopen(SPLASHSCREEN_SO, RTLD_LAZY | RTLD_GLOBAL); sla@2327: } sla@2327: if (hSplashLib) { sla@2327: void* sym = dlsym(hSplashLib, name); sla@2327: return sym; sla@2327: } else { sla@2327: return NULL; sla@2327: } sla@2327: } sla@2327: sla@2327: void SplashFreeLibrary() { sla@2327: if (hSplashLib) { sla@2327: dlclose(hSplashLib); sla@2327: hSplashLib = NULL; sla@2327: } sla@2327: } sla@2327: sla@2327: const char * sla@2327: jlong_format_specifier() { sla@2327: return "%lld"; sla@2327: } sla@2327: sla@2327: /* sla@2327: * Block current thread and continue execution in a new thread sla@2327: */ sla@2327: int sla@2327: ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) { sla@2327: int rslt; sla@2327: #ifdef __linux__ sla@2327: pthread_t tid; sla@2327: pthread_attr_t attr; sla@2327: pthread_attr_init(&attr); sla@2327: pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); sla@2327: sla@2327: if (stack_size > 0) { sla@2327: pthread_attr_setstacksize(&attr, stack_size); sla@2327: } sla@2327: sla@2327: if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) { sla@2327: void * tmp; sla@2327: pthread_join(tid, &tmp); sla@2369: rslt = (int)(intptr_t)tmp; sla@2327: } else { sla@2327: /* sla@2327: * Continue execution in current thread if for some reason (e.g. out of sla@2327: * memory/LWP) a new thread can't be created. This will likely fail sla@2327: * later in continuation as JNI_CreateJavaVM needs to create quite a sla@2327: * few new threads, anyway, just give it a try.. sla@2327: */ sla@2327: rslt = continuation(args); sla@2327: } sla@2327: sla@2327: pthread_attr_destroy(&attr); sla@2327: #else sla@2327: thread_t tid; sla@2327: long flags = 0; sla@2327: if (thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) == 0) { sla@2327: void * tmp; sla@2327: thr_join(tid, NULL, &tmp); sla@2369: rslt = (int)(intptr_t)tmp; sla@2327: } else { sla@2327: /* See above. Continue in current thread if thr_create() failed */ sla@2327: rslt = continuation(args); sla@2327: } sla@2327: #endif sla@2327: return rslt; sla@2327: } sla@2327: sla@2327: /* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */ sla@2327: #define MAX_PID_STR_SZ 20 sla@2327: sla@2327: void SetJavaLauncherPlatformProps() { sla@2327: /* Linux only */ sla@2327: #ifdef __linux__ sla@2327: const char *substr = "-Dsun.java.launcher.pid="; sla@2327: char *pid_prop_str = (char *)JLI_MemAlloc(strlen(substr) + MAX_PID_STR_SZ + 1); sla@2327: sprintf(pid_prop_str, "%s%d", substr, getpid()); sla@2327: AddOption(pid_prop_str, NULL); sla@2327: #endif sla@2327: }