HuntnGather – Rev 3

Subversion Repositories:
Rev:
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2021 Wizardry and Steamworks - License: MIT          //
///////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <signal.h>
#include <ctype.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <proto/dos.h>
#include <proto/exec.h>

#if defined ___AmigaOS___
#include "getopt.h"
#endif

#if !defined TRUE
#define TRUE 1;
#endif

#if !defined FALSE
#define FALSE 0;
#endif

#define DEFAULT_DATABASE_FILE "S:gather.db"

/*************************************************************************/
/*        Version string used for querrying the program version.         */
/*************************************************************************/
TEXT version_string[] =
        "\0$VER: Hunt 1.3 "__DATE__" by Wizardry and Steamworks";

int run = TRUE;

void SignalHandler(int sig) {
        // Toggle the run flag to stop execution.
        run = FALSE;
}

/*
        * Convert string to uppercase.
        */
char *strupr(char *str) {
        char *up;
        int i;

        up = (char *) malloc((strlen(str) + 1) * sizeof(char));
        sprintf(up, "%s", str);

        i = strlen(up);
        while(--i > -1) {
                up[i] = toupper(up[i]);
        }

        return up;
}

/*
        * Compare "name" and "needle" for equality.
        */
int compare(char *name, char *needle) {
#if defined ___AmigaOS___
        ULONG size;
        char *upn, *upe;
        int success;
        UBYTE *pattern;

        upe = strupr(needle);
        upn = strupr(name);

        size = strlen(upe) * 3;

        if(pattern = AllocVec(size, MEMF_ANY|MEMF_CLEAR)) {

                if(ParsePatternNoCase(upe, pattern, (LONG)size) >= 0) {
                        success = MatchPatternNoCase(pattern, upn);

                        FreeMem(pattern, size);

                        return success;
                }
        }

        return FALSE;
#else
        return strstr(strupr(name), strupr(needle) != NULL;
#endif
}


/*
        *
        * Search the database for a matching string.
        */
void SearchDatabase(char *dbFile, char* needle) {
        FILE *fp;
        char *name;
        char *path;
        char c;
        int i;
        int side;
        int match;
        int total;

        if((fp = fopen(dbFile, "r")) == NULL) {
                fprintf(stderr, "Unable to open gather database for reading.\n");
                return;
        }

        name = (char *) malloc(sizeof(char));
        path = (char *) malloc(sizeof(char));
        i = 0;
        side = 0;
        match = FALSE;
        total = 0;
        while(run && fscanf(fp, "%c", &c) == 1) {
#if defined ___AmigaOS___
                // Check if CTRL+C was pressed and abort the program.
                if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
                        run = FALSE;
                        break;
                }
#endif

                switch(c) {
                        case '\n':
                                ++total;
                                if(match) {
                                        fprintf(stdout, "%s\n", path);
                                        match = FALSE;
                                }
                                if(name != NULL) {
                                        free(name);
                                        name = (char *) malloc(sizeof(char));
                                }
                                --side;
                                i = 0;
                                break;
                        case '\t':
                                // Case insensitive match.
                                if(compare(name, needle)) {
                                        match = TRUE;
                                }
                                if(path != NULL) {
                                        free(path);
                                        path = (char *) malloc(sizeof(char));
                                }
                                ++side;
                                i = 0;
                                break;
                        default:
                                switch(side) {
                                        case 0:
                                                name = (char *) realloc(name, (i + 1 + 1) * sizeof(char));
                                                name[i] = c;
                                                name[i + 1] = '\0';
                                                break;
                                        case 1:
                                                path = (char *) realloc(path, (i + 1 + 1) * sizeof(char));
                                                path[i] = c;
                                                path[i + 1] = '\0';
                                                break;
                                        default:
                                                fprintf(stderr, "Database corrupted.\n");
                                                break;
                                }
                                ++i;
                                break;
                }
        }

        fclose(fp);
}

/*
        *
        * Search the database for the matching string.
        */
void Hunt(char *dbFile, char *needle) {
        // Search the database for the matching string.
        SearchDatabase(dbFile, needle);
}

int main(int argc, char **argv) {
        int option;
        char *dbFile;
        struct stat path;

        // Bind handler to SIGINT.
        signal(SIGINT, SignalHandler);

        dbFile = DEFAULT_DATABASE_FILE;
        while((option = getopt(argc, argv, "hd:")) != -1) {
                switch(option) {
                        case 'd':
                                dbFile = optarg;
                                break;
                        case 'h':
                                fprintf(stdout, "SYNTAX: %s [-d DATABASE] PATTERN\n", argv[0]);
                                break;
                        case '?':
                                fprintf(stderr, "Invalid option %c.\n", optopt);
                                fprintf(stdout, "SYNTAX: %s [-d DATABASE] PATTERN\n", argv[0]);
                                return 1;
                }
        }

        if(optind > argc) {
                fprintf(stdout, "SYNTAX: %s [-d DATABASE] PATTERN\n", argv[0]);
                return 1;
        }

        stat(dbFile, &path);
        if(!S_ISREG(path.st_mode)) {
                fprintf(stderr, "%s is not a file.\n", dbFile);
                return 1;
        }

        Hunt("S:gather.db", argv[1]);

   return 0;
}