/* this CLI based program performs a search on a file for a specified
*  phrase. This code is freely distributable. You may use, misuse and 
*  abuse it to your hearts content.
*                                                   Phoggy
*  NOTE to NON AMIGADOS PLATFORMS:
*  A couple of minor adjustments:
*  1. The first #include statement will probably need to be removed.
*  2. If your system attaches Control-M to the end of each line, please 
*     make the modification commented in the function fillStructure.
*  3. I'd appreciate comments regarding any problems you find compiling
*     this code. There shouldn't be any..
*/

#include <exec/types.h>  /* probably requires removal for non-AmigaDOS */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define MAXLIST 1000  /* may need to be lowered for some systems */
#define MAXDATALEN 256

#define MAXNAMELEN 35
#define MAXADDRESSLEN 25
#define MAXLOCALLEN 50
#define MAXSYSOPLEN 50
#define MAXTELEPHONE 20
#define MAXACCESSINFO 100

void usage();
void noFile(char *);
void readFile(FILE *,struct THELIST *, char *, int *);
void fillStructure(char *, struct THELIST *, int);
void notifyMax();
void findZoneHostHub(char *, char *);
void setZoneHostHub(char *, char *, char *);
void fixSpecialStatus(char *, char *);

int locateFile(char *,struct THELIST *, char *, int *);
int searchCandidate(char *, char *);
int specialStatus(char *, char *);

struct attributes {
   char fidoname[MAXNAMELEN];
   char fidoaddress[MAXADDRESSLEN];
   char location[MAXLOCALLEN];
   char sysop[MAXSYSOPLEN];
   char telephone[MAXTELEPHONE];
   char accessinfo[MAXACCESSINFO];
   };
typedef struct {
   struct attributes data[MAXLIST];
   }THELIST;

main(int argc, char *argv[])
{
int status;
int numberofcases,i;
char searchfile[80];
char itemwanted[80];
THELIST *foundlist;

   if(argc!=3) {
      usage();
      exit(1);
   }

   foundlist = (THELIST *)malloc(sizeof(THELIST));

   strcpy(searchfile, argv[1]);
   strcpy(itemwanted, argv[2]);

   numberofcases = 0;

   status = locateFile(searchfile,foundlist,itemwanted,&numberofcases);
   if(status) {
      noFile(searchfile);
      exit(1);
   }

   for(i=0; i<numberofcases; i++) {
      printf("\nNAME:      %s\n", foundlist->data[i].fidoname);
      printf("ADDRESS:   %s\n", foundlist->data[i].fidoaddress);
      printf("LOCATION:  %s\n", foundlist->data[i].location);
      printf("SYSOP:     %s\n", foundlist->data[i].sysop);
      printf("TELEPHONE: %s\n", foundlist->data[i].telephone);
      printf("OTHERINFO: %s\n", foundlist->data[i].accessinfo);
   }
   if(numberofcases == MAXLIST)
      notifyMax();

  free(foundlist);
}
 int locateFile(char *filename, THELIST *list, char *searchtag, int *cases)
{
FILE *file;

int ret;

   if(!(file = fopen(filename,"r"))) {
      return(ret=ferror(file));
   }
   else {
      readFile(file,list,searchtag,cases);
      close(file);
      return(ret=ferror(file));
   }
}

void readFile(FILE *fp, THELIST *list, char *st, int *iterations)
{
int position = 0;
int status,done;
int c;
int cases;

char specialstatus[6];
char buf[MAXDATALEN];
char zone_num[15];
char host_num[15];
char hub_num[15];
char down_num[15];
char pvt_num[15];
char reg_num[15];

   cases = *iterations;
   while(!(done = feof(fp))) {
      c=fgetc(fp);
      if(c != '\n') {
         if(isascii(c)) {
            buf[position] = c; 
            buf[position+1] = '\0';

            position++;
            if(position==119)
               position = 0;
         }
      } 
      else {
         if(c =='\n') {
            position = 0;

            status = specialStatus(buf,specialstatus);
            if(status>0) {
                 switch(status) {
                    case 1: findZoneHostHub(buf,zone_num);
                            break;
                    case 2: findZoneHostHub(buf,host_num);
                            break;
                    case 3: findZoneHostHub(buf,hub_num);
                            break;
                    case 4: findZoneHostHub(buf,down_num);
                            break;
                    case 5: findZoneHostHub(buf,pvt_num);
                            break;
                    case 6: findZoneHostHub(buf,reg_num);
                            break;
                    default: break;
                 }
              fixSpecialStatus(buf,specialstatus); 
            }
            status = searchCandidate(buf,st);
            if(status) {
               if(cases<MAXLIST) {
                  setZoneHostHub(buf,zone_num,host_num);
                  fillStructure(buf,list,cases);
                  cases++;
               }
               else 
                  done = TRUE;
            } 
         } 
      }
   }
 *iterations = cases;
}

int specialStatus(char *teststring, char *status)
{
char *ptr;
char check[MAXDATALEN];
char *token;

   strncpy(check,teststring,1);
   if(ptr = strstr(check,","))
      return(0);
   if(ptr = strstr(check,";"))
      return(-1);
   strcpy(check,teststring);
   token = strtok(check,","); 
   strcpy(status,token);

   if(strstr(status,"Zone"))
      return(1);
   if(strstr(status,"Host"))
      return(2);
   if(strstr(status,"Hub"))
      return(3);
   if(strstr(status,"Pvt"))
      return(4);
   if(strstr(status,"Down"))
      return(5);
   if(strstr(status,"Region"))
      return(6);

return(-2);
}
void fixSpecialStatus(char *teststring, char *data)
{
char temp[MAXDATALEN];
char *ptr;
char *token;

   strcpy(temp,teststring);

   token = strtok(temp,",");
   token = strtok(NULL,",");

   ptr = teststring+(strlen(data)+1+strlen(token)+1);
   strcpy(teststring,ptr);
   strins(teststring,"),");
   strins(teststring,data);
   strins(teststring," - (");
   strins(teststring,token);
   strins(teststring,",");
}

int searchCandidate(char *teststring, char *searchstring)
{
char *ptr;

     ptr = strstr(teststring,searchstring);
     if(ptr) 
        return(1);
     else 
        return(0);
}

void findZoneHostHub(char *searchstring, char *zonehosthub)
{
char *token;
char temp[MAXDATALEN];

 strcpy(temp,searchstring); 

 token = strtok(temp,","); 
 token = strtok(NULL,",");
 strcpy(zonehosthub,token);
}

void setZoneHostHub(char *s, char *zone, char *hosthub)
{
char *ptr;

   if(!(ptr=strstr(s,"(Zone)"))) {

      if((ptr=strstr(s,"(Host)"))) {
         ptr = s+1;
         strcpy(s,ptr);
         strins(s,":");
         strins(s,zone);
         strins(s,",");
      }
      else {
         ptr = s+1;
         strcpy(s,ptr);
         strins(s,"/");
         strins(s,hosthub);
         strins(s,":");
         strins(s,zone);
         strins(s,",");
      }
   }
}

void fillStructure(char *searchstring, THELIST *list, 
                   int occurences)
{
char *token;
char temp[MAXACCESSINFO];
char *ptr;

   strcpy(temp,"");
   token = strtok(searchstring,",");
      strcpy(list->data[occurences].fidoaddress,token);
   token = strtok(NULL,",");
      strcpy(list->data[occurences].fidoname,token);
   token = strtok(NULL,",");
      strcpy(list->data[occurences].location,token);
   token = strtok(NULL,",");
      strcpy(list->data[occurences].sysop,token);
   token = strtok(NULL,",");
      strcpy(list->data[occurences].telephone,token);
   token = strtok(NULL,",");
   while(token != NULL) {
      strcat(temp,",");
      strcat(temp,token);
      token = strtok(NULL,",");
   }
/* The next three lines must be removed for some platforms */

   ptr = strrev(temp); /* nodelist was built using pc-klunk-junk so  */
   ptr = ptr+1;        /* strip the useless control-M from last line */
   strcpy(temp,strrev(ptr));

   strcpy(list->data[occurences].accessinfo,temp+1);
}

void usage()
{
   printf("\n\nUSAGE: <path_filename> <path_filetosearch> <item_to_find>\n\n");
}
void noFile(char *file)
{
   printf("\nERROR:Unable to locate \"%s\"\n",file);
}
void notifyMax()
{
   printf("\nNOTICE: There may be more items in the list than indicated.\n");
   printf("        The maximum number of allowable items has been found.\n");
   printf("        You may want to try again with a larger SEARCHSTRING\n");
}