Wednesday, April 9, 2014

Updated Text Search Utility (Source Code)


// TSUNAMI - Text Search Utility
//--------------------
// Searches files for multiple text strings
//
//   - Takes up to 10 search strings
//   - Searches up to 10 file types
//   - Accepts wildcards (*, ?) in file types
//   - Optionally searches subdirectories
//   - Optionally searches hidden files/directories
//   - Program can be paused or aborted early
//   - Handles both text and binary files
//   - All search strings must be found in file
//   - Writes search results (file name and path) to
//     TSUNAMI.OUT 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 = 512;
const MAX_LIST   =  10;
const MAX_FNAME  =  13;  // max. field length for file types
const MAX_SSTR   =  64;  // max. field length for search strings

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;  // stores file types to search in
struct ss_list SLIST;  // stores strings to search for

char SRCH_DIR[MAX_STRING];
char ORIG_DIR[MAX_STRING];

const YES = 1;
const NO  = 0;

int DO_SUBDIRS;
int DO_HIDDEN;
int DO_OPTIMIZE;

int RESULTS_COUNT = 0;

char RESULTS_FILE[MAX_FNAME] = "TSUNAMI.OUT";  // output file

FILE *results_fptr;


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


//-----------------------------
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)
// s is the default input string to display
// max_len is the maximum length for input + 1
// length of s MUST be <= max_len <= MAX_STRING
{
 char t[MAX_STRING] = {'\0'};
 int i, key;

 if (max_len > MAX_STRING) max_len = MAX_STRING;  // keep in range
 strcpy(t, s);
 i = strlen(s);
 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);
    strcpy(s, t);
    return(s);
   }
   case 27:  // ESCAPE
   {
    putch('\n');
    putch('\r');
    s = "";
    return(s);
   }
   default:
   {
    if (i < max_len-1)  // allow for ending null
    {
     putch(key);
     t[i] = key;
     i++;
     t[i] = '\0';
     break;
    }
   }
  }
 }
 return (s);
} // get_input


//--------------------------------------------------------
void user_interrupt (void)
{
 int key = 0;

 switch (key = (int) toupper(getch()))
 {
  case 'P': // PAUSE
   {
    printf("\rPausing. Press any key to continue...");
    clreol();
    while (!kbhit());
    break;
   }
  case 27:  // ESCAPE
   {
    printf("\rAborting TSUNAMI");
    clreol();
    printf("\n\n%d results saved in %s\n", RESULTS_COUNT, RESULTS_FILE);
    chdir(ORIG_DIR);
    exit(1);
   }
  default:
   {
   }
 }
} // user_interrupt


//--------------------------------------------------------
void input_search_directory (void)
{
 char s[MAX_STRING] = {'\0'};

 strcpy(s, "C:\\DOCUME~1\\ADMINI~1\\MYDOCU~1\\DOWNLO~1");
 printf("Specify directory to search in:\n");
 do
 {
  strcpy(SRCH_DIR, upstr(get_input(s, MAX_STRING)));
  if (SRCH_DIR[0] == '\0')
  {
   printf("\nAborting TSUNAMI...\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");
  strcpy(s, "");
 }
 while (file_exist(SRCH_DIR) != 0);
} // input_search_directory


//--------------------------------------------------------
int toggle_YN (char *s)
{
 char ch;

 printf("%s", s);
 do
  ch = toupper(getch());
 while ((ch != 'Y') && (ch != 'N'));
 printf("%c\n", ch);
 if (ch == 'Y') return(YES); else return(NO);
} // toggle_YN


//--------------------------------------------------------
void input_search_strings (void)
{
 char s[MAX_SSTR] = {'\0'};

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


//--------------------------------------------------------
void input_file_strings (void)
{
 char s[MAX_FNAME] = {'\0'};

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


//--------------------------------------------------------
int search_file_for_string (char *fname, char *s)
{
 FILE *fptr;
 struct ffblk ffblk;
 char ch;
 int len;
 int  si = 0;      // search string index
 long fi = 0;      // file index

 len = strlen(s);
 if ((fptr = fopen(fname, "rb")) != NULL)
 {
  findfirst(fname, &ffblk, FA_HIDDEN);
  while (fi < ffblk.ff_fsize)
  {
   ch = fgetc(fptr);
   fi++;
   // convert special characters to spaces
   if ((ch == '\n') || (ch == '\r') || (ch == '\t') || (ch == '\0'))
    ch = ' ';
   if ((ch == s[si]) && (si < len))
   {
    si++;
    if (si == len)
    {
     fclose(fptr);
     return(1);
    }
   }
   else si = 0;
  }
  fclose(fptr);
 }
 return(0);
} // search_file_for_string


//--------------------------------------------------------
void save_results_to_file (char *fname)
{
 char cwd[MAX_STRING] = {'\0'};

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


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

 n = 0;
 for (i = 0; i < SLIST.count; i++)
 {
  if (search_file_for_string(fname, SLIST.array[i]) == 0) break;
  if (kbhit()) user_interrupt();  // check for pause or abort
  n++;
 }
 if ((n > 0) && (n == SLIST.count))
 {
  RESULTS_COUNT++;
  save_results_to_file(fname);
 }
} // search_for_strings


//--------------------------------------------------------
void search_for_files (char *fname)
{
 struct ffblk ffblk;
 char cwd[MAX_STRING] = {'\0'};
 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)
 {
  if (DO_OPTIMIZE == YES)
   search_for_strings(ffblk.ff_name);
  else
  {
   printf("\r%s%s", cwd, ffblk.ff_name);
   clreol();
   search_for_strings(ffblk.ff_name);
   printf("\r");
   clreol();
  }
  done = findnext(&ffblk);
 }
 if (DO_SUBDIRS == 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);
  }
 }
} // search_for_files



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

 clrscr();
 input_search_directory();
 DO_SUBDIRS  = toggle_YN("Search subdirectories? [Y/N]: ");
 DO_HIDDEN   = toggle_YN("Search hidden files/directories? [Y/N]: ");
 DO_OPTIMIZE = toggle_YN("Full optimization (no screen output)? [Y/N]: ");
 input_search_strings();
 input_file_strings();
 getcwd(ORIG_DIR, MAX_STRING);
 if ((results_fptr = fopen(RESULTS_FILE, "wt")) != NULL)
 {
  chdir(SRCH_DIR);
  printf("Press (P) to Pause, (ESC) to Abort...
  for (i = 0; i < FLIST.count; i++)
   search_for_files(FLIST.array[i]);
  chdir(ORIG_DIR);
  fclose(results_fptr);
  printf("\n%d results in %s\n", RESULTS_COUNT, RESULTS_FILE);
  pause();
 }
 return(0);
}

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);
}