Example #1
0
/*
 * Load a jvm from "jvmpath" and initialize the invocation functions.
 */
jboolean
LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
{
    HINSTANCE handle;

    if (_launcher_debug) {
	printf("JVM path is %s\n", jvmpath);
    }

    /* Load the Java VM DLL */
    if ((handle = LoadLibrary(jvmpath)) == 0) {
	ReportErrorMessage2("Error loading: %s", (char *)jvmpath, JNI_TRUE);
	return JNI_FALSE;
    }

    /* Now get the function addresses */
    ifn->CreateJavaVM =
	(void *)GetProcAddress(handle, "JNI_CreateJavaVM");
    ifn->GetDefaultJavaVMInitArgs =
	(void *)GetProcAddress(handle, "JNI_GetDefaultJavaVMInitArgs");
    if (ifn->CreateJavaVM == 0 || ifn->GetDefaultJavaVMInitArgs == 0) {
	ReportErrorMessage2("Error: can't find JNI interfaces in: %s", 
			    (char *)jvmpath, JNI_TRUE);
	return JNI_FALSE;
    }

    return JNI_TRUE;
}
Example #2
0
/*
 * Load a jvm from "jvmpath" and initialize the invocation functions.
 */
jboolean
LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
{
    HINSTANCE handle;
    char crtpath[MAXPATHLEN];

    if (_launcher_debug) {
        printf("JVM path is %s\n", jvmpath);
    }

    /*
     * The Microsoft C Runtime Library needs to be loaded first.  A copy is
     * assumed to be present in the "JRE path" directory.  If it is not found
     * there (or "JRE path" fails to resolve), skip the explicit load and let
     * nature take its course, which is likely to be a failure to execute.
     */
    if (GetJREPath(crtpath, MAXPATHLEN)) {
        (void)strcat(crtpath, "\\bin\\" CRT_DLL);       /* Add crt dll */
        if (_launcher_debug) {
             printf("CRT path is %s\n", crtpath);
        }
        if (_access(crtpath, 0) == 0) {
            if (LoadLibrary(crtpath) == 0) {
                ReportErrorMessage2("Error loading: %s", crtpath, JNI_TRUE);
                return JNI_FALSE;
            }
        }
    }

    /* Load the Java VM DLL */
    if ((handle = LoadLibrary(jvmpath)) == 0) {
        ReportErrorMessage2("Error loading: %s", (char *)jvmpath, JNI_TRUE);
        return JNI_FALSE;
    }

    /* Now get the function addresses */
    ifn->CreateJavaVM =
        (void *)GetProcAddress(handle, "JNI_CreateJavaVM");
    ifn->GetDefaultJavaVMInitArgs =
        (void *)GetProcAddress(handle, "JNI_GetDefaultJavaVMInitArgs");
    if (ifn->CreateJavaVM == 0 || ifn->GetDefaultJavaVMInitArgs == 0) {
        ReportErrorMessage2("Error: can't find JNI interfaces in: %s",
                            (char *)jvmpath, JNI_TRUE);
        return JNI_FALSE;
    }

    return JNI_TRUE;
}
Example #3
0
static jboolean
LoadMSVCRT()
{
    // Only do this once
    static int loaded = 0;
    char crtpath[MAXPATHLEN];

    if (!loaded) {
        /*
         * The Microsoft C Runtime Library needs to be loaded first.  A copy is
         * assumed to be present in the "JRE path" directory.  If it is not found
         * there (or "JRE path" fails to resolve), skip the explicit load and let
         * nature take its course, which is likely to be a failure to execute.
         */
        if (GetJREPath(crtpath, MAXPATHLEN)) {
            (void)strcat(crtpath, "\\bin\\" CRT_DLL);   /* Add crt dll */
            if (_launcher_debug) {
                printf("CRT path is %s\n", crtpath);
            }
            if (_access(crtpath, 0) == 0) {
                if (LoadLibrary(crtpath) == 0) {
                    ReportErrorMessage2("Error loading: %s", crtpath, JNI_TRUE);
                    return JNI_FALSE;
                }
            }
        }
        loaded = 1;
    }
    return JNI_TRUE;
}
Example #4
0
/*
 * Load a jvm from "jvmpath" and initialize the invocation functions.
 */
jboolean
LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
{
#ifdef GAMMA
    /* JVM is directly linked with gamma launcher; no Loadlibrary() */
    ifn->CreateJavaVM = JNI_CreateJavaVM;
    ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs;
    return JNI_TRUE;
#else
    HINSTANCE handle;

    if (_launcher_debug) {
        printf("JVM path is %s\n", jvmpath);
    }

    /* The Microsoft C Runtime Library needs to be loaded first. */
    LoadMSVCRT();

    /* Load the Java VM DLL */
    if ((handle = LoadLibrary(jvmpath)) == 0) {
        ReportErrorMessage2("Error loading: %s", (char *)jvmpath, JNI_TRUE);
        return JNI_FALSE;
    }

    /* Now get the function addresses */
    ifn->CreateJavaVM =
        (void *)GetProcAddress(handle, "JNI_CreateJavaVM");
    ifn->GetDefaultJavaVMInitArgs =
        (void *)GetProcAddress(handle, "JNI_GetDefaultJavaVMInitArgs");
    if (ifn->CreateJavaVM == 0 || ifn->GetDefaultJavaVMInitArgs == 0) {
        ReportErrorMessage2("Error: can't find JNI interfaces in: %s",
                            (char *)jvmpath, JNI_TRUE);
        return JNI_FALSE;
    }

    return JNI_TRUE;
#endif /* ifndef GAMMA */
}
Example #5
0
/*
 * Parses command line arguments.  Returns JNI_FALSE if launcher
 * should exit without starting vm (e.g. certain version and usage
 * options); returns JNI_TRUE if vm needs to be started to process
 * given options.  *pret (the launcher process return value) is set to
 * 0 for a normal exit.
 */
static jboolean
ParseArguments(int *pargc, char ***pargv, char **pjarfile,
		       char **pclassname, int *pret)
{
    int argc = *pargc;
    char **argv = *pargv;
    jboolean jarflag = JNI_FALSE;
    char *arg;

    *pret = 1;
    while ((arg = *argv) != 0 && *arg == '-') {
	argv++; --argc;
	if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) {
	    if (argc < 1) {
	        ReportErrorMessage2("%s requires class path specification",
				    arg, JNI_TRUE);
		PrintUsage();
		return JNI_FALSE;
	    }
	    SetClassPath(*argv);
	    argv++; --argc;
	} else if (strcmp(arg, "-jar") == 0) {
	    jarflag = JNI_TRUE;
	} else if (strcmp(arg, "-help") == 0 ||
		   strcmp(arg, "-h") == 0 ||
		   strcmp(arg, "-?") == 0) {
	    PrintUsage();
	    *pret = 0;
	    return JNI_FALSE;
	} else if (strcmp(arg, "-version") == 0) {
	    printVersion = JNI_TRUE;
	    return JNI_TRUE;
	} else if (strcmp(arg, "-showversion") == 0) {
	    showVersion = JNI_TRUE;
	} else if (strcmp(arg, "-X") == 0) {
	    *pret = PrintXUsage();
	    return JNI_FALSE;
/*
 * The following case provide backward compatibility with old-style
 * command line options.
 */
	} else if (strcmp(arg, "-fullversion") == 0) {
	    fprintf(stderr, "%s full version \"%s\"\n", progname,
		    FULL_VERSION);
	    *pret = 0;
	    return JNI_FALSE;
	} else if (strcmp(arg, "-verbosegc") == 0) {
	    AddOption("-verbose:gc", NULL);
	} else if (strcmp(arg, "-t") == 0) {
	    AddOption("-Xt", NULL);
	} else if (strcmp(arg, "-tm") == 0) {
	    AddOption("-Xtm", NULL);
	} else if (strcmp(arg, "-debug") == 0) {
	    AddOption("-Xdebug", NULL);
	} else if (strcmp(arg, "-noclassgc") == 0) {
	    AddOption("-Xnoclassgc", NULL);
	} else if (strcmp(arg, "-Xfuture") == 0) {
	    AddOption("-Xverify:all", NULL);
	} else if (strcmp(arg, "-verify") == 0) {
	    AddOption("-Xverify:all", NULL);
	} else if (strcmp(arg, "-verifyremote") == 0) {
	    AddOption("-Xverify:remote", NULL);
	} else if (strcmp(arg, "-noverify") == 0) {
	    AddOption("-Xverify:none", NULL);
        } else if (strcmp(arg, "-XXsuppressExitMessage") == 0) {
            noExitErrorMessage = 1;
	} else if (strncmp(arg, "-prof", 5) == 0) {
	    char *p = arg + 5;
	    char *tmp = MemAlloc(strlen(arg) + 50);
	    if (*p) {
	        sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);
	    } else {
	        sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");
	    }
	    AddOption(tmp, NULL);
	} else if (strncmp(arg, "-ss", 3) == 0 ||
		   strncmp(arg, "-oss", 4) == 0 ||
		   strncmp(arg, "-ms", 3) == 0 ||
		   strncmp(arg, "-mx", 3) == 0) {
	    char *tmp = MemAlloc(strlen(arg) + 6);
	    sprintf(tmp, "-X%s", arg + 1); /* skip '-' */
	    AddOption(tmp, NULL);
	} else if (strcmp(arg, "-checksource") == 0 ||
		   strcmp(arg, "-cs") == 0 ||
		   strcmp(arg, "-noasyncgc") == 0) {
	    /* No longer supported */
	    fprintf(stderr,
		    "Warning: %s option is no longer supported.\n",
		    arg);
        } else if (strncmp(arg, "-version:", 9) == 0 ||
                   strcmp(arg, "-no-jre-restrict-search") == 0 ||
                   strcmp(arg, "-jre-restrict-search") == 0) {
	    ; /* Ignore machine independent options already handled */
	} else if (RemovableMachineDependentOption(arg) ) {
	    ; /* Do not pass option to vm. */
	}
	else {
	    AddOption(arg, NULL);
	}
    }

    if (--argc >= 0) {
        if (jarflag) {
	    *pjarfile = *argv++;
	    *pclassname = 0;
	} else {
	    *pjarfile = 0;
	    *pclassname = *argv++;
	}
	*pargc = argc;
	*pargv = argv;
    }

    return JNI_TRUE;
}
Example #6
0
/*
 * The SelectVersion() routine ensures that an appropriate version of
 * the JRE is running.  The specification for the appropriate version
 * is obtained from either the manifest of a jar file (preferred) or
 * from command line options.
 */
static void
SelectVersion(int argc, char **argv, char **main_class)
{
    char    *arg;
    char    **new_argv;
    char    **new_argp;
    char    *operand;
    char    *version = NULL;
    char    *jre = NULL;
    int     jarflag = 0;
    int     restrict_search = -1;		/* -1 implies not known */
    manifest_info info;
    char    env_entry[MAXNAMELEN + 24] = ENV_ENTRY "=";
    char    *env_in;
    int     res;

    /*
     * If the version has already been selected, set *main_class
     * with the value passed through the environment (if any) and
     * simply return.
     */
    if ((env_in = getenv(ENV_ENTRY)) != NULL) {
	if (*env_in != '\0')
	    *main_class = strdup(env_in);
	return;
    }

    /*
     * Scan through the arguments for options relevant to multiple JRE
     * support.  For reference, the command line syntax is defined as:
     *
     * SYNOPSIS
     *      java [options] class [argument...]
     *
     *      java [options] -jar file.jar [argument...]
     *
     * As the scan is performed, make a copy of the argument list with
     * the version specification options (new to 1.5) removed, so that
     * a version less than 1.5 can be exec'd.
     */
    new_argv = MemAlloc((argc + 1) * sizeof(char*));
    new_argv[0] = argv[0];
    new_argp = &new_argv[1];
    argc--;
    argv++;
    while ((arg = *argv) != 0 && *arg == '-') {
	if (strncmp(arg, "-version:", 9) == 0) {
	    version = arg + 9;
	} else if (strcmp(arg, "-jre-restrict-search") == 0) {
	    restrict_search = 1;
	} else if (strcmp(arg, "-no-jre-restrict-search") == 0) {
	    restrict_search = 0;
	} else {
	    if (strcmp(arg, "-jar") == 0)
		jarflag = 1;
	    /* deal with "unfortunate" classpath syntax */
	    if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) {
	        if (argc >= 1) {
		    *new_argp++ = arg;
		    argc--;
		    argv++;
		    arg = *argv;
		}
	    }
	    *new_argp++ = arg;
	}
	argc--;
	argv++;
    }
    if (argc <= 0) {	/* No operand? Possibly legit with -[full]version */
	operand = NULL;
    } else {
	argc--;
	*new_argp++ = operand = *argv++;
    }
    while (argc-- > 0)  /* Copy over [argument...] */
	*new_argp++ = *argv++;
    *new_argp = NULL;

    /*
     * If there is a jar file, read the manifest. If the jarfile can't be
     * read, the manifest can't be read from the jar file, or the manifest
     * is corrupt, issue the appropriate error messages and exit.
     *
     * Even if there isn't a jar file, construct a manifest_info structure
     * containing the command line information.  Its a convenient way to carry
     * this data around.
     */
    if (jarflag && operand) {
	if ((res = parse_manifest(operand, &info)) != 0) {
	    if (res == -1)
		ReportErrorMessage2("Unable to access jarfile %s",
		  operand, JNI_TRUE);
	    else
		ReportErrorMessage2("Invalid or corrupt jarfile %s",
		  operand, JNI_TRUE);
	    exit(1);
	}
    } else {
	info.manifest_version = NULL;
	info.main_class = NULL;
	info.jre_version = NULL;
	info.jre_restrict_search = 0;
    }

    /*
     * The JRE-Version and JRE-Restrict-Search values (if any) from the
     * manifest are overwritten by any specified on the command line.
     */
    if (version != NULL)
	info.jre_version = version;
    if (restrict_search != -1)
	info.jre_restrict_search = restrict_search;

    /*
     * "Valid" returns (other than unrecoverable errors) follow.  Set
     * main_class as a side-effect of this routine.
     */
    if (info.main_class != NULL)
	*main_class = strdup(info.main_class);

    /*
     * If no version selection information is found either on the command
     * line or in the manifest, simply return.
     */
    if (info.jre_version == NULL) {
	free_manifest();
	free(new_argv);
	return;
    }

    /*
     * Check for correct syntax of the version specification (JSR 56).
     */
    if (!valid_version_string(info.jre_version)) {
	ReportErrorMessage2("Syntax error in version specification \"%s\"",
	  info.jre_version, JNI_TRUE);
	exit(1);
    }

    /*
     * Find the appropriate JVM on the system. Just to be as forgiving as
     * possible, if the standard algorithms don't locate an appropriate
     * jre, check to see if the one running will satisfy the requirements.
     * This can happen on systems which haven't been set-up for multiple
     * JRE support.
     */
    jre = LocateJRE(&info);
    if (_launcher_debug)
        printf("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n",
          (info.jre_version?info.jre_version:"null"),
          (info.jre_restrict_search?"true":"false"), (jre?jre:"null"));
    if (jre == NULL) {
	if (acceptable_release(FULL_VERSION, info.jre_version)) {
	    free_manifest();
	    free(new_argv);
	    return;
	} else {
	    ReportErrorMessage2(
	      "Unable to locate JRE meeting specification \"%s\"",
	      info.jre_version, JNI_TRUE);
	    exit(1);
	}
    }

    /*
     * If I'm not the chosen one, exec the chosen one.  Returning from
     * ExecJRE indicates that I am indeed the chosen one.
     *
     * The private environment variable _JAVA_VERSION_SET is used to
     * prevent the chosen one from re-reading the manifest file and
     * using the values found within to override the (potential) command
     * line flags stripped from argv (because the target may not
     * understand them).  Passing the MainClass value is an optimization
     * to avoid locating, expanding and parsing the manifest extra
     * times.
     */
    if (info.main_class != NULL) {
	if (strlen(info.main_class) <= MAXNAMELEN) {
	    (void)strcat(env_entry, info.main_class);
	} else {
	    ReportErrorMessage("Error: main-class: attribute exceeds system limits\n", JNI_TRUE);
	    exit(1);
	}
    }
    (void)putenv(env_entry);
    ExecJRE(jre, new_argv);
    free_manifest();
    free(new_argv);
    return;
}
Example #7
0
/*
 * Checks the command line options to find which JVM type was
 * specified.  If no command line option was given for the JVM type,
 * the default type is used.  The environment variable
 * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also
 * checked as ways of specifying which JVM type to invoke.
 */
char *
CheckJvmType(int *pargc, char ***argv, jboolean speculative) {
    int i, argi;
    int argc;
    char **newArgv;
    int newArgvIdx = 0;
    int isVMType;
    int jvmidx = -1;
    char *jvmtype = getenv("JDK_ALTERNATE_VM");

    argc = *pargc;

    /* To make things simpler we always copy the argv array */
    newArgv = MemAlloc((argc + 1) * sizeof(char *));

    /* The program name is always present */
    newArgv[newArgvIdx++] = (*argv)[0];

    for (argi = 1; argi < argc; argi++) {
	char *arg = (*argv)[argi];
        isVMType = 0;

#ifdef JAVA_ARGS
 	if (arg[0] != '-') {
            newArgv[newArgvIdx++] = arg;
            continue;
        }
#else
 	if (strcmp(arg, "-classpath") == 0 || 
 	    strcmp(arg, "-cp") == 0) {
            newArgv[newArgvIdx++] = arg;
 	    argi++;
            if (argi < argc) {
                newArgv[newArgvIdx++] = (*argv)[argi];
            }
 	    continue;
 	}
 	if (arg[0] != '-') break;
#endif

 	/* Did the user pass an explicit VM type? */
	i = KnownVMIndex(arg);
	if (i >= 0) {
	    jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */
	    isVMType = 1;
	    *pargc = *pargc - 1;
	}

	/* Did the user specify an "alternate" VM? */
	else if (strncmp(arg, "-XXaltjvm=", 10) == 0 || strncmp(arg, "-J-XXaltjvm=", 12) == 0) {
	    isVMType = 1;
	    jvmtype = arg+((arg[1]=='X')? 10 : 12);
	    jvmidx = -1;
	}

        if (!isVMType) {
            newArgv[newArgvIdx++] = arg;
        }
    }

    /* 
     * Finish copying the arguments if we aborted the above loop.
     * NOTE that if we aborted via "break" then we did NOT copy the
     * last argument above, and in addition argi will be less than
     * argc.
     */
    while (argi < argc) {
        newArgv[newArgvIdx++] = (*argv)[argi];
        argi++;
    }

    /* argv is null-terminated */
    newArgv[newArgvIdx] = 0;

    /* Copy back argv */
    *argv = newArgv;
    *pargc = newArgvIdx;

    /* use the default VM type if not specified (no alias processing) */
    if (jvmtype == NULL)
	return knownVMs[0].name+1;

    /* if using an alternate VM, no alias processing */
    if (jvmidx < 0)
      return jvmtype;

    /* Resolve aliases first */
    {    
      int loopCount = 0;
      while (knownVMs[jvmidx].flag == VM_ALIASED_TO) {
        int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias);

        if (loopCount > knownVMsCount) {
	  if (!speculative) {
	    ReportErrorMessage("Error: Corrupt jvm.cfg file; cycle in alias list.",
			       JNI_TRUE);
	    exit(1);
	  } else {
	    return "ERROR";
	    /* break; */
	  }
        }

        if (nextIdx < 0) {
	  if (!speculative) {
            ReportErrorMessage2("Error: Unable to resolve VM alias %s",
				knownVMs[jvmidx].alias, JNI_TRUE);
            exit(1);
	  } else {
	    return "ERROR";
	  }
        }
        jvmidx = nextIdx;
        jvmtype = knownVMs[jvmidx].name+1;
	loopCount++;
      }
    }

    switch (knownVMs[jvmidx].flag) {
    case VM_WARN:
        if (!speculative) {
	    fprintf(stderr, "Warning: %s VM not supported; %s VM will be used\n", 
		    jvmtype, knownVMs[0].name + 1);
        }
	jvmtype = knownVMs[jvmidx=0].name + 1;
	/* fall through */
    case VM_KNOWN:
	break;
    case VM_ERROR:
        if (!speculative) {
	    ReportErrorMessage2("Error: %s VM not supported", jvmtype, JNI_TRUE);
	    exit(1);
        } else {
	    return "ERROR";
        }
    }

    return jvmtype;
}
Example #8
0
/*
 * Read the jvm.cfg file and fill the knownJVMs[] array.
 *
 * The functionality of the jvm.cfg file is subject to change without 
 * notice and the mechanism will be removed in the future.
 *
 * The lexical structure of the jvm.cfg file is as follows:
 *
 *     jvmcfg         :=  { vmLine }
 *     vmLine         :=  knownLine 
 *                    |   aliasLine 
 *                    |   warnLine 
 *                    |   errorLine 
 *                    |   commentLine
 *     knownLine      :=  flag  "KNOWN"                  EOL
 *     warnLine       :=  flag  "WARN"                   EOL
 *     errorLine      :=  flag  "ERROR"                  EOL
 *     aliasLine      :=  flag  "ALIASED_TO"       flag  EOL
 *     commentLine    :=  "#" text                       EOL
 *     flag           :=  "-" identifier
 *
 * The semantics are that when someone specifies a flag on the command line:
 * - if the flag appears on a knownLine, then the identifier is used as 
 *   the name of the directory holding the JVM library (the name of the JVM).
 * - if the flag appears as the first flag on an aliasLine, the identifier 
 *   of the second flag is used as the name of the JVM.
 * - if the flag appears on a warnLine, the identifier is used as the 
 *   name of the JVM, but a warning is generated.
 * - if the flag appears on an errorLine, an error is generated.
 * If no flag is given on the command line, the first vmLine of the jvm.cfg 
 * file determines the name of the JVM.
 *
 * The intent of the jvm.cfg file is to allow several JVM libraries to 
 * be installed in different subdirectories of a single JRE installation, 
 * for space-savings and convenience in testing.  
 * The intent is explicitly not to provide a full aliasing or predicate
 * mechanism.
 */
jint
ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative)
{
    FILE *jvmCfg;
    char jvmCfgName[MAXPATHLEN+20];
    char line[MAXPATHLEN+20];
    int cnt = 0;
    int lineno = 0;
    jlong start, end;
    int vmType;
    char *tmpPtr;
    char *altVMName;
    static char *whiteSpace = " \t";
    if (_launcher_debug) {
        start = CounterGet();
    }

    strcpy(jvmCfgName, jrepath);
    strcat(jvmCfgName, FILESEP "lib" FILESEP);
    strcat(jvmCfgName, arch);
    strcat(jvmCfgName, FILESEP "jvm.cfg");
    
    jvmCfg = fopen(jvmCfgName, "r");
    if (jvmCfg == NULL) {
      if (!speculative) {
        ReportErrorMessage2("Error: could not open `%s'", jvmCfgName,
			    JNI_TRUE);
	exit(1);
      } else {
	return -1;
      }
    }
    while (fgets(line, sizeof(line), jvmCfg) != NULL) {
        vmType = VM_UNKNOWN;
        lineno++;
        if (line[0] == '#')
            continue;
        if (line[0] != '-') {
            fprintf(stderr, "Warning: no leading - on line %d of `%s'\n",
                    lineno, jvmCfgName);
        }
        if (cnt >= knownVMsLimit) {
            GrowKnownVMs(cnt);
        }
        line[strlen(line)-1] = '\0'; /* remove trailing newline */
        tmpPtr = line + strcspn(line, whiteSpace);
        if (*tmpPtr == 0) {
            fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
                    lineno, jvmCfgName);
        } else {
            /* Null-terminate this string for strdup below */
            *tmpPtr++ = 0;
            tmpPtr += strspn(tmpPtr, whiteSpace);
            if (*tmpPtr == 0) {
                fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
                        lineno, jvmCfgName);
            } else {
                if (!strncmp(tmpPtr, "KNOWN", strlen("KNOWN"))) {
                    vmType = VM_KNOWN;
                } else if (!strncmp(tmpPtr, "ALIASED_TO", strlen("ALIASED_TO"))) {
                    tmpPtr += strcspn(tmpPtr, whiteSpace);
                    if (*tmpPtr != 0) {
                        tmpPtr += strspn(tmpPtr, whiteSpace);
                    }
                    if (*tmpPtr == 0) {
                        fprintf(stderr, "Warning: missing VM alias on line %d of `%s'\n",
                                lineno, jvmCfgName);
                    } else {
                        /* Null terminate altVMName */
                        altVMName = tmpPtr;
                        tmpPtr += strcspn(tmpPtr, whiteSpace);
                        *tmpPtr = 0;
                        vmType = VM_ALIASED_TO;
                    }
                } else if (!strncmp(tmpPtr, "WARN", strlen("WARN"))) {
                    vmType = VM_WARN;
                } else if (!strncmp(tmpPtr, "ERROR", strlen("ERROR"))) {
                    vmType = VM_ERROR;
                } else {
                    fprintf(stderr, "Warning: unknown VM type on line %d of `%s'\n",
                            lineno, &jvmCfgName[0]);
                    vmType = VM_KNOWN;
                }
            }
        }

        if (_launcher_debug)
            printf("jvm.cfg[%d] = ->%s<-\n", cnt, line);
        if (vmType != VM_UNKNOWN) {
            knownVMs[cnt].name = strdup(line);
            knownVMs[cnt].flag = vmType;
            switch (vmType) {
            default:
                break;
            case VM_ALIASED_TO:
                knownVMs[cnt].alias = strdup(altVMName);
                if (_launcher_debug) {
                    printf("    name: %s  vmType: %s  alias: %s\n", 
                           knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias);
                }
                break;
            }
            cnt++;
        }
    }
    fclose(jvmCfg);
    knownVMsCount = cnt;

    if (_launcher_debug) {
        end   = CounterGet();
        printf("%ld micro seconds to parse jvm.cfg\n",
               (long)(jint)Counter2Micros(end-start));
    }

    return cnt;
}