#include <exec/types.h>
#include <proto/exec.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <proto/dos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <devices/tpt.h>

#include <dlg/dlg.h>
#include <dlg/resman.h>
#include <dlg/log.h>
#include <dlg/user.h>

#include <proto/dlg.h>

#include <pragmas/dlg.h>

static char version[]="$VER: TPTShell 2.0 © 1995-1997 by DLG Development ("__AMIGADATE__")";

int   NumArgs(char *);
int   ConvertCommand(char *, int);
int   cmp(struct CommandConvert *, struct CommandConvert *);
void  ListCommands(int );
void  CleanUp(char *);
void _CXBRK(void);
 
BPTR            ifh;
BPTR            ofh;

struct USER_DATA UserDat;
struct Ram_File  RStruct;

struct CommandConvert {char   cname[256];
                       char   tname[256];
                       UBYTE  levreq;
                       UBYTE  numargs;
                      } *convert = NULL;
long   comnum = 0;

char               mydevice[4];
struct Library    *DLGBase = NULL;
struct LangStruct *ls;
char             **SA;


void main(void)

{struct Process  *myproc;

 char  dname[128];
 char *argptr;
 int   access;
 int   comm;
 int   error;

 char  tnum [16];
 long  bytes_read;
 char  buf[256];



 ifh = Input();
 ofh = Output();

 if (!(DLGBase = OpenLibrary(DLGNAME, DLGVERSION)))  exit(5);
  
 myproc = (struct Process *)FindTask(NULL);
 ASPrintf(NULL, tnum, "%d> ", myproc->pr_TaskNum);
 
 if (GetDevName(mydevice)==-1)   CleanUp("Unable to determine port");
 if (!(ls = GetLang(mydevice)))  CleanUp(NULL);
 SA = ls->strings;

 if (!ReadUser(&RStruct,&UserDat,mydevice))  CleanUp(SA[3007]);

 WriteLog(DROP_TO_DOS, RStruct.Name, mydevice, "");

  access = UserDat.User_Level;
  ASPrintf(NULL, dname, "USER:%s", RStruct.Name);
  UnderScore(dname);
  CD(dname);

 TSetFlags  (T_ECHO, mydevice);
 TUnSetFlags(T_RAW,  mydevice);

 if (access < 255)
    {FILE *cfp;
     long  levreq;
     long  numargs = 255;
     long  counter;

     TUnSetFlags(T_BREAK, mydevice);
     if (!(cfp=fopen("DLGCONFIG:Misc/TPTSHELL.CFG", "r")))  CleanUp(SA[3008]);

     while((fscanf(cfp, "%s%s%d%d;\n", buf, buf, &levreq, &numargs)) > 2)
            comnum++;

     if (comnum)
        {convert = malloc(sizeof(struct CommandConvert) * comnum);

         fseek(cfp, 0, SEEK_SET);
         for(counter = 0; counter < comnum; counter++)
            {numargs = 255;

             fscanf(cfp, "%s%s%d%d;\n", convert[counter].cname,
                                        convert[counter].tname,
                                       &levreq,
                                       &numargs);
             convert[counter].levreq  = levreq;
             convert[counter].numargs = numargs;
            }

         TSetFlags(T_BREAK, mydevice);
         qsort(convert, comnum, sizeof(struct CommandConvert), cmp);
        }

     fclose(cfp);
    }

  AFPrintf(&UserDat, ofh, SA[3009]);
  if (UserDat.User_Level<255)  AFPrintf(&UserDat, ofh, SA[3010]);

  for(;;)
     {Write(ofh, &tnum, strlen(tnum));
      bytes_read = Read(ifh, buf, 256);
      Chk_Abort();

      if (bytes_read < 2)         continue;
      buf[bytes_read-1] = 0;
      if (!strlen(buf))           continue;

      if (!Stricmp(buf, "exit"))  break;
      if (!strcmp(buf, "?"))
         {ListCommands(access);
          continue;
         }

     {UBYTE offset = 0;
      char *c;

      for(c=buf; (*c!=' ')&&(*c!='\0'); c++)
          offset++;

      if (*c=='\0')
           argptr = NULL;
         else
          {buf[offset] = 0;
           argptr      = buf + offset + 1;
     }
     }

     {char tname[512];

      strcpy(tname, buf);
      if (access < 255)
         {if (!(comm = ConvertCommand(buf, access)))
             {AFPrintf(&UserDat, ofh, SA[3012], buf);
              continue;
             }
          
          comm = comm - 1;
          
          strcpy(tname, convert[comm].tname);

          if (argptr)
              if (NumArgs(argptr) > convert[comm].numargs)
                 {AFPrintf(&UserDat, ofh, SA[3013]);
                  continue;
                 }
         }

      if (argptr)
         {strcat(tname, " ");
          strcat(tname, argptr);
         }

      Chk_Abort();
      error = OverlayProgram(tname);
      Chk_Abort();
      if (error==-1)  AFPrintf(&UserDat, ofh, "%s: Unknown command\n", buf);
     }
     }

 AFPrintf(&UserDat, ofh, SA[3014]);
 CleanUp(NULL);
}


int NumArgs(char *buf)

{int   numargs =  1;
 UBYTE inspace = TRUE;

 for(;*buf; buf++)
     if ((*buf == ' ') && !inspace)
        {numargs++;
         inspace = TRUE;
        }
      else
         inspace = FALSE;

 return(numargs);
}


int ConvertCommand(char *buf, int access)
{
   int i;
   
   for(i = 0; i < comnum; i++)
   {
      if(!Stricmp(buf,convert[i].cname))
      {
         if(access<convert[i].levreq)
         {
            return(NULL);
         }
         else
         {
            return(i+1);
         }
      }
   }
   
   return(NULL);
}
   

int cmp(struct CommandConvert *a, struct CommandConvert *b)

{return(Stricmp(a->cname, b->cname));
}


void ListCommands(int access)

{int counter;

 if (access == 255)
    {AFPrintf(&UserDat, ofh, SA[3011]);
     return;
    }

 AFPrintf(&UserDat, ofh, SA[3015]);
 AFPrintf(&UserDat, ofh, SA[3016]);
 AFPrintf(&UserDat, ofh, SA[3017]);
 AFPrintf(&UserDat, ofh, SA[3018]);
  
 for(counter=0; counter < comnum; counter++)
     if (access>=convert[counter].levreq)
         AFPrintf(&UserDat, ofh, SA[3019],convert[counter].cname);

 AFPrintf(NULL, ofh, "\n");
}


void CleanUp(char *s)

{if (convert)    free(convert);

 TSetFlags  (T_RAW,  mydevice);
 TUnSetFlags(T_ECHO, mydevice);

 if (s)
    {Write(ofh, "\n Error: ", 9);
     Write(ofh, s, strlen(s));
     Write(ofh, "\n\n", 2);
    }

 ChainProgram("DLG:Menu", mydevice);
 CloseLibrary(DLGBase);
 exit(0);
}


void _CXBRK(void)

{CleanUp(NULL);
}
