/* This function gets called very early, before VM_CALLS are setup.
 * Do not use any of the VM_CALLS entries!!!
 */
java_props_t *
GetJavaProperties(JNIEnv *env)
{
    static java_props_t sprops = {0};
    char *v; /* tmp var */

    if (sprops.user_dir) {
        return &sprops;
    }

    /* tmp dir */
    sprops.tmp_dir = P_tmpdir;

    /* Printing properties */
    sprops.printerJob = "sun.print.PSPrinterJob";

    /* Preferences properties */
    sprops.util_prefs_PreferencesFactory = 
                                "java.util.prefs.FileSystemPreferencesFactory";

    /* patches/service packs installed */
    sprops.patch_level = "unknown";
    
    /* Java 2D properties */
    sprops.graphics_env = "sun.awt.X11GraphicsEnvironment";
    sprops.awt_toolkit = NULL;

    v = getenv("JAVA_FONTS");
    /*
    sprops.font_dir = v ? v :
    "/usr/openwin/lib/X11/fonts/Type1:/usr/openwin/lib/X11/fonts/TrueType";
    */

    /* If JAVA_FONTS is not set, the system-dependent fontpath will
     * be lazy evaluated later
     */
    sprops.font_dir = v ? v : "";

#ifdef SI_ISALIST
    /* supported instruction sets */
    {
        char list[258];
        sysinfo(SI_ISALIST, list, sizeof(list));
        sprops.cpu_isalist = strdup(list);
    }
#else
    sprops.cpu_isalist = NULL;
#endif

    /* endianness of platform */
    {
        unsigned int endianTest = 0xff000000;
        if (((char*)(&endianTest))[0] != 0)
            sprops.cpu_endian = "big";
        else
            sprops.cpu_endian = "little";
    }

    /* os properties */
    {
        struct utsname name;
	char arch[12];
	uname(&name);
	sprops.os_name = strdup(name.sysname);
	sprops.os_version = strdup(name.release);

#ifdef ARCH
        sprops.os_arch = ARCH;
#else
	sysinfo(SI_ARCHITECTURE, arch, sizeof(arch));
	if (strcmp(arch,"sparc") == 0 ) {
#ifdef _LP64
	    sprops.os_arch = "sparcv9";
#else
	    sprops.os_arch = "sparc";
#endif
	} else if (strcmp(arch,"i386") == 0 ) {
	    /* use x86 to match the value received on win32 */
	    sprops.os_arch = "x86";
	} else if (strcmp(arch,"ppc") == 0 ) {
	    sprops.os_arch = "ppc";
#ifdef __linux__
       } else if (strcmp(arch,"m68k") == 0 ) {
           sprops.os_arch = "m68k";
#endif
	} else {
            sprops.os_arch = "Unknown";
	}
#endif
    }

    /* Determine the language, country, variant, and encoding from the host,
     * and store these in the user.language, user.country, user.variant and
     * file.encoding system properties. */
    {
        char *lc;
        lc = setlocale(LC_CTYPE, "");
#ifndef __linux__
        if (lc == NULL) {
            /*
             * 'lc == null' means system doesn't support user's environment
             * variable's locale.
             */
          setlocale(LC_ALL, "C");
          sprops.language = "en";
          sprops.encoding = "ISO8859-1";
        } else {
#else
        if (lc == NULL || !strcmp(lc, "C") || !strcmp(lc, "POSIX")) {
            lc = "en_US";
        }
        {
#endif

            /*
             * locale string format in Solaris is
             * <language name>_<country name>.<encoding name>@<variant name>
             * <country name>, <encoding name>, and <variant name> are optional.
             */
            char temp[64];
            char *language = NULL, *country = NULL, *variant = NULL,
                 *encoding = NULL;
            char *std_language = NULL, *std_country = NULL, *std_variant = NULL,
                 *std_encoding = NULL;
            char *p, encoding_variant[64];
            int i, found;

#ifndef __linux__
            /*
             * Workaround for Solaris bug 4201684: Xlib doesn't like @euro
             * locales. Since we don't depend on the libc @euro behavior,
             * we just remove the qualifier.
             * On Linux, the bug doesn't occur; on the other hand, @euro
             * is needed there because it's a shortcut that also determines
             * the encoding - without it, we wouldn't get ISO-8859-15.
             * Therefore, this code section is Solaris-specific.
             */
	    lc = strdup(lc);	/* keep a copy, setlocale trashes original. */
            strcpy(temp, lc);
	    p = strstr(temp, "@euro");
	    if (p != NULL) 
		*p = '\0';
            setlocale(LC_ALL, temp);
#endif

            strcpy(temp, lc);

            /* Parse the language, country, encoding, and variant from the
             * locale.  Any of the elements may be missing, but they must occur
             * in the order language_country.encoding@variant, and must be
             * preceded by their delimiter (except for language).
             *
             * If the locale name (without .encoding@variant, if any) matches
             * any of the names in the locale_aliases list, map it to the
             * corresponding full locale name.  Most of the entries in the
             * locale_aliases list are locales that include a language name but
             * no country name, and this facility is used to map each language
             * to a default country if that's possible.  It's also used to map
             * the Solaris locale aliases to their proper Java locale IDs.
             */
            if ((p = strchr(temp, '.')) != NULL) {
                strcpy(encoding_variant, p); /* Copy the leading '.' */
                *p = '\0';
            } else if ((p = strchr(temp, '@')) != NULL) {
                 strcpy(encoding_variant, p); /* Copy the leading '@' */
                 *p = '\0';
            } else {
                *encoding_variant = '\0';
            }
            
            if (mapLookup(locale_aliases, temp, &p)) {
                strcpy(temp, p);
            }
            
            language = temp;
            if ((country = strchr(temp, '_')) != NULL) {
                *country++ = '\0';
            }
            
            p = encoding_variant;
            if ((encoding = strchr(p, '.')) != NULL) {
                p[encoding++ - p] = '\0';
                p = encoding;
            }
            if ((variant = strchr(p, '@')) != NULL) {
                p[variant++ - p] = '\0';
            }

            /* Normalize the language name */
            std_language = "en";
            if (language != NULL) {
                mapLookup(language_names, language, &std_language);
            }
            sprops.language = std_language;

            /* Normalize the country name */
            if (country != NULL) {
                std_country = country;
                mapLookup(country_names, country, &std_country);
                sprops.country = strdup(std_country);
            }

            /* Normalize the variant name.  Note that we only use
             * variants listed in the mapping array; others are ignored. */
            if (variant != NULL) {
                mapLookup(variant_names, variant, &std_variant);
                sprops.variant = std_variant;
            }

            /* Normalize the encoding name.  Note that we IGNORE the string
             * 'encoding' extracted from the locale name above.  Instead, we use the
             * more reliable method of calling nl_langinfo(CODESET).  This function
             * returns an empty string if no encoding is set for the given locale
             * (e.g., the C or POSIX locales); we use the default ISO 8859-1
             * converter for such locales.
	     */

	    /* OK, not so reliable - nl_langinfo() gives wrong answers on
	     * Euro locales, in particular. */
	    if (strcmp(p, "ISO8859-15") == 0)
		p = "ISO8859-15";
	    else		
                p = nl_langinfo(CODESET);

	    /* Convert the bare "646" used on Solaris to a proper IANA name */
	    if (strcmp(p, "646") == 0)
		p = "ISO646-US";

	    /* return same result nl_langinfo would return for en_UK,
	     * in order to use optimizations. */
            std_encoding = (*p != '\0') ? p : "ISO8859-1";


#ifdef __linux__
	    /* 
	     * Remap the encoding string to a different value for japanese
	     * locales on linux so that customized converters are used instead
	     * of the default converter for "EUC-JP". The customized converters
	     * omit support for the JIS0212 encoding which is not supported by
	     * the variant of "EUC-JP" encoding used on linux
	     */
	    if (strcmp(p, "EUC-JP") == 0) {
		std_encoding = "EUC-JP-LINUX";
	    }
#else
            /* For Solaris use customized vendor defined character 
             * customized EUC-JP converter
             */
            if (strcmp(p,"eucJP") == 0) {
                std_encoding = "eucJP-open"; 
            }
#endif
#ifndef __linux__
	    /* 
	     * Remap the encoding string to Big5_Solaris which augments
	     * the default converter for Solaris Big5 locales to include
	     * seven additional ideographic characters beyond those included
	     * in the Java "Big5" converter.
	     */
	    if (strcmp(p, "Big5") == 0) {
		    std_encoding = "Big5_Solaris";
	    }
#endif
	    sprops.encoding = std_encoding;
        }
    }
    
#ifdef __linux__ 
#if __BYTE_ORDER == __LITTLE_ENDIAN
    sprops.unicode_encoding = "UnicodeLittle";
#else
    sprops.unicode_encoding = "UnicodeBig";
#endif
#else
    sprops.unicode_encoding = "UnicodeBig";
#endif

    /* user properties */
    {
        struct passwd *pwent = getpwuid(getuid());
	sprops.user_name = pwent ? strdup(pwent->pw_name) : "?";
	sprops.user_home = pwent ? strdup(pwent->pw_dir) : "?";
    }

    /* User TIMEZONE */
    {
	/*
	 * We defer setting up timezone until it's actually necessary.
	 * Refer to TimeZone.getDefault(). However, the system
	 * property is necessary to be able to be set by the command
	 * line interface -D. Here temporarily set a null string to
	 * timezone.
	 */
	tzset();	/* for compatibility */
	sprops.timezone = "";
    }

    /* Current directory */
    {
        char buf[MAXPATHLEN];
        errno = 0;
        if (getcwd(buf, sizeof(buf))  == NULL)
            JNU_ThrowByName(env, "java/lang/Error", 
             "Properties init: Could not determine current working directory.");
        else
            sprops.user_dir = strdup(buf);
    }

    sprops.file_separator = "/";
    sprops.path_separator = ":";
    sprops.line_separator = "\n";
    
    /* Append CDE message and resource search path to NLSPATH and
     * XFILESEARCHPATH, in order to pick localized message for 
     * FileSelectionDialog window (Bug 4173641).
     */
    setPathEnvironment("NLSPATH=/usr/dt/lib/nls/msg/%L/%N.cat");
    setPathEnvironment("XFILESEARCHPATH=/usr/dt/app-defaults/%L/Dt");

    return &sprops;
}
static int ParseLocale(int cat, char ** std_language, char ** std_script,
                       char ** std_country, char ** std_variant, char ** std_encoding) {
    char temp[64];
    char *language = NULL, *country = NULL, *variant = NULL,
         *encoding = NULL;
    char *p, encoding_variant[64];
    char *lc;

    /* Query the locale set for the category */

#ifdef MACOSX
    lc = setupMacOSXLocale(cat); // malloc'd memory, need to free
#else
    lc = setlocale(cat, NULL);
#endif

#ifndef __linux__
    if (lc == NULL) {
        return 0;
    }

    if (cat == LC_CTYPE) {
        /*
         * Workaround for Solaris bug 4201684: Xlib doesn't like @euro
         * locales. Since we don't depend on the libc @euro behavior,
         * we just remove the qualifier.
         * On Linux, the bug doesn't occur; on the other hand, @euro
         * is needed there because it's a shortcut that also determines
         * the encoding - without it, we wouldn't get ISO-8859-15.
         * Therefore, this code section is Solaris-specific.
         */
        lc = strdup(lc);    /* keep a copy, setlocale trashes original. */
        strcpy(temp, lc);
        p = strstr(temp, "@euro");
        if (p != NULL) {
            *p = '\0';
            setlocale(LC_ALL, temp);
        }
    }
#else
    if (lc == NULL || !strcmp(lc, "C") || !strcmp(lc, "POSIX")) {
        lc = "en_US";
    }
#endif

    /*
     * locale string format in Solaris is
     * <language name>_<country name>.<encoding name>@<variant name>
     * <country name>, <encoding name>, and <variant name> are optional.
     */

    strcpy(temp, lc);
#ifdef MACOSX
    free(lc); // malloced memory
#endif
    /* Parse the language, country, encoding, and variant from the
     * locale.  Any of the elements may be missing, but they must occur
     * in the order language_country.encoding@variant, and must be
     * preceded by their delimiter (except for language).
     *
     * If the locale name (without .encoding@variant, if any) matches
     * any of the names in the locale_aliases list, map it to the
     * corresponding full locale name.  Most of the entries in the
     * locale_aliases list are locales that include a language name but
     * no country name, and this facility is used to map each language
     * to a default country if that's possible.  It's also used to map
     * the Solaris locale aliases to their proper Java locale IDs.
     */
    if ((p = strchr(temp, '.')) != NULL) {
        strcpy(encoding_variant, p); /* Copy the leading '.' */
        *p = '\0';
    } else if ((p = strchr(temp, '@')) != NULL) {
        strcpy(encoding_variant, p); /* Copy the leading '@' */
        *p = '\0';
    } else {
        *encoding_variant = '\0';
    }

    if (mapLookup(locale_aliases, temp, &p)) {
        strcpy(temp, p);
        // check the "encoding_variant" again, if any.
        if ((p = strchr(temp, '.')) != NULL) {
            strcpy(encoding_variant, p); /* Copy the leading '.' */
            *p = '\0';
        } else if ((p = strchr(temp, '@')) != NULL) {
            strcpy(encoding_variant, p); /* Copy the leading '@' */
            *p = '\0';
        }
    }

    language = temp;
    if ((country = strchr(temp, '_')) != NULL) {
        *country++ = '\0';
    }

    p = encoding_variant;
    if ((encoding = strchr(p, '.')) != NULL) {
        p[encoding++ - p] = '\0';
        p = encoding;
    }
    if ((variant = strchr(p, '@')) != NULL) {
        p[variant++ - p] = '\0';
    }

    /* Normalize the language name */
    if (std_language != NULL) {
        *std_language = "en";
        if (language != NULL && mapLookup(language_names, language, std_language) == 0) {
            *std_language = malloc(strlen(language)+1);
            strcpy(*std_language, language);
        }
    }

    /* Normalize the country name */
    if (std_country != NULL && country != NULL) {
        if (mapLookup(country_names, country, std_country) == 0) {
            *std_country = malloc(strlen(country)+1);
            strcpy(*std_country, country);
        }
    }

    /* Normalize the script and variant name.  Note that we only use
     * variants listed in the mapping array; others are ignored.
     */
    if (variant != NULL) {
        if (std_script != NULL) {
            mapLookup(script_names, variant, std_script);
        }

        if (std_variant != NULL) {
            mapLookup(variant_names, variant, std_variant);
        }
    }

    /* Normalize the encoding name.  Note that we IGNORE the string
     * 'encoding' extracted from the locale name above.  Instead, we use the
     * more reliable method of calling nl_langinfo(CODESET).  This function
     * returns an empty string if no encoding is set for the given locale
     * (e.g., the C or POSIX locales); we use the default ISO 8859-1
     * converter for such locales.
     */
    if (std_encoding != NULL) {
        /* OK, not so reliable - nl_langinfo() gives wrong answers on
         * Euro locales, in particular. */
        if (strcmp(p, "ISO8859-15") == 0)
            p = "ISO8859-15";
        else
            p = nl_langinfo(CODESET);

        /* Convert the bare "646" used on Solaris to a proper IANA name */
        if (strcmp(p, "646") == 0)
            p = "ISO646-US";

        /* return same result nl_langinfo would return for en_UK,
         * in order to use optimizations. */
        *std_encoding = (*p != '\0') ? p : "ISO8859-1";

#ifdef __linux__
        /*
         * Remap the encoding string to a different value for japanese
         * locales on linux so that customized converters are used instead
         * of the default converter for "EUC-JP". The customized converters
         * omit support for the JIS0212 encoding which is not supported by
         * the variant of "EUC-JP" encoding used on linux
         */
        if (strcmp(p, "EUC-JP") == 0) {
            *std_encoding = "EUC-JP-LINUX";
        }
#else
        if (strcmp(p,"eucJP") == 0) {
            /* For Solaris use customized vendor defined character
             * customized EUC-JP converter
             */
            *std_encoding = "eucJP-open";
        } else if (strcmp(p, "Big5") == 0 || strcmp(p, "BIG5") == 0) {
            /*
             * Remap the encoding string to Big5_Solaris which augments
             * the default converter for Solaris Big5 locales to include
             * seven additional ideographic characters beyond those included
             * in the Java "Big5" converter.
             */
            *std_encoding = "Big5_Solaris";
        } else if (strcmp(p, "Big5-HKSCS") == 0) {
            /*
             * Solaris uses HKSCS2001
             */
            *std_encoding = "Big5-HKSCS-2001";
        }
#endif
#ifdef MACOSX
        /*
         * For the case on MacOS X where encoding is set to US-ASCII, but we
         * don't have any encoding hints from LANG/LC_ALL/LC_CTYPE, use UTF-8
         * instead.
         *
         * The contents of ASCII files will still be read and displayed
         * correctly, but so will files containing UTF-8 characters beyond the
         * standard ASCII range.
         *
         * Specifically, this allows apps launched by double-clicking a .jar
         * file to correctly read UTF-8 files using the default encoding (see
         * 8011194).
         */
        if (strcmp(p,"US-ASCII") == 0 && getenv("LANG") == NULL &&
            getenv("LC_ALL") == NULL && getenv("LC_CTYPE") == NULL) {
            *std_encoding = "UTF-8";
        }
#endif
    }

    return 1;
}
CVMBool
CVMgetJavaProperties(java_props_t *sprops)
{
    const char *v; /* tmp var */

    if (sprops->user_dir) {
        return CVM_TRUE;
    }

    /* tmp dir */
    sprops->tmp_dir = P_tmpdir;

#ifndef JAVASE
    /* Printing properties */
    sprops->printerJob = NULL;

    /* Java 2D properties */
    sprops->graphics_env = NULL;
#else
    /* Printing properties */
    sprops->printerJob = "sun.print.PSPrinterJob";

    /* Preferences properties */
    sprops->util_prefs_PreferencesFactory =
                                "java.util.prefs.FileSystemPreferencesFactory";

    /* patches/service packs installed */
    sprops->patch_level = "unknown";

    sprops->graphics_env = "sun.awt.X11GraphicsEnvironment";
#endif

    sprops->awt_toolkit = NULL;

    v = getenv("JAVA_FONTS");
    /*
    sprops->font_dir = v ? v :
    "/usr/openwin/lib/X11/fonts/Type1:/usr/openwin/lib/X11/fonts/TrueType";
    */

    /* If JAVA_FONTS is not set, the system-dependent fontpath will
     * be evaluated later
     */
    sprops->font_dir = v ? v : "";

#ifdef SI_ISALIST
    /* supported instruction sets */
    {
        char list[258];
        sysinfo(SI_ISALIST, list, sizeof(list));
        sprops->cpu_isalist = strdup(list);
	if (sprops->cpu_isalist == NULL) {
	    goto out_of_memory;
	}
    }
#else
    sprops->cpu_isalist = NULL;
#endif

    /* endianness of platform */
    {
        unsigned int endianTest = 0xff000000;
        if (((char*)(&endianTest))[0] != 0)
            sprops->cpu_endian = "big";
        else
            sprops->cpu_endian = "little";
    }

    /* os properties */
    {
        struct utsname name;
	uname(&name);
	sprops->os_name = strdup(name.sysname);
	sprops->os_version = strdup(name.release);
	if (sprops->os_name == NULL || sprops->os_version == NULL) {
	    goto out_of_memory;
	}

#ifdef ARCH
        sprops->os_arch = ARCH;
#else
	{
	    char* arch = name.machine;
	    if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6' &&
		(arch[1] >= '3' && arch[1] <= '6')) {
		/* use x86 to match the value received on win32 */
		sprops->os_arch = strdup("x86");
	    } else if (strncmp(arch, "sparc", 5) == 0) {
		sprops->os_arch = strdup("sparc");
	    } else {
		sprops->os_arch = strdup(arch);
	    }
	    if (sprops->os_arch == NULL) {
		goto out_of_memory;
	    }
	}
#endif
    }

    /* Determing the language, country, and encoding from the host,
     * and store these in the user.language, user.region, and
     * file.encoding system properties. */
    {
        char *lc;
        lc = setlocale(LC_CTYPE, "");
        if (lc == NULL || !strcmp(lc, "C") || !strcmp(lc, "POSIX")) {
            lc = "en_US";
        }
        {
            /*
             * locale string format in Solaris is
             * <language name>_<region name>.<encoding name>
             * <region name> and <encoding name> are optional.
             */
            char temp[64], *language = NULL, *region = NULL, *encoding = NULL;
            char *std_language = NULL, *std_region = NULL,
                 *std_encoding = NULL;
            char region_variant[64], *variant = NULL, *std_variant = NULL;
            char *p, encoding_variant[64];

	    /*
	     * Bug 4201684: Xlib doesn't like @euro locales.  Since we don't
	     * depend on the libc @euro behavior, drop it.
	     */
	    lc = strdup(lc);	/* keep a copy, setlocale trashes original. */
	    if (lc == NULL) {
		goto out_of_memory;
	    }
            strcpy(temp, lc);
	    p = strstr(temp, "@euro");
	    if (p != NULL) 
		*p = '\0';
            setlocale(LC_ALL, temp);

            strcpy(temp, lc);

            /* Release lc now that we don't need it anymore: */
            free(lc);
            lc = NULL;

            /* Parse the language, region, encoding, and variant from the
             * locale.  Any of the elements may be missing, but they must occur
             * in the order language_region.encoding@variant, and must be
             * preceded by their delimiter (except for language).
             *
             * If the locale name (without .encoding@variant, if any) matches
             * any of the names in the locale_aliases list, map it to the
             * corresponding full locale name.  Most of the entries in the
             * locale_aliases list are locales that include a language name but
             * no country name, and this facility is used to map each language
             * to a default country if that's possible.  It's also used to map
             * the Solaris locale aliases to their proper Java locale IDs.
             */
            if ((p = strchr(temp, '.')) != NULL) {
                strcpy(encoding_variant, p); /* Copy the leading '.' */
                *p = '\0';
            } else if ((p = strchr(temp, '@')) != NULL) {
                 strcpy(encoding_variant, p); /* Copy the leading '@' */
                 *p = '\0';
            } else {
                *encoding_variant = '\0';
            }
            
            if (mapLookup(locale_aliases, temp, &p)) {
                strcpy(temp, p);
            }
            
            language = temp;
            if ((region = strchr(temp, '_')) != NULL) {
                *region++ = '\0';
            }
            
            p = encoding_variant;
            if ((encoding = strchr(p, '.')) != NULL) {
                p[encoding++ - p] = '\0';
                p = encoding;
            }
            if ((variant = strchr(p, '@')) != NULL) {
                p[variant++ - p] = '\0';
            }

            /* Normalize the language name */
            std_language = "en";
            if (language != NULL) {
                mapLookup(language_names, language, &std_language);
            }
            sprops->language = std_language;

            /* Normalize the variant name.  Do this BEFORE handling the region
             * name, since the variant name will be incorporated into the
             * user.region property.
             */
            if (variant != NULL) {
                mapLookup(variant_names, variant, &std_variant);
            }

            /* Normalize the region name.  If there is a std_variant, then
             * append it to the region.  This applies even if there is no
             * region, in which case the empty string is used for the region.
             * Note that we only use variants listed in the mapping array;
	     * others are ignored.
             */
            *region_variant = '\0';
            if (region != NULL) {
                std_region = region;
                mapLookup(region_names, region, &std_region);
                strcpy(region_variant, std_region);
            }
            if (std_variant != NULL) {
               strcat(region_variant, "_");
               strcat(region_variant, std_variant);
            }
            if ((*region_variant) != '\0') {
               sprops->region = strdup(region_variant);
	       if (sprops->region == NULL) {
		   goto out_of_memory;
	       }
            }

            /* Normalize the encoding name.  Note that we IGNORE the string
             * 'encoding' extracted from the locale name above.  Instead, we 
             * use the more reliable method of calling nl_langinfo(CODESET).  
             * This function returns an empty string if no encoding is set for
             * the given locale (e.g., the C or POSIX locales); we use the
             * default ISO 8859-1 converter for such locales.  We don't need 
             * to map from the Solaris string to the Java identifier at this 
             * point because that mapping is handled by the character
             * converter alias table in CharacterEncoding.java.
             */
            p = nl_langinfo(CODESET);
	    /* SVMC d022301 17.02.2003
	     * it seems that nl_langinfo() does not return standardized
	     * strings. 'locale charmap' return on
	     * linux: ISO-8859-1
	     * hp-ux: iso88591
	     * AIX:   ISO8859-1
	     * So add "iso88591" as a valid string for the iso 8859-1
	     * encoding.
	     * (this is required to pass jck test 
	     * javasoft.sqe.tests.api.java.lang.String.serial.ConstructorTests)
	     */
	    if (strcmp(p, "ANSI_X3.4-1968") == 0 || *p == '\0' ||
		strcmp(p, "ASCII") == 0 ||
		strcmp(p, "ISO-8859-1") == 0 || strcmp(p, "iso88591") == 0 ) {
		std_encoding = "ISO8859_1";
	    } else {
		std_encoding = p;
	    }
            /*  
             * Remap the encoding string to a different value for japanese
             * locales on linux so that customized converters are used instead
             * of the default converter for "EUC-JP". The customized converters
             * omit support for the JIS0212 encoding which is not supported by
             * the variant of "EUC-JP" encoding used on linux
             */
            if (strcmp(p, "EUC-JP") == 0) {
                std_encoding = "EUC-JP-LINUX";
            }
            sprops->encoding = std_encoding;
#ifdef JAVASE 
            sprops->sun_jnu_encoding = sprops->encoding;
#endif

        }
    }
    
#if (CVM_ENDIANNESS == CVM_LITTLE_ENDIAN)
   sprops->unicode_encoding = "UnicodeLittle";
#else
   sprops->unicode_encoding = "UnicodeBig";
#endif

    /* user properties */
    {
        struct passwd *pwent;
	/* Don't call getpwuid if both -Duser.home and -Duser.name were
	 * specified on the command line.  This is mostly done because
	 * getpwuid crashes if it runs out of memory, so we need a way
	 * to allow electric fence to run without causing a crash here. */
	if (CVMglobals.userHomePropSpecified &&
	    CVMglobals.userNamePropSpecified)
	{
	    pwent = NULL;
	} else {
	    pwent = getpwuid(getuid());
	}
	sprops->user_name = strdup(pwent ? pwent->pw_name : "?");
	sprops->user_home = strdup(pwent ? pwent->pw_dir : "?");
	if (sprops->user_name == NULL || sprops->user_home == NULL) {
	    goto out_of_memory;
	}
    }

    /* User TIMEZONE */
    {
	/*
	 * We defer setting up timezone until it's actually necessary.
	 * Refer to TimeZone.getDefault(). However, the system
	 * property is necessary to be able to be set by the command
	 * line interface -D. Here temporarily set a null string to
	 * timezone.
	 */
	tzset();	/* for compatibility */
	sprops->timezone = "";
    }

    /* Current directory */
    {
        char buf[MAXPATHLEN];
	/*
	 * getcwd can fail because of 
	 * EACCES, EFAULT, EINVAL, ENOENT, ERANGE
	 * so check return code to be save
	 */
        if (getcwd(buf, sizeof(buf)) != NULL) {
	    sprops->user_dir = strdup(buf);
	    if (sprops->user_dir == NULL ) {
	        goto out_of_memory;
	    }
        }
    }

    sprops->file_separator = "/";
    sprops->path_separator = ":";
    sprops->line_separator = "\n";

    /* Generic Connection Framework (GCF): CommConnection Property */
    /* NOTE: comma-delimited (no spaces) list of available comm (serial)
       ports */
    sprops->commports = "/dev/ttyS0";

    return CVM_TRUE;

 out_of_memory:
    CVMreleaseJavaProperties(sprops);
    return CVM_FALSE;
}
CVMBool
CVMgetJavaProperties(java_props_t *sprops)
{
    const char *v; /* tmp var */

    if (sprops->user_dir) {
        return CVM_TRUE;
    }

    /* tmp dir */
    {
      DWORD err;
      char consdir[MAX_PATH];        
        TCHAR tmpdir[MAX_PATH];
        if (GetTempPath(MAX_PATH, tmpdir) <= 0) {         
          char msg[1024];
          jio_snprintf(msg, 1024,
                       "GetTempPath: error=%d", GetLastError());
          return CVM_FALSE;
        }
        // convert wide character to sequence of multibyte characters. 
        copyToMCHAR(consdir, tmpdir, MAX_PATH);
        sprops->tmp_dir = strdup(consdir);
    }

    /* Printing properties */
    sprops->printerJob = "sun.awt.motif.PSPrinterJob";

    /* Java 2D properties */
    sprops->graphics_env = NULL;
    sprops->awt_toolkit = NULL;

    v = getenv("JAVA_FONTS");

    /* If JAVA_FONTS is not set, the system-dependent fontpath will
     * be evaluated later
     */
    sprops->font_dir = v ? v : "";


    sprops->cpu_isalist = NULL;

    /* endianness of platform */
    {
        unsigned int endianTest = 0xff000000;
        if (((char*)(&endianTest))[0] != 0)
            sprops->cpu_endian = "big";
        else
            sprops->cpu_endian = "little";
    }

    /* os properties */
    {
        OSVERSIONINFO si;

	si.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 
	if (GetVersionEx(&si) == 0) {
		printf("GetVersion Error \n");
	}

	switch (si.dwPlatformId) {
	case VER_PLATFORM_WIN32s:
		sprops->os_name = strdup("Windows 3.1");
		sprops->os_version = strdup("Unknown");
		break;
	case VER_PLATFORM_WIN32_WINDOWS:
		if (si.dwMinorVersion == 0)
		    sprops->os_name = strdup("Windows 95");
		else
		    sprops->os_name = strdup("Windows 98");
		sprops->os_version = strdup((char*)si.szCSDVersion);
		break;
	case VER_PLATFORM_WIN32_NT:
          if (si.dwMajorVersion <= 4) {
	        sprops->os_name = strdup("Windows NT");
          } else if (si.dwMajorVersion == 5) {
	        switch (si.dwMinorVersion) {
		case 0:
		    sprops->os_name = strdup("Windows 2000");
		    break;
	        case 1:
		    sprops->os_name = strdup("Windows XP");
		    break;
	        case 2:
		    sprops->os_name = strdup("Windows 2003");
		    break;
	        default:
		    sprops->os_name = strdup("Windows NT (unknown)");
		    break;
                }
          } else {
            sprops->os_name = strdup("Windows NT (unknown)");
          }

          sprops->os_version = malloc(30);
          if (sprops->os_version == NULL) break;
          sprintf((char*)sprops->os_version, "%d.%d", si.dwMajorVersion, si.dwMinorVersion);
          break;

#ifdef WINCE
	case VER_PLATFORM_WIN32_CE: 
		sprops->os_name = strdup("Windows CE");
		sprops->os_version = malloc(32);
		if (sprops->os_name == NULL || sprops->os_version == NULL)
		    break;
		sprintf((char*)sprops->os_version, "%d.%d build %d",
			si.dwMajorVersion, si.dwMinorVersion,
			si.dwBuildNumber);
		break;
#endif
	default:
	        sprops->os_name = strdup("Unknown");
		sprops->os_version = strdup("Unknown");
		break;
	}
	if (sprops->os_name == NULL || sprops->os_version == NULL) {
	    goto out_of_memory;
	}


#ifdef WINCE

	/* Set WINCE processor properties using SYSTEM_INFO */
	{
	  SYSTEM_INFO si;
	  GetSystemInfo (&si);
	  switch (si.wProcessorArchitecture) {
	  case PROCESSOR_ARCHITECTURE_INTEL:
	    sprops->os_arch = strdup("x86");
	    break;
	  case PROCESSOR_ARCHITECTURE_MIPS:
	    sprops->os_arch = strdup("mips");
	    break;
	  case PROCESSOR_ARCHITECTURE_SHX:
	    sprops->os_arch = strdup("shx");
	    break;
	  case PROCESSOR_ARCHITECTURE_ARM:
	    sprops->os_arch = strdup("arm");
	    break;
	  case PROCESSOR_ARCHITECTURE_UNKNOWN:
	  default:
	    sprops->os_arch = strdup("unknown");   
	  }
	}

#else  /* not WINCE */

	/* Set Windows XP/2000 processor properties using SYSTEM_INFO */
	{
	  SYSTEM_INFO si;
	  GetSystemInfo (&si);
	  switch (si.wProcessorArchitecture) {
	  case PROCESSOR_ARCHITECTURE_AMD64:
	    sprops->os_arch = strdup("amd64");
	    break;
	  case PROCESSOR_ARCHITECTURE_IA64:
	    sprops->os_arch = strdup("ia64");
	    break;
	  case PROCESSOR_ARCHITECTURE_INTEL:
	    sprops->os_arch = strdup("x86");
	    break;
	  case PROCESSOR_ARCHITECTURE_UNKNOWN:
	  default:
	    sprops->os_arch = strdup("unknown");   
	  }
	}

#endif /* WINCE */
    }

    /* Determing the language, country, and encoding from the host,
     * and store these in the user.language, user.region, and
     * file.encoding system properties. */
    {
        char *lc = "UTF-8";
#ifndef WINCE
        lc = setlocale(LC_CTYPE, "");
        if (lc == NULL) {
            /*
             * 'lc == null' means system doesn't support user's environment
             * variable's locale.
             */
          setlocale(LC_ALL, "C");
          sprops->language = "en";
          sprops->encoding = "UTF-8";
#else
        if (lc == NULL || !strcmp(lc, "C") || !strcmp(lc, "POSIX")) {
            lc = "en_US";
#endif
        } else {
            /*
             * locale string format in Solaris is
             * <language name>_<region name>.<encoding name>
             * <region name> and <encoding name> are optional.
             */
            char temp[64], *language = NULL, *region = NULL, *encoding = NULL;
            char *std_language = NULL, *std_region = NULL,
                 *std_encoding = NULL;
            char region_variant[64], *variant = NULL, *std_variant = NULL;
            char *p, encoding_variant[64];

            strcpy(temp, lc);
#ifndef WINCE
            setlocale(LC_ALL, lc);
#endif
            /* Parse the language, region, encoding, and variant from the
             * locale.  Any of the elements may be missing, but they must occur
             * in the order language_region.encoding@variant, and must be
             * preceded by their delimiter (except for language).
             *
             * If the locale name (without .encoding@variant, if any) matches
             * any of the names in the locale_aliases list, map it to the
             * corresponding full locale name.  Most of the entries in the
             * locale_aliases list are locales that include a language name but
             * no country name, and this facility is used to map each language
             * to a default country if that's possible.  It's also used to map
             * the Solaris locale aliases to their proper Java locale IDs.
             */
            if ((p = strchr(temp, '.')) != NULL) {
                strcpy(encoding_variant, p); /* Copy the leading '.' */
                *p = '\0';
            } else if ((p = strchr(temp, '@')) != NULL) {
                 strcpy(encoding_variant, p); /* Copy the leading '@' */
                 *p = '\0';
            } else {
                *encoding_variant = '\0';
            }
            
            if (mapLookup(locale_aliases, temp, &p)) {
                strcpy(temp, p);
            }
            
            language = temp;
            if ((region = strchr(temp, '_')) != NULL) {
                *region++ = '\0';
            }
            
            p = encoding_variant;
            if ((encoding = strchr(p, '.')) != NULL) {
                p[encoding++ - p] = '\0';
                p = encoding;
            }
            if ((variant = strchr(p, '@')) != NULL) {
                p[variant++ - p] = '\0';
            }

            /* Normalize the language name */
            std_language = "en";
            if (language != NULL) {
                mapLookup(language_names, language, &std_language);
            }
            sprops->language = std_language;

            /* Normalize the variant name.  Do this BEFORE handling the region
             * name, since the variant name will be incorporated into the
             * user.region property.
             */
            if (variant != NULL) {
                mapLookup(variant_names, variant, &std_variant);
            }

            /* Normalize the region name.  If there is a std_variant, then
             * append it to the region.  This applies even if there is no
             * region, in which case the empty string is used for the region.
             * Note that we only use variants listed in the mapping array;
	     * others are ignored.
             */
            *region_variant = '\0';
            if (region != NULL) {
                std_region = region;
                mapLookup(region_names, region, &std_region);
                strcpy(region_variant, std_region);
            }
            if (std_variant != NULL) {
               strcat(region_variant, "_");
               strcat(region_variant, std_variant);
            }
            if ((*region_variant) != '\0') {
               sprops->region = strdup(region_variant);
	       if (sprops->region == NULL) {
		   goto out_of_memory;
	       }
            }

            /* Normalize the encoding name.  Note that we IGNORE the string
             * 'encoding' extracted from the locale name above.  Instead, we 
             * use the more reliable method of calling nl_langinfo(CODESET).  
             * This function returns an empty string if no encoding is set for
             * the given locale (e.g., the C or POSIX locales); we use the
             * default ISO 8859-1 converter for such locales.  We don't need 
             * to map from the Solaris string to the Java identifier at this 
             * point because that mapping is handled by the character
             * converter alias table in CharacterEncoding.java.
             */
/*
            p = nl_langinfo(CODESET);
	    if (*p == '\0' || strcmp(p, "ANSI_X3.4-1968") == 0) {
		std_encoding = "8859_1";
	    } else {
		std_encoding = p;
	    }
*/
	    std_encoding = "UTF-8";

            sprops->encoding = std_encoding;
        }
    }
    
    sprops->unicode_encoding = "UnicodeLittle";

    /* 
     *  User Properties 
     */
    {  
      DWORD len = 256;
      char *uname, *userprofile;
      int length;   

      /* User Name */
      {
        sprops->user_name = (char *)malloc(len);
        if (sprops->user_name == NULL) {
          goto out_of_memory;
        }
        uname = getenv("USERNAME");
        if (uname != NULL && strlen(uname) > 0) {
          strcpy((char *)sprops->user_name, uname);
        } else {
          GetUserNameA((char*)sprops->user_name, &len);
        }
      }

      /* User Home Directory */
      {
        userprofile = getenv("USERPROFILE");
        if (userprofile != NULL) {
	  length = strlen(userprofile);
          sprops->user_home = (char *)malloc(length + 1);  
          if (sprops->user_home == NULL) {
            goto out_of_memory;
          }
          strcpy((char*)sprops->user_home, userprofile); 
        }          
        else {
          sprops->user_home = strdup("");
        }        
      }
    }
    
    /* User TIMEZONE */
    {
	/*
	 * We defer setting up timezone until it's actually necessary.
	 * Refer to TimeZone.getDefault(). However, the system
	 * property is necessary to be able to be set by the command
	 * line interface -D. Here temporarily set a null string to
	 * timezone.
	 */
#ifndef WINCE
	_tzset(); /* for compatibility */
#endif
	sprops->timezone = "";

    }

    /* Current directory */
#ifndef WINCE
    sprops->user_dir = (char *)malloc(256);
    if (sprops->user_dir == NULL) {
	goto out_of_memory;
    }
    GetCurrentDirectoryA(256, (char*)sprops->user_dir);
#else
    sprops->user_dir ="\\";
#endif

    sprops->file_separator = "\\";
    sprops->path_separator = ";";
    sprops->line_separator = "\n";

    /* Generic Connection Framework (GCF): CommConnection Property */
    /* NOTE: comma-delimited (no spaces) list of available comm (serial)
       ports */
    sprops->commports = "com0";

    return CVM_TRUE;

 out_of_memory:
    CVMreleaseJavaProperties(sprops);
    return CVM_FALSE;
}

/*
 * Free up memory allocated by CVMgetJavaProperties().
 */
void CVMreleaseJavaProperties(java_props_t *sprops)
{
    if (sprops->os_name != NULL) {
	free((char*)sprops->os_name);
    }
    if (sprops->os_version != NULL) {
	free((char*)sprops->os_version);
    }
    if (sprops->region != NULL) {
	free((char*)sprops->region);
    }
    if (sprops->user_name != NULL) {
	free((char*)sprops->user_name);
    }
    if (sprops->user_home != NULL) {
	free((char*)sprops->user_home);
    }
#ifndef WINCE
    if (sprops->user_dir != NULL) {
	free((char*)sprops->user_dir);
    }
#endif
}