/*
 * @(#)jre_md.c	1.4 97/05/13 David Connelly
 *
 * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
 * modify and redistribute this software in source and binary code form,
 * provided that i) this copyright notice and license appear on all copies of
 * the software; and ii) Licensee does not utilize the software in a manner
 * which is disparaging to Sun.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * This software is not designed or intended for use in on-line control of
 * aircraft, air traffic, aircraft navigation or aircraft communications; or in
 * the design, construction, operation or maintenance of any nuclear
 * facility. Licensee represents and warrants that it will not use or
 * redistribute the Software for such purposes.
 */

/*
 * Solaris specific JRE support functions
 */

#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <dlfcn.h>
#include <jni.h>
#include "jre.h"

/* Default threads type */
#ifndef THREADS_TYPE
#define THREADS_TYPE "native_threads"
#endif

/* Default Java runtime library */
#ifndef JAVA_RUNTIME
#ifdef DEBUG
#define JAVA_RUNTIME "libjava_g.so"
#else
#define JAVA_RUNTIME "libjava.so"
#endif
#endif

/* Machine type */
#if defined(sparc)
#define ARCH "sparc"
#elif defined(i386)
#define ARCH "i386"
#endif

/* Forward declarations */
char *GetDefaultJavaHome();
void SetLibraryPath(const char *dir);

/*
 * Retrieve settings for current runtime version. Returns 0 if successful
 * otherwise returns -1 if no installed runtime could be found.
 */
jint
JRE_GetCurrentSettings(JRESettings *set)
{
    return -1;
}
/*
 * Retrieves settings for specified runtime version. Returns 0 if successful
 * otherwise returns -1 if no corresponding runtime version could be found.
 */
jint
JRE_GetSettings(JRESettings *set, const char *version)
{
    return -1;
}

/*
 * Returns default runtime settings based on location of this executable
 * program. Makes best attempt at determining location of runtime. Returns
 * 0 if successful or -1 if a runtime could not be found.
 */
jint
JRE_GetDefaultSettings(JRESettings *set)
{
    char buf[PATH_MAX];
    char *s;

    set->javaHome = getenv("JAVA_HOME");
    if (set->javaHome == 0) {
	set->javaHome = GetDefaultJavaHome();
	if (set->javaHome == 0) {
	    return -1;
	}
    }
    set->runtimeLib = JRE_GetDefaultRuntimeLib(set->javaHome);
    set->classPath = getenv("CLASSPATH");
    if (set->classPath == 0) {
	set->classPath = JRE_GetDefaultClassPath(set->javaHome);
    }
    set->compiler = getenv("JAVA_COMPILER");

    /* Reset other fields since these are not known */
    set->majorVersion = 0;
    set->minorVersion = 0;
    set->microVersion = 0;

    return 0;
}

/*
 * Returns default Java home based on location of this executable.
 */
char *
GetDefaultJavaHome()
{
    Dl_info dli;
    char *path = 0;

    if (dladdr((void *)GetDefaultJavaHome, &dli) != 0) {
	if (dli.dli_fname[0] != '/') {
	    char buf[PATH_MAX];
	    if (getcwd(buf, sizeof(buf)) != 0) {
		path = JRE_Malloc(sizeof(buf) + sizeof(dli.dli_fname) + 8);
		sprintf(path, "%s/%s/../..", buf, dli.dli_fname);
	    }
	}
    }
    return path;
}

/*
 * Sets LD_LIBRARY_PATH to include the specified directory.
 */
void
SetLibraryPath(const char *dir)
{
    char *s = getenv("LD_LIBRARY_PATH"), *buf;

    /* Set library path */
    if (s == 0) {
	buf = JRE_Malloc(strlen(dir) + strlen(s) + 32);
	sprintf(buf, "LD_LIBRARY_PATH=%s:%s", dir, s);
    } else {
	buf = JRE_Malloc(strlen(dir) + 32);
	sprintf(buf, "LD_LIBRARY_PATH=%s", dir);
    }
    if (putenv(buf) != 0) {
	perror("putenv");
	exit(1);
    }
}

/*
 * Return default runtime library for specified Java home directory.
 */
char *
JRE_GetDefaultRuntimeLib(const char *dir)
{
    char buf[PATH_MAX+1], *s;

    if ((s = getenv("THREADS_TYPE")) == 0) {
	s = THREADS_TYPE;
    }
    sprintf(buf, "%s/lib/" ARCH "/%s", dir, s);
    SetLibraryPath(buf);
    return strdup(strcat(buf, "/" JAVA_RUNTIME));
}

/*
 * Return default class path for specified Java home directory.
 */
char *
JRE_GetDefaultClassPath(const char *dir)
{
    char *cp = JRE_Malloc(strlen(dir) * 2 + 32);
    sprintf(cp, "%s/lib/rt.jar;%s/lib/i18n.jar", dir, dir);
    return cp;
}

/*
 * Loads the runtime library corresponding to 'libname' and returns
 * an opaque handle to the library.
 */
void *
JRE_LoadLibrary(const char *path)
{
    return dlopen(path, RTLD_LAZY);
}

/*
 * Unloads the runtime library associated with handle.
 */
void
JRE_UnloadLibrary(void *handle)
{
    dlclose(handle);
}

/*
 * Loads default VM args for the specified runtime library handle.
 */
jint
JRE_GetDefaultJavaVMInitArgs(void *handle, void *vmargs)
{
    jint (*proc)();
    proc = (jint (*)())dlsym(handle, "JNI_GetDefaultJavaVMInitArgs");
    return proc != 0 ? ((*proc)(vmargs), 0) : -1;
}

/*
 * Creates a Java VM for the specified runtime library handle.
 */
jint
JRE_CreateJavaVM(void *handle, JavaVM **vmp, JNIEnv **envp, void *vmargs)
{
    jint (*proc)();
    proc = (jint (*)())dlsym(handle, "JNI_CreateJavaVM");
    return proc != 0 ? (*proc)(vmp, envp, vmargs) : -1;
}
