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