
/******************************************************************************
**
**  This program is free software; you can redistribute it and/or
**  modify it, however, you cannot sell it.
**
**  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.
**
**  You should have received a copy of the license attached to the
**  use of this software.  If not, visit http://osiris.shmoo.com for
**  details.
**
******************************************************************************/

/*****************************************************************************
**
**  File:    printdb.c
**  Date:    June 11, 2002
**
**  Author:  Brian Wotring
**  Purpose: standalone osiris databse cli utility.
**
******************************************************************************/

#include "libosiris.h"
#include "libosirism.h"
#include "libosirisdb.h"
#include "libfileapi.h"

char db_path[MAX_PATH_LENGTH] = "";

osi_bool print_all_records = FALSE;
osi_bool print_all_errors  = FALSE;

/******************************************************************************
**
**    Function: print_usage
**
**    Purpose:  print usage statement.
**
******************************************************************************/

void print_usage()
{
    fprintf( stderr, "osiris db command line utility (v1.0).\n" );
    fprintf( stdout, "usage: printdb [-a] [-e] <database>\n\n" );
}

/******************************************************************************
**
**    Function: parse_arguments
**
**    Purpose:  read command line arguments.
**
******************************************************************************/

void parse_arguments( int argument_count, char *argument_list[] )
{
    int count;
    
    if( argument_count == 1 )
    {
        print_usage();
        exit(-1);
    }
    
    /* if only given a db name, run with that. */
    
    if( argument_count == 2 )
    {
        osi_strlcpy( db_path, argument_list[1], sizeof( db_path ) );
        return;
    }
    
    /* otherwise, look for options. */
    
    for( count = 1; count < ( argument_count - 1 ); count++ )
    {
        if( ( strcmp( argument_list[count], "-e" ) == 0 ||
              strcmp( argument_list[count], "--print-errors" ) == 0 ) )
        {
            print_all_errors = TRUE;
            continue;
        }
        
        if( ( strcmp( argument_list[count], "-a" ) == 0 ||
              strcmp( argument_list[count], "--all-records" ) == 0 ) )
        {
            print_all_records = TRUE;
            continue;
        }
                    
        else
        {
            print_usage();
            exit( -1 );
        }
    }
    
    /* get db name. */

    osi_strlcpy( db_path, argument_list[(argument_count-1)],
                 sizeof( db_path ) );
}

void print_database_header( OSI_DB *db )
{    
    int length;
    
    long record_count = 0;
    long error_count  = 0;
    
    OSI_DB_HEADER header;

    /* get and print db header items. */
    
    osi_scan_db_get_header_item( db, OSI_DB_HEADER_ITEM_COMPLETE,
                            &( header.complete ), sizeof( header.complete ),
                            &length );

    if( length == 0 )
    {
        header.complete = 0;
    }
    
    osi_scan_db_get_header_item( db, OSI_DB_HEADER_ITEM_RECORD_TYPE,
                            &( header.record_type ),
                            sizeof( header.record_type ), &length );

    if( length == 0 )
    {
        header.record_type = 0;
    }

    osi_scan_db_get_header_item( db, OSI_DB_HEADER_ITEM_HOST, header.host,
                            sizeof( header.host ), &length );

    header.host[length] = '\0';

    osi_scan_db_get_header_item( db, OSI_DB_HEADER_ITEM_USERNAME,
                                 header.username,
                            sizeof( header.username ), &length );

    header.username[length] = '\0';

    osi_scan_db_get_header_item( db, OSI_DB_HEADER_ITEM_CONFIG_NAME,
                            header.config_name, sizeof( header.config_name ),
                            &length );

    header.config_name[length] = '\0';

    osi_scan_db_get_header_item( db, OSI_DB_HEADER_ITEM_CONFIG_ID,
                            header.config_id, sizeof( header.config_id ),
                            &length );

    header.config_id[length] = '\0';

    osi_scan_db_get_header_item( db, OSI_DB_HEADER_ITEM_SCAN_RESULTS,
                            &( header.scan_results ),
                            sizeof( header.scan_results ), &length );
    
    /* get counts for records and errors. */
    
    error_count  = osi_scan_db_get_error_count( db );
    record_count = osi_scan_db_get_record_count( db );

    fprintf( stdout, "\n  DATABASE: %s\n\n", db->path );

    /* print status. */
    
    fprintf( stdout, "      status: " );
    
    if( header.complete == 1 )
    {
        fprintf( stdout, "complete\n" );
    }
    
    else
    {
        fprintf( stdout, "incomplete\n" );
    }
    
    /* print record type, only if incomplete, it is in the scan results. */
    
    if( header.complete == 0 )
    {
        fprintf( stdout, " record type: %s\n",
                 get_scan_record_name_from_type( (short)header.record_type ) );
    }
    
    /* print host. */
    
    fprintf( stdout, "        host: " );
    
    if( strlen( header.host ) > 0 )
    {
        fprintf( stdout, "%s", header.host );
    }
    
    else
    {
        fprintf( stdout, "unknown" );
    }
    
    fprintf( stdout, "\n" );
    
    /* print user. */
    
    fprintf( stdout, "        user: " );
    
    if( strlen( header.username ) > 0 )
    {
        fprintf( stdout, "%s", header.username );
    }
    
    else
    {
        fprintf( stdout, "unknown" );
    }
    
    fprintf( stdout, "\n" );
    
    /* print config name and id */

    fprintf( stdout, "      config: " );
    
    if( strlen( header.config_name ) > 0 )
    {
        fprintf( stdout, "%s", header.config_name );
        
        if( strlen( header.config_id ) > 0 )
        {
            fprintf( stdout, " (%s)", header.config_id );
        }
    }
    
    else
    {
        fprintf( stdout, "unknown" );
    }
    
    fprintf( stdout, "\n" );
    
    fprintf( stdout, "      errors: %d\n", error_count );
    fprintf( stdout, "     records: %d\n", record_count );
    
    if( header.complete == 1 )
    {
        fprintf( stdout, "\n  SCAN RESULTS:" );
        print_scan_results( &( header.scan_results ) );
    }
    
    else
    {
        fprintf( stdout, "\n" );
        fprintf( stdout, "  ** database is incomplete, no scan results.\n\n" );
    }
}

void print_database_records( OSI_DB *db )
{
    int result;
    
    int record_size;
    int record_type;
    
    SCAN_RECORD *record;
        
    record_type = osi_scan_db_get_record_type( db );
    record_size = determine_scan_record_size_from_type( record_type );
    
    if( record_size <= 0 )
    {
        return;
    }
    
    record = osi_malloc( record_size );
    result = osi_scan_db_get_first_record( db, record, record_size );
    
    while( result == OSI_DB_OK )
    {
        print_scan_record( record );
        result = osi_scan_db_get_next_record( db, record, record_size );
    }
    
    osi_free( record );
    fprintf( stdout, "\n" );
}

void print_database_errors( OSI_DB *db )
{
    int result;
    int size;
    
    OSI_ERROR error;
    result = osi_scan_db_get_first_error( db, &error, sizeof( error ), &size );

    while( result == OSI_DB_OK )
    {
        
        fprintf( stdout, "\n-------- begin error -------\n" );
        
        print_osi_error( &error );
        result = osi_scan_db_get_next_error( db, &error,
                                             sizeof( error ), &size );
    }
    
    fprintf( stdout, "\n" );
}


int main( int argument_count, char *argument_list[] )
{    
    OSI_DB db;
    int result;

    memset( &db, 0, sizeof( db ) );
    parse_arguments( argument_count, argument_list );
    
    if( osi_file_is_regular_file( db_path ) == FALSE )
    {
        fprintf( stderr, "printdb: error, file (%s) is not a regular file.\n\n",                 db_path );

        exit(-1);
    }
    
    osi_strlcpy( db.path, db_path, sizeof( db.path ) );
   
    result = osi_scan_db_open( &db, OSI_DB_READ );
 
    if( result != OSI_DB_OK )
    {
        fprintf( stderr, "error: %s\n", osi_get_name_for_error( result ) );
        exit(-1);
    }
    
    print_database_header( &db );
    
    /* now walk through the database. */
    
    if( print_all_records )
    {
        print_database_records( &db );
    }
    
    if( print_all_records || print_all_errors )
    {
        print_database_errors( &db );
    }
    
    osi_scan_db_close( &db );
    return 0;
}


