HuntnGather – Rev 12
?pathlinks?
///////////////////////////////////////////////////////////////////////////
// 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 ___HAVE_GETOPT___
#include "getopt.h"
#endif
#if defined ___AmigaOS___
/*************************************************************************/
/* Version string used for querrying the program version. */
/*************************************************************************/
TEXT version_string[] =
"\0$VER: Hunt 1.7 "__DATE__" by Wizardry and Steamworks";
#endif
#if !defined TRUE
#define TRUE 1;
#endif
#if !defined FALSE
#define FALSE 0;
#endif
#define NAME_BUF 32
#define PATH_BUF 128
#define DEFAULT_DATABASE_FILE "S:gather.db"
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 = 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 *need) {
#if defined ___AmigaOS___
ULONG size;
char *upn, *upe;
int success;
UBYTE *pattern;
upe = strupr(need);
upn = strupr(name);
size = strlen(upe) * 3;
success = FALSE;
if(pattern = AllocVec(size, MEMF_ANY|MEMF_CLEAR)) {
if(ParsePatternNoCase(upe, pattern, (LONG)size) > 0) {
success = MatchPatternNoCase(pattern, upn);
FreeVec(pattern);
free(upe);
free(upn);
return success;
}
FreeVec(pattern);
}
free(upe);
free(upn);
return success;
#else
char *upn, *upe;
int success = FALSE;
upe = strupr(need);
upn = strupr(name);
success = strstr(strupr(name), strupr(need)) != NULL;
free(upe);
free(upn);
return success;
#endif
}
/*
*
* Search the database for a matching string.
*/
void SearchDatabase(char *dbFile, char* need) {
FILE *fp;
char *name;
int name_size;
char *path;
int path_size;
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_size = NAME_BUF;
name = malloc(name_size * sizeof(char));
path_size = PATH_BUF;
path = malloc(path_size * 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_size = NAME_BUF;
name = malloc(name_size * sizeof(char));
}
--side;
i = 0;
break;
case '\t':
// Case insensitive match.
if(compare(name, need)) {
match = TRUE;
}
if(path != NULL) {
free(path);
path_size = PATH_BUF;
path = malloc(path_size * sizeof(char));
}
++side;
i = 0;
break;
default:
switch(side) {
case 0:
if(strlen(name) == name_size) {
name_size = 1.5 * name_size;
name = realloc(name, name_size * sizeof(char));
}
//name = realloc(name, (i + 1 + 1) * sizeof(char));
name[i] = c;
name[i + 1] = '\0';
break;
case 1:
if(strlen(path) == path_size) {
path_size = 1.5 * path_size;
path = realloc(path, path_size * sizeof(char));
}
//path = realloc(path, (i + 1 + 1) * sizeof(char));
path[i] = c;
path[i + 1] = '\0';
break;
default:
fprintf(stderr, "Database corrupted.\n");
break;
}
++i;
break;
}
}
free(name);
free(path);
fclose(fp);
}
/*
*
* Search the database for the matching string.
*/
void Hunt(char *dbFile, char *need) {
// Search the database for the matching string.
SearchDatabase(dbFile, need);
}
void usage(char *name) {
fprintf(stdout, "Hunt & Gather - %s, a file index search tool. \n", name);
fprintf(stdout, " \n");
fprintf(stdout, "SYNTAX: %s [-d DATABASE] PATTERN \n", name);
fprintf(stdout, " \n");
fprintf(stdout, " -d DATABASE A path to a database generated by the \n");
fprintf(stdout, " Gather tool that should be searched. \n");
fprintf(stdout, " \n");
fprintf(stdout, "PATTERN is an AmigaOS DOS pattern to match file names. \n");
fprintf(stdout, " \n");
fprintf(stdout, "(c) 2021 Wizardry and Steamworks, MIT. \n");
}
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':
usage(argv[0]);
return 0;
case '?':
fprintf(stderr, "Invalid option %c.\n", optopt);;
return 1;
}
}
if(optind >= argc) {
usage(argv[0]);
return 1;
}
stat(dbFile, &path);
if(!S_ISREG(path.st_mode)) {
fprintf(stderr, "Database file '%s' is not a file.\n", dbFile);
return 1;
}
Hunt(dbFile, argv[optind]);
return 0;
}