/* * @(#)main.c 1.6 00/08/26 * * Copyright 1997, 1998 by Sun Microsystems, Inc., * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. * All rights reserved. * * This software is the confidential and proprietary information * of Sun Microsystems, Inc. ("Confidential Information"). You * shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with Sun. * Use is subject to license terms. */ /*========================================================================= * SYSTEM: Verifier * SUBSYSTEM: main program * FILE: main.c * OVERVIEW: Runs the Java class verifier. * AUTHOR: Sheng Liang, Sun Microsystems, Inc. * Modifications for JAR support, CLDC compliance, and comments, * Tasneem Sayeed, Sun Microsystems *=======================================================================*/ /*========================================================================= * Include files *=======================================================================*/ #include #include #include #include #include #include #include "sys_api.h" #include "path_md.h" #include "path.h" #include "oobj.h" //#include "jar.h" #include "locale_md.h" /* #include "../util/strings.h" #include "../util/error.h" #include "../util/message.h" #include "../structures/type_list.h" #include "../structures/string_list.h" #include "../structures/type.h" #include "../structures/identifier.h" #include "../structures/name_table.h" #include "../classgen/bytecode.h" #include "../structures/block.h" #include "../parser/parser.h" #include "../util/memory.h" #include "../main/static_entry.h" #include #include #include */ /*========================================================================= * Globals and extern declarations *=======================================================================*/ char str_buffer[STRINGBUFFERSIZE]; /* shared string buffer */ int processedfile = 0; int errorCode = 0; /* Error code returned by program */ bool_t no_native_methods = FALSE; bool_t no_floating_point = FALSE; bool_t no_finalizers = FALSE; char tmp_dir[32]; /* temporary directory for storing verified classes */ extern char *output_dir; /* output directory */ bool_t tmpDirExists = FALSE; extern void VerifyFile(register char *fn); //extern bool_t ProcessJARfile(char *buf, int len); //extern bool_t isJARfile(char *fn, int length); //static void usage(char *progname); /*========================================================================= * FUNCTION: recurse_dir() * TYPE: Handles recursive directories * OVERVIEW: Internal function called by ProcessInputs(). * * This function reads a directory, searching for either another directory, * JAR file or an individual class name that is to be verified. * * INTERFACE: * parameters: dirname name of the directory entry. * pkgname name of the package * returns: nothing *=======================================================================*/ /* static void recurse_dir(char *dirname, char *pkgname) { struct dirent *ent; char buf[MAXPACKAGENAME]; char pkgbuf[MAXPACKAGENAME]; DIR *dir = opendir(dirname); if (dir == NULL) { fprintf(stderr, "Can't open dir %s\n", dirname); exit(1); } for (ent = readdir(dir); ent; ent = readdir(dir)) { struct stat stat_buf; char *name = ent->d_name; int len; if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { continue; } strcpy(pkgbuf, pkgname); if (pkgname[0] != 0) { strcat(pkgbuf, "/"); } if (JAR_DEBUG && verbose) jio_fprintf(stderr, "recurse_dir: Reading filename [%s] from directory [%s]\n", name, dirname); strcat(pkgbuf, name); strcpy(buf, dirname); strcat(buf, name); stat(buf, &stat_buf); len = strlen(buf); if (stat_buf.st_mode & S_IFDIR) { // handle the recursive directory found strcat(buf, "/"); if (JAR_DEBUG && verbose) jio_fprintf(stderr, "recurse_dir: Recursive directory found, calling recurse_dir ([%s] [%s])\n", buf, pkgbuf); recurse_dir(buf, pkgbuf); continue; } else if (isJARfile (buf, len)) { // // this directory contains a JAR file which contains // the classes to be verified // if (JAR_DEBUG && verbose) jio_fprintf(stderr, "recurse_dir: Found JAR file [%s] in dir!\n", buf); if (!ProcessJARfile(buf, len)) { fprintf(stderr, "Not a valid JAR file [%s]\n", buf); exit(1); } } // we just have a class file that needs verification len = strlen(pkgbuf); if (len > 6 && strcmp(pkgbuf + len - 6, ".class") == 0) { pkgbuf[len - 6] = 0; if (JAR_DEBUG && verbose) jio_fprintf(stderr, "recurse_dir: Verifying Class [%s] \n", pkgbuf); VerifyFile(pkgbuf); } } closedir(dir); } */ /*========================================================================= * FUNCTION: ProcessInputs() * TYPE: Processes inputs * OVERVIEW: Internal function called by main(). * * This function processes input entries for specifying classes that are to * be verified. The inputs may be in 3 forms: a directory, or nested * directories, one or more JAR files, or one or more individual class files. * If a directory entry is specified, it may also contain one or more JAR * files, or one or more individual class files. * * INTERFACE: * parameters: argname: directory, JAR file or an individual class file. * returns: nothing *=======================================================================*/ /* static void ProcessInputs(char *argname) { char buf[MAXPACKAGENAME]; struct stat stat_buf; int res = stat(argname, &stat_buf); int len; strcpy(buf, argname); len = strlen(argname); if ((res == 0) && (stat_buf.st_mode & S_IFDIR)) { /* Append dir separator if it does not yet exist. if (buf[len - 1] != LOCAL_DIR_SEPARATOR && buf[len - 1] != DIR_SEPARATOR) { buf[len] = DIR_SEPARATOR; buf[len + 1] = 0; } pushDirectoryOntoClassPath(buf); recurse_dir(buf, ""); popClassPath(); } else if ((res == 0) && (isJARfile (buf, len))) { /* the classes to be verified are in a JAR file if (!ProcessJARfile(buf, len)) { fprintf(stderr, "Not a valid JAR file [%s]\n", buf); exit(1); } } else { char *p; /* Convert all periods in the argname to slashes for (p = buf; ((p = strchr(p, '.')) != 0); *p++ = '/'); if (JAR_DEBUG && verbose) jio_fprintf(stderr, "ProcessInputs: Verifying file [%s]\n", buf ); VerifyFile(buf); } }*/ /*========================================================================= * FUNCTION: main() * TYPE: Runs the verifier. * OVERVIEW: Main function. * * This is the main function that invokes the Java class verifier. * * INTERFACE: * parameters: argc: arg count. * argv: arg value(s) * returns: nothing *=======================================================================*/ /* int main(argc, argv) register char **argv; { char *progname; char *argv0 = argv[0]; SET_DEFAULT_LOCALE; if ((progname = strrchr(argv[0], LOCAL_DIR_SEPARATOR)) != 0) { progname++; } else { progname = argv[0]; } // initialize tmp_dir memset(tmp_dir, 0, 32); // initialize the seed for the random number srand(time(NULL)); // generate a random temp directory name sprintf(tmp_dir, "%s%d%c", "tmp", rand(), '\0'); while (--argc > 0) if ((++argv)[0][0] == '-') { if (strcmp(argv[0], "-verbose") == 0) { extern bool_t verbose; verbose = TRUE; #ifdef DEBUG_VERIFIER } else if (strcmp(argv[0], "-verify-verbose") == 0) { extern int verify_verbose; verify_verbose++; #endif } else if (strcmp(argv[0], "-cldc") == 0) { no_native_methods = TRUE; no_floating_point = TRUE; no_finalizers = TRUE; } else if (strcmp(argv[0], "-nofinalize") == 0) { no_finalizers = TRUE; } else if (strcmp(argv[0], "-nonative") == 0) { no_native_methods = TRUE; } else if (strcmp(argv[0], "-nofp") == 0) { no_floating_point = TRUE; } else if (strcmp(argv[0], "-Xns") == 0) { extern bool_t stack_map_on; stack_map_on = FALSE; } else if (strcmp(argv[0], "-Xni") == 0) { extern bool_t inline_jsr_on; inline_jsr_on = FALSE; } else if (strcmp(argv[0], "-d") == 0) { output_dir = strdup(argv[1]); argc--; argv++; } else if (strcmp(argv[0], "-classpath") == 0) { if (argc > 1) { char *buf = (char *)malloc(strlen(argv[1]) + 32); sprintf(buf, "CLASSPATH=%s", argv[1]); putenv(buf); argc--; argv++; } else { //fprintf(stderr, // "-classpath requires class path specification\n"); // usage(progname); exit(1); } } else { //fprintf(stderr, "%s: Illegal option %s\n\n", progname, argv[0]); // usage(progname); exit(1); } } else if (argv[0][0] == '@') { char *new_argv[MAXOPTIONS]; char *buffer; int new_argc = 1; char *token; bool_t done = FALSE; struct stat sbuf; FILE *fp; int buflen; int filelength; int i; new_argv[0] = argv0; fp = fopen(&argv[0][1], "rt"); if (fp == NULL) { fprintf(stderr, "Can't open %s\n", &argv[0][1]); exit(1); } // get the size of the file stat(&argv[0][1], &sbuf); filelength = sbuf.st_size; // allocate the buffer if ((buffer = (char *) malloc(filelength+1)) == NULL) { fprintf(stderr, "Out of memory\n"); exit(1); } if (fgets(buffer, filelength+1, fp) != NULL) { buflen = strlen(buffer); if (DEBUG_READFROMFILE) { fprintf(stderr, "Buffer = [%s]\n", buffer); } // get the first parameter token = strtok(buffer, " \0\n\r\t\""); // Search for parameters until none can be found while (token != NULL && !done) { if ((strcmp(token, "\n") == 0) || (strcmp(token, "\r") == 0) || (strcmp(token, "\t") == 0)) { // , or done = TRUE; } else { // On Win32, it's possible to have a // appended at the end of the token, which needs // to be extracted before restoring the arg // char *p; // Convert all to NULL for (p = token; *p != '\0'; p++) { if (*p == '\n' || *p == '\r') *p = '\0'; } // save the parameter new_argv[new_argc++] = token; if ((strcmp(token, "-classpath") == 0) || (strcmp(token, "-d") == 0)) { // search for the beginning of a string literal token = strtok(NULL, "\""); } else { // get the next token token = strtok(NULL," \0\n\r\t\""); } } } if (DEBUG_READFROMFILE) { // print the arguments after restoring all of them for (i=0; i < new_argc; i++) fprintf(stderr, "new_argv[%d] = [%s]\n", i, new_argv[i]); } } fclose(fp); main(new_argc, new_argv); if (buffer != NULL) { free(buffer); } argc--; argv++; } else { processedfile++; if (strlen(argv[0]) > MAXPACKAGENAME) { // fprintf(stderr, // "Package name for class exceeds max allowed size [1024]\n"); // usage(progname); exit(1); } ProcessInputs(argv[0]); } if (processedfile == 0) { usage(progname); exit(1); } return errorCode; // normal errorCode=0 indicates successful completion }*/ /* static void usage(char *progname) { fprintf(stderr, "Usage: %s [options] classnames|dirnames ...\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "where options include:\n"); fprintf(stderr, " -classpath \n", (char)PATH_SEPARATOR); fprintf(stderr, " Directories in which to look for classes\n"); fprintf(stderr, " -d Directory in which output is written (default is ./output/)\n"); fprintf(stderr, " -cldc Checks for existence of language features prohibited\n"); fprintf(stderr, " by CLDC (native methods, floating point and finalizers)\n"); fprintf(stderr, " -nofinalize No finalizers allowed\n"); fprintf(stderr, " -nonative No native methods allowed\n"); fprintf(stderr, " -nofp No floating point operations allowed\n"); fprintf(stderr, " @ Read command line arguments from a text file\n"); fprintf(stderr, " Command line arguments must all be on a single line\n"); fprintf(stderr, " Directory names must be enclosed in double quotes (\")\n"); fprintf(stderr, "\n"); } */ #ifndef O_BINARY #define O_BINARY 0 #endif //static int OpenCode(char *fn, char *sfn, char *dir, struct stat * st) { long codefd; char *fullname = (char*) malloc(strlen(fn) + strlen(dir) + 10); #ifdef WIN32 sprintf(fullname, "%s\\%s", dir, fn); #endif #ifdef UNIX sprintf(fullname, "%s/%s", dir, fn); #endif if (fn == 0 || (codefd = open(fullname, O_BINARY, 0644)) < 0 || fstat(codefd, st) < 0) { free(fullname); return -2; } free(fullname); return codefd; }