/* 
 * Copyright (c) 2001 Secure Software Solutions
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include "report.h"
#include "version.h"

int     flags         = 0;
char *  progname      = "a.out";
char *  database_file = LIBDIR "/rats.xml";

static
int load_database(char *filename)
{
    int         result;
    FILE *      fd;
    char *      buf;
    struct stat st;

    if ((fd = fopen(filename, "r")) == (FILE *)NULL)
    {
        fprintf(stderr, "Unable to open '%s' for reading.\n", filename);
        return 0;
    }

    fstat(fileno(fd), &st);
    buf = (char *)malloc(st.st_size + 1);
    fread(buf, st.st_size, 1, fd);
    *(buf + st.st_size) = '\0';

    result = (ParseVulnDb(buf, &database) != NULL);
    free(buf);
    return result;
}

static
void usage(void)
{
    printf("RATS v%d.%d - Rough Auditing Tool for Security\n", VERSION_MAJOR, VERSION_MINOR);
    printf("Copyright 2001 by Secure Software Solutions\nhttp://www.securesw.com\n\n");
    printf("usage: %s [-dhrwx] name1 name2 ...\n\n", progname);
    printf("    -d <filename>   specify an alternate vulnerability database.\n");
    printf("    -h              display usage information (what you\'re reading)\n");
    printf("    -i              report functions that accept external input\n");
    printf("    -r              include references that are not function calls\n");
    printf("    -w <1,2,3>      set warning level (default %d)\n", warning_level);
    printf("    -x              do not load default database (%s)\n", database_file);
}

int main(int argc, char **argv)
{
    int i, load_default = 1;

    progname = argv[0];
    while ((i = getopt(argc, argv, "d:hirw:x")) != -1)
    {
        switch (i)
        {
            case 'd':
                if (!load_database(optarg))
                {
                    exit(1);
                    return 1;
                }
                break;

            case 'h':
                usage();
                exit(1);
                return 1;

            case 'i':
                flags |= INPUT_MODE;
                break;

            case 'r':
                flags |= INCLUDE_ALL_REFERENCES;
                break;

            case 'w':
                warning_level = 4 - atoi(optarg);
                if (warning_level < 1)
                    warning_level = 1;
                if (warning_level > 3)
                    warning_level = 3;
                break;

            case 'x':
                load_default = 0;
                break;

            default:
                exit(1);
                return 1;
        }
    }

    if (load_default)
    {
        /* Load the vulnerability database into memory */
        if (!load_database(database_file))
        {
            exit(1);
            return 1;
        }
    }

    if (optind >= argc)
    {
        process_file("<stdin>", stdin);
    }
    else
    {
        while (optind < argc)
        {
            char *  filename;
            FILE *  fd;

            filename = argv[optind++];
            if ((fd = fopen(filename, "r")) == (FILE *)NULL)
            {
                fprintf(stderr, "%s: unable to open '%s' for reading.\n", progname, filename);
                continue;
            }
            process_file(filename, fd);
            fclose(fd);
        }
    }

    generate_report();

    exit(0);
    return 0;
}
