

#include <stdio.h>
#include <string.h>

#include <exec/nodes.h>
#include <exec/types.h>
#include <exec/lists.h>
#include <exec/devices.h>
#include <exec/io.h>
#include <exec/libraries.h>

#include <devices/serial.h>

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

#include "xferq/xferq.h"
#include "xferq/xferq_pragmas.h"

char VerString[]="$VER: JamTool 0.28c (94.03.27)";

typedef struct entry {
   char address[40];
   char password[20];
   struct entry *next;
   struct entry *prev;
} NODE;

NODE *addnew(NODE *start, char *address, char *password);
NODE *search(NODE *start, NODE *temp, char *address);
void delall(NODE *start);

int flolist(char uucp);
void writevar(char *stem, char *info);
void readvar(char *name, char *info);
void lookup(struct structup *lookupstruct);
void scanlist(char *list, struct structup *lookupstruct);
void xferqparse(char *source, char *destination);
void dialresp(char *address, char *response);
void chopadds(char *string, char *variable);

int type(char *filename, char *device, int unit, unsigned long baud, unsigned char sf);


int main(int argc, char **argv)
{

    FILE *datevar;

    static struct structup {
       char found;
       char nodelist[50];
       char address[50];
       char phone[50];
       char sysop[50];
       char type[6];
       char password[20];
       char city[20];
       char flags[30];
       char system[40];
       char baud[10];
       char hub[10];
       char region[10];
       char cost[10];
    } lookupstruct;
 
    int wazoocap, i;
    int error = 0;
    char c;
    char temp[255], tmp[255], stem[30];

    char cacheflag, nodeflag, displayflag, variables;

    strcpy(lookupstruct.nodelist, "Nodelist:");
    lookupstruct.found=0;

    if (argc > 1) argv[1][1] = tolower(argv[1][1]);

    if ((argc == 1)||(argv[1][0] != '-')||(argv[1][1] != 'i')&&(argv[1][1] != 'd')
        &&(argv[1][1] != 'v') && (argv[1][1] != 'o') && (argv[1][1] != 'l')
        &&(argv[1][1] != 't') && (argv[1][1] != 's') && (argv[1][1] != 'e')
        &&(argv[1][1] != 'r') && (argv[1][1] != 'i') && (argv[1][1] != 'a'))
    {
       
       printf("\n%s\n\nUsage: %s -command options\n\n", &VerString[6], argv[0]);
       printf("\t%s -a\tline\n", argv[0]);
       printf("\t%s -d\twazoo.cap line\n", argv[0]);
       printf("\t%s -e\tStartTime EndTime env:variable\n", argv[0]);
       printf("\t%s -i\tenv:varname\n", argv[0]);
       printf("\t%s -l{c}{n}{d} Address {stem}\n", argv[0]);
       printf("\t%s -r\tAddress Response\n", argv[0]);
       printf("\t%s -s\t{u}\n", argv[0]);
       printf("\t%s -t\tfilename device unit lockbaud serflags\n", argv[0]);
       printf("\t%s -v\tline\n", argv[0]);
       exit(0);
    }
    if (!(XferqBase = OpenLibrary("xferq.library", 1)))
    {
        printf("Can't Open Libs:Xferq.library v1.0\n");
        exit(0);
    }

    switch(argv[1][1])
    {
      case 'a':
      {

         FILE *fp;

         NODE *start;
         NODE *thisnode;

         char *akas, *valid, *invalid, *unknown, *temp;
         char password[20], address[40], passwd[20];
         int i,p, t;
         char junk[50];

         if (argc!=3)
         {
            printf("Usage: %s -a line\n", argv[0]);
            printf("\tThis function reads the Env: variable '$(line).remote.password', and it does\n");
            printf("\ta Lookup (phonebook only) of each address in the Env: Variable\n");
            printf("\t'Remote.Addresses', and writes 3 new Env: variables,\n");
            printf("\t'Remote.Addresses.Valid', 'Remote.Addresses.Invalid', and\n");
            printf("\t'Remote.Addresses.Unknown'.  Each variable starts with the\n");
            printf("\tline number you specified in your argument\n");
            CloseLibrary(XferqBase);
            exit(1);
	 }

         akas=(char *)malloc(2048);
         valid=(char *)malloc(2048);
         invalid=(char *)malloc(2048);
         unknown=(char *)malloc(2048);
         temp=(char *)malloc(512);

         start=(struct entry *)malloc(sizeof(struct entry));
         thisnode=(struct entry *)malloc(sizeof(struct entry));


         start->next = NULL;
         start->prev = NULL;
         strcpy(start->address, "start");

         sprintf(temp, "%s.remote.addresses", argv[2]);
         GetVar(temp, akas, 2048, GVF_GLOBAL_ONLY);

         sprintf(temp, "%s.remote.password", argv[2]);
         GetVar(temp, password, 20, GVF_GLOBAL_ONLY);

#ifdef KDEBUG
         KPrintF("%s\n", akas);
#endif

         if ((fp=fopen("s:jamtool.phone", "r")) == NULL)
         {
             strcpy(unknown, akas);
             strcpy(valid, "");
             strcpy(invalid, "");
             goto exitall;
         }

         t=0;
         while(fgets(temp, 512, fp)!=NULL)
         {
             t++;
             sscanf(temp, "%s %s %s %s", address, junk, junk, passwd);
             start=addnew(start, address, passwd);
         };
         fclose(fp);

         if ((fp=fopen("t:jamtool.cache", "r")) != NULL)
         {

            t=0;
            while(fgets(temp, 512, fp)!=NULL)
            {
               t++;
               sscanf(temp, "%s %s %s %s", address, junk, junk, passwd);
               start=addnew(start, address, passwd);
            };
            fclose(fp);
         }

#ifdef KDEBUG
         KPrintF("%ld entries read\n", t);
#endif

         p=0;
         while(p<strlen(akas))
         {
            i=0;
            while((p<strlen(akas)) && (akas[p] != ' '))
            {
               temp[i]=akas[p];
               p++;
               i++;
	    }
            temp[i]=0;
#ifdef KDEBUG
         KPrintF("%s ->", temp);
#endif

            xferqparse(temp, address);

#ifdef KDEBUG
         KPrintF("%s\n", address);
#endif

            thisnode=search(start, thisnode, address);
            strcat(address, " ");
            strcat(thisnode->address, " ");

            if (stricmp(thisnode->address, address))
               strcat(unknown, address);
            else if ((!stricmp(thisnode->password, password)) ||
                  (thisnode->password[0] == '-')) 
               strcat(valid, address);
            else
               strcat(invalid, address);
            p++;
	 }

         delall(start);

      exitall:

         sprintf(temp, "%s.Remote.Addresses.Valid", argv[2]);

         if (strlen(valid) < 255)
            writevar(temp, valid);
         else
            chopadds(valid, temp);

         sprintf(temp, "%s.Remote.Addresses.Invalid", argv[2]);
         if (strlen(invalid) < 255)
            writevar(temp, invalid);
         else
            chopadds(invalid, temp);

         sprintf(temp, "%s.Remote.Addresses.Unknown", argv[2]);
         if (strlen(unknown) < 255)
            writevar(temp, unknown);
         else
            chopadds(unknown, temp);

         free(akas);
         free(valid);
         free(invalid);
         free(unknown);
         free(temp);
         free(thisnode);
         free(start);

      }
      break;

      case 'l':
      {
         cacheflag = nodeflag = displayflag = variables = 0;
         
         for(i=1;i<strlen(argv[1]); i++)
         {
           c=tolower(argv[1][i]);
           if (c=='c') cacheflag = 1;
           if (c=='n') nodeflag = 1;
           if (c=='d') displayflag = 1;
           if (c=='v') variables = 1;
         }

         if ((argc - variables) != 3)
         {
            printf("Usage: %s -l{c}{n}{d}{v} Address {stem}\n\n", argv[0]);
            printf("\tThis command will do a lookup function for the\n");
            printf("\taddress you provide.\n");
            printf("\tc - Turn Cache support on\n");
            printf("\tn - Turn Nodelist support on\n");
            printf("\td - Turn extra display on\n");
            printf("\tv - Turn Env: variables on\n");
            printf("\t{stem} required if Env: variables are enabled\n");
            CloseLibrary(XferqBase);
            exit(5);
         }

         readvar("NODELISTDIR", temp);
         if (temp[0]) strcpy(lookupstruct.nodelist, temp);
 
         xferqparse(argv[2], lookupstruct.address);
         for(i=0;lookupstruct.address[i]=toupper(lookupstruct.address[i]);i++);

         scanlist("s:jamtool.phone", &lookupstruct);

         if (!lookupstruct.found)
         {
            if (cacheflag)
            {
               scanlist("t:jamtool.cache", &lookupstruct);
               if (!lookupstruct.found)
               {
                  if (nodeflag)
                  {
                    lookup(&lookupstruct);
                    if (lookupstruct.found)
                    {
                        sprintf(tmp, "echo >>t:jamtool.cache \"%s %s %s %s %s %s %s\"",
                            lookupstruct.address, lookupstruct.phone,
                            lookupstruct.type, lookupstruct.password,
                            lookupstruct.flags, lookupstruct.city,
                            lookupstruct.sysop);
                        system(tmp);
                    }
                  }
               }
            }
            else
            {
               if (nodeflag)
                 lookup(&lookupstruct);
               
            }                
	 }

         if (lookupstruct.found)
         {
            if (!strcmp(lookupstruct.sysop, "-")) lookupstruct.sysop[0] = 0;
            if (!strcmp(lookupstruct.city, "-")) lookupstruct.city[0] = 0;
            if (!strcmp(lookupstruct.password, "-")) lookupstruct.password[0] = 0;

            if (!strcmp(lookupstruct.phone, "-"))
                  strcpy(lookupstruct.phone, "-Undialable");

            printf("Address: %s (%s)\n", lookupstruct.address, lookupstruct.password);

            if (lookupstruct.hub[0])
               printf("System : %s\n", lookupstruct.system);

            if (displayflag)
               printf("Phone  : %s  Type: %s\n", lookupstruct.phone, lookupstruct.type);

            if (lookupstruct.sysop[0])
               printf("Sysop  : %s (%s)\n", lookupstruct.sysop, lookupstruct.city);

            printf("Flags  : %s", lookupstruct.flags);

            if (lookupstruct.baud[0])
               printf(",%s", lookupstruct.baud);
            printf("\n");

            if ((lookupstruct.hub[0]) && displayflag)
            {
               printf("Hub    : %s, Region: %s\n", lookupstruct.hub, lookupstruct.region);
               printf("Cost   : %s\n", lookupstruct.cost);
            }

            if (variables)
            {
               sprintf(stem, "%s.Sysop", argv[3]);
               writevar(stem, lookupstruct.sysop);

               sprintf(stem, "%s.Address", argv[3]);
               writevar(stem, lookupstruct.address);

               sprintf(stem, "%s.Type", argv[3]);
               writevar(stem, lookupstruct.type);

               sprintf(stem, "%s.MaxBaud", argv[3]);
               writevar(stem, lookupstruct.baud);

               sprintf(stem, "%s.Cost", argv[3]);
               writevar(stem, lookupstruct.cost);

               sprintf(stem, "%s.Number", argv[3]);
               writevar(stem, lookupstruct.phone);

               sprintf(stem, "%s.Flags", argv[3]);
               writevar(stem, lookupstruct.flags);

               if(lookupstruct.password[0]=='-')
                 lookupstruct.password[0]=0;

               sprintf(stem, "%s.Password", argv[3]);
               writevar(stem, lookupstruct.password);

               sprintf(stem, "%s.City", argv[3]);
               writevar(stem, lookupstruct.city);

               sprintf(stem, "%s.SiteName", argv[3]);
               writevar(stem, lookupstruct.system);
	    }

         }
         else
         {
            printf("Huh?  I don't know this Dude!\n");
            error=1;
         }
      }
      break;

    case 'i':
       if (argc != 3)
       {
          printf("Usage: %s -i env:variable\n", argv[0]);
          printf("\tThis function checks the validity of the string in the env:variable\n");
          printf("\tthat you specify.  It checks for special 'control' characters and\n");
          printf("\tother things that you may not want.  It returns WARN (5) if a bad\n");
          printf("\tcharacter is found\n");
          CloseLibrary(XferqBase);
          exit(1);
       }

       readvar(argv[2], tmp);
       for (i=0;i<strlen(tmp);i++)
       {
          if ((tmp[i] == '`') || (tmp[i] == '$'))
          {
             CloseLibrary(XferqBase);
             exit(5);
          }
            
          if ((tmp[i] == 34) || (tmp[i] == 39) || (tmp[i] == 96))
          {
             CloseLibrary(XferqBase);
             exit(5);
          }
       }
       break;

    case 'r':
       if (argc == 4) dialresp(argv[2], argv[3]);
       else error=1;
       break;

    case 's':
       if ((argc != 3) || (argv[2][0]=='u')) 
          flolist(0);
       else
          flolist(1);
       break;

    case 'e':
       {
          int hh,mm,ss;
          long start, end, duration;
          if (argc != 5)
          { 
             printf("Usage: %s -e StartTime EndTime Difference\n\n", argv[0]);
             printf("\tBoth StartTime and EndTime are time values specified\n");
             printf("\tin HH:MM:SS format.  An Environment variable named in\n");
             printf("\tthe 3rd value given will have the value of the\n");
             printf("\tdifference between the two.\n");
             CloseLibrary(XferqBase);
             exit(5);
          }
          sscanf(argv[2], "%d:%d:%d", &hh, &mm, &ss);
          start = hh*3600+mm*60+ss;
          sscanf(argv[3], "%d:%d:%d", &hh, &mm, &ss);
          end = hh*3600+mm*60+ss;
          if (end < start) end = end + 86400;
          duration = end - start;

          sprintf(tmp, "%02d:%02d:%02d", duration/3600,
          (duration/60)%60, duration%60);
          writevar(argv[4], tmp);
          error = 0;
       }
       break;

    case 'd':
       {
          if (argc != 4)
          {
              printf("Usage: %s -d Wazoo.Cap line\n\n", argv[0]);
              printf("\tThis option takes a decimal value and returns an ascii string\n");
              printf("\tin Env:{line}.wazoo.\n");
              error=1;
          }
          else
          {
              strcpy(tmp, "");
              wazoocap = atol(argv[2]);
              if (wazoocap &  8192) strcat(tmp, " 8192");
              if (wazoocap &  4096) strcat(tmp, " 4096");
              if (wazoocap &  2048) strcat(tmp, " 2048");
              if (wazoocap &  1024) strcat(tmp, " 1024");
              if (wazoocap &   256) strcat(tmp, " 256");
              if (wazoocap &   512) strcat(tmp, " 512");
              if (wazoocap &   128) strcat(tmp, " 128");
              if (wazoocap &    64) strcat(tmp, " 64");
              if (wazoocap &    32) strcat(tmp, " Hydra");
              if (wazoocap &    16) strcat(tmp, " Janus");
              if (wazoocap &     8) strcat(tmp, " ZedZap");
              if (wazoocap &     4) strcat(tmp, " ZedZip");
              if (wazoocap &     2) strcat(tmp, " Opus");
              if (wazoocap &     1) strcat(tmp, " DietIFNA");

              if (wazoocap & 32768) strcat(tmp, " +Freq");
              if (wazoocap & 16384) strcat(tmp, " +Domain");
              sprintf(temp, "%d.Wazoo", atoi(argv[3])); 
              writevar(temp, tmp);
              error = 0;
          }
          break;
       }

     case 't':
       {
          if (argc != 7)
          {
              printf("Usage: %s -t filename device unit baud serflags\n\n", argv[0]);
              printf("\tThis option types a single out the modem\n");
              error = 1;
          }
          else
          {
              type(argv[2], argv[3], atoi(argv[4]), (unsigned) atol(argv[5]),
                 (unsigned char) atoi(argv[6]));
          }
          break;

       }

     case 'v':
       {
          if (argc != 3)
          {
              printf("Usage: %s -v [line]\n\n", argv[0]);
              printf("\tThis option takes a single parameter of the line number, and\n");
              printf("\tcreates two env: variables, {line}.version and {line}.date.\n");
              error = 1;
          }
          else
          {
              sprintf(temp,"date >env:%s.Date", argv[2]);
              system(temp);
              sprintf(temp,"env:%s.Date", argv[2]);
              datevar = fopen(temp, "r");
              fgets(tmp, 80, datevar);
              fclose(datevar);
              tmp[strlen(tmp)-10] = 0;
              datevar = fopen(temp, "w");
              fputs(tmp, datevar);
              fclose(datevar);
              sprintf(temp,"version >env:%s.Version", argv[2]);
              system(temp);
              sprintf(temp,"env:%s.Version", argv[2]);
              datevar = fopen(temp, "r");
              fgets(tmp, 80, datevar);
              fclose(datevar);
              tmp[strlen(tmp)-1] = 0;
              datevar = fopen(temp, "w");
              fputs(tmp, datevar);
              fclose(datevar);
              error = 0;
          }
          CloseLibrary(XferqBase);
          exit(error);
          break;
       }
   
    }
    CloseLibrary(XferqBase);
    return(error);
}





void writevar(char *name, char *info)
{
   SetVar(name, info, -1, GVF_GLOBAL_ONLY);
}


void readvar(char *name, char *info)
{
   int l;
   l=GetVar(name, info, 10, GVF_GLOBAL_ONLY);

   if (l<1)
      info[0]=0;

}


NODE *addnew(NODE *start, char *address, char *password)
{
    NODE *new=NULL;
    NODE *temp;
 
    if ((new=(NODE *)malloc(sizeof(NODE))) != NULL)
    {
        strcpy(new->address, address);
        strcpy(new->password, password);
        
        temp=start;
        if (temp->next != NULL) temp=temp->next;

        while((temp->next != NULL) && (strcmp(temp->address, new->address) < 0))
           temp=temp->next;

        if (temp->next == NULL)
        {
           temp->next = new;
           new->prev = temp;
           new->next = NULL;
        }
        else if (temp==start)
        {
           new->prev=NULL;
           new->next=temp;
           start->prev=new;
           start=new;
        }
        else
        {
           temp=temp->prev;
           new->next=temp->next;
           temp->next=new;
           new->prev=temp;
           new->next->prev=new;
	}

#ifdef KDEBUG
         KPrintF("Added: %s -> %ld\n", new->address, new->address);
#endif
    }
    return (start);
}
        
NODE *search(NODE *start, NODE *temp, char *address)
{
    temp=start;

#ifdef KDEBUG
         KPrintF("\nSearching for: %s\n", address);
#endif

    while((temp->next != NULL) && (stricmp(address, temp->address)))
    {
#ifdef KDEBUG
       KPrintF("%s -> %ld\n", temp->address, stricmp(address, temp->address));
#endif
       temp=temp->next;
    }

    return temp;
}

void delall(NODE *start)
{

   NODE *temp;

   temp=start->next;

   while(temp->next != NULL)
   {
      temp=temp->next;

#ifdef KDEBUG
         KPrintF("Deleting: %s -> %ld\n", temp->prev->address, temp->prev);
#endif
      free(temp->prev);
   }

#ifdef KDEBUG
         KPrintF("Deleting: %s -> %ld\n", temp->address, temp);
#endif
   free(temp);
}

void chopadds(char *string, char *variable)
{
   char info[300], name[255];
   int i;                     /* counter in string */
   int j;                     /* counter in info */
   int k;                     /* number of variables */


#ifdef KDEBUG
   KPrintF("%s -> %s\n", variable, string);
#endif

   i=0;k=0;
   while(string[i])
   {
      j=0;

      do
      {
         info[j++]=string[i++];
      } while ((j<200) && (string[i]));

      if (string[i])
      {
         do
         {
            info[j++]=string[i++];
         } while ((string[i]) && (string[i] != ' '));
      }

      info[j]=0;
      if (string[i]) i++;

      if (k)
         sprintf(name, "%s.%d", variable, k+1);
      else
         strcpy(name, variable);
      SetVar(name, info, -1, GVF_GLOBAL_ONLY);

#ifdef KDEBUG
   KPrintF("%s -> %s\n", name, info);
#endif

      k++;
   }
}

void xferqparse(char *source, char *destination)
{
    char *address=NULL;

    struct NetAddress *addr;

    if(addr=XfqGetAddressTags(source,NULL,XQ_Mandatory,XQADDR_NODE,
                  XQ_Optional,XQADDR_ANYTHING,TAG_DONE))
    {
       if(address=XfqPutAddressTags(addr, XQ_Mandatory,XQADDR_ANYTHING,
                   XQ_Optional,XQADDR_ANYTHING,TAG_DONE))
       {
           strcpy(destination, address);
           XfqDropObject(address);
           XfqDropObject(addr);
       }
    }
    else
       strcpy(destination, source);

    return;
}
