Monday, April 7, 2014

My Text Search Utility


// TSUNAMI - Text Search Utility
// -----------------------------------
// Searches files for multiple text strings in given directory.
//
//   - Takes up to 10 search strings
//   - Searches up to 10 file types
//   - Optionally searches subdirectories
//   - Optionally searches hidden files/directories
//   - Writes results to RESULTS.TMP in current working 
//     directory. 
//

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <dir.h>
#include <dos.h>
#include <string.h>


const MAX_STRING = 1024;
const MAX_LIST   =   10;
const MAX_FNAME  =   13;
const MAX_SSTR   =   64;

const YES = 1;
const NO  = 0;

struct ft_list {
    char array[MAX_LIST][MAX_FNAME];
    int count;
};

struct ss_list {
    char array[MAX_LIST][MAX_SSTR];
    int count;
};

struct ft_list FLIST;
struct ss_list SLIST;

char RESULTS_FILE[MAX_FNAME] = "RESULTS.TMP";
char SRCH_DIR[MAX_STRING];
char ORIG_DIR[MAX_STRING];

int DO_SUBS;
int DO_HIDDEN;

FILE *results_fptr;


//--------------------------------------------------------
pause ()
{
    printf("\nPress any key... \n");
    while (!kbhit());
    return(0);
}


//-----------------------------
int file_exist (const char *fname)
{
    struct ffblk ffblk;

    return(findfirst(fname, &ffblk, FA_DIREC+FA_HIDDEN));
}

//--------------------------------------------------------
char *upstr (char *s)
{
    int i;

    for (i = 0; s[i] != 0; i++) s[i] = toupper(s[i]);
    return (s);
} // upstr


//--------------------------------------------------------
int get_ext_key (char k)
{
    if (k == 0) k = getch();
    return (k);
} // get_ext_key


//--------------------------------------------------------
char *get_input (char *s, int max_len)
{
    char *t;
    int i, key;

    if ((t = (char *) malloc(MAX_STRING)) != NULL)
    {
        if (max_len <= MAX_STRING) strcpy(t, s);
        i = strlen(t);
        printf("%s", s);
        while (!kbhit())
        {
            switch(key = getch())
            {
                case  0:  // EXTENDED KEY
                {
                    key = get_ext_key(key);
                    break;
                }
                case  8:  // BACKSPACE
                {
                    if (i > 0)
                    {
                        putch(key);
                        putch(' ');
                        putch(key);
                        t[--i] = '\0';
                    }
                    break;
                }
                case 13:  // RETURN
                {
                    putch('\n');
                    putch(key);
                    s = t;
                    return(s);
                }
                case 27:  // ESCAPE
                {
                    putch('\n');
                    putch('\r');
                    return(s);
                }
                default:
                {
                    if (i < max_len)
                    {
                        putch(key);
                        t[i] = key;
                        i++;
                        t[i] = '\0';
                        break;
                    }
                }
            }
        }
        free(t);
    }
    return (s);
} // get_input


//--------------------------------------------------------
input_search_directory ()
{
    struct ffblk ffblk;
    char *s;

    if ((s = (char *) malloc(MAX_STRING)) != NULL)
    {
        printf("Specify directory to search in:\n");
        do
        {
            s = "";
            strcpy(SRCH_DIR, upstr(get_input(s, MAX_STRING)));
            if (SRCH_DIR[0] == '\0')
            {
                printf("\nAborting TSU...\n");
                exit(1);
            }
            if (SRCH_DIR[strlen(SRCH_DIR)-1] == '\\')
                SRCH_DIR[strlen(SRCH_DIR)-1] = '\0';
            if (file_exist(SRCH_DIR) != 0)
                printf("\nERROR: Directory does not exist. Try again:\n");
        }
        while (file_exist(SRCH_DIR) != 0);
        free(s);
    }
    return (0);
} // input_search_directory


//--------------------------------------------------------
int toggle_subdirectories ()
{
    char ch;

    printf("Search subdirectories? [Y/N]: ");
    do
        ch = toupper(getch());
    while ((ch != 'Y') && (ch != 'N'));
    printf("%c\n", ch);
    if (ch == 'Y') DO_SUBS = YES; else DO_SUBS = NO;
    return (0);
} // toggle_subdirectories


//--------------------------------------------------------
int toggle_hidden ()
{
    char ch;

    printf("Search hidden files/directories? [Y/N]: ");
    do
        ch = toupper(getch());
    while ((ch != 'Y') && (ch != 'N'));
    printf("%c\n", ch);
    if (ch == 'Y') DO_HIDDEN = YES; else DO_HIDDEN = NO;
    return (0);
} // toggle_hidden


//--------------------------------------------------------
input_file_strings ()
{
    char *s;

    if ((s = (char *) malloc(MAX_FNAME)) != NULL)
        {
        s = "*.*";
        FLIST.count = 0;
        printf("Specify file types to search for (max. 10):\n");
        while (FLIST.count < MAX_LIST)
        {
            printf("%d) ", FLIST.count+1);
            s = upstr(get_input(s, MAX_FNAME));
            strcpy(FLIST.array[FLIST.count], s);
            if (FLIST.array[FLIST.count][0] == NULL) break;
            FLIST.count++;
            s = "";
        }
    free(s);
    }
    return (0);
} // input_file_strings


//--------------------------------------------------------
input_search_strings ()
{
    char *s;

    if ((s = (char *) malloc(MAX_SSTR)) != NULL)
    {
        SLIST.count = 0;
        printf("Specify search strings (max. 10):\n");
        while (SLIST.count < MAX_LIST)
        {
            printf("%d) ", SLIST.count+1);
            s = "";
            s = get_input(s, MAX_SSTR);
            strcpy(SLIST.array[SLIST.count], s);
            if (SLIST.array[SLIST.count][0] == NULL) break;
            SLIST.count++;
        }
        free(s);
    }
    return (0);
} // input_search_strings


//--------------------------------------------------------
int search_file_for_string (char *fname, char *s)
{
    struct ffblk ffblk;
    char ch;
    int i = 0;
    int len;
    FILE *fptr;

    len = strlen(s);
    if ((fptr = fopen(fname, "rt")) != NULL)
    {
        do
        {
            ch = fgetc(fptr);
            // convert special characters to spaces
            if ((ch == '\n') || (ch == '\r') || (ch == '\0')) ch = ' ';
            if ((ch == s[i]) && (i < len))
            {
                i++;
                if (i == len)
                {
                    fclose(fptr);
                    return(1);
                }
            }
            else i = 0;
        }
        while (ch != EOF);
        fclose(fptr);
    }
    return(0);
} // search_file_for_string


//--------------------------------------------------------
save_results_to_file (char *fname)
{
    char cwd[MAX_STRING];

    getcwd(cwd, MAX_STRING);
    if (cwd[3] != '\0') strcat(cwd, "\\");
    fprintf(results_fptr, "%s%s\n", cwd, fname);
    printf("\n");
    return(0);
} // save_results_to_file



//--------------------------------------------------------
search_for_strings (char *fname)
{
    int i, n;
    char *cwd;

    n = 0;
    for (i = 0; i < SLIST.count; i++)
    {
        if (search_file_for_string(fname, SLIST.array[i]) == 0) break;
        n++;
    }
    if ((n > 0) && (n == SLIST.count))
        save_results_to_file(fname);
    return(0);
} // search_for_strings


//--------------------------------------------------------
search_for_files (char *fname)
{
    struct ffblk ffblk;
    char cwd[MAX_STRING];
    int att = 0;
    int done;

    getcwd(cwd, MAX_STRING);
    if (cwd[3] != '\0') strcat(cwd, "\\");
    if (DO_HIDDEN == YES) att = FA_HIDDEN;
    done = findfirst(fname, &ffblk, att);
    while (!done)
    {
        printf("\r%s%s", cwd, ffblk.ff_name);
        clreol();
        search_for_strings(ffblk.ff_name);
        printf("\r");
        clreol();
        done = findnext(&ffblk);
    }
    if (DO_SUBS == YES)
    {
        att = att + FA_DIREC;
        done = findfirst("*.*", &ffblk, att);
        while (!done)
        {
            if (ffblk.ff_attrib & FA_DIREC)
            {
                if (ffblk.ff_name[0] != '.')
                {
                    chdir(ffblk.ff_name);
                    search_for_files(fname);
                    chdir("..");
                }
            }
            done = findnext(&ffblk);
        }
    }
    return (0);
} // search_for_files



//--------------------------------------------------------
int main (void)
{
    int i;

    clrscr();
    input_search_directory();
    toggle_subdirectories();
    toggle_hidden();
    input_search_strings();
    input_file_strings();
    getcwd(ORIG_DIR, MAX_STRING);
    if ((results_fptr = fopen(RESULTS_FILE, "wt")) != NULL)
    {
        if (chdir(SRCH_DIR) == 0)
        {
            for (i = 0; i < FLIST.count; i++)
                search_for_files(FLIST.array[i]);
            chdir(ORIG_DIR);
        }
        fclose(results_fptr);
        pause();
    }
    return(0);
}

No comments:

Post a Comment