/* EMACS_MODES: !lnumb !fill */

#include <stdio.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <dos.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <dir.h>

#define NAME "fremote"
#define VERSION "V2.1"

#define PAUSEWARN 20L /* Warn user if paused more than PAUSEWARN secs */

#define CONFIGFLE "fmenu.cfg" /* Config file for this program, list of Nodes */
#define MAXDIRS  64  /* maximum number of file areas */

#define MAXLINE 128

#define OK    0
#define ERROR   1

#define BREAKON 0
#define NOBREAK 1

#define MAXELM  256          /* Maximum number of elements for temp. array */
#define MAXNODE 128          /* Maximum number of nodes */
#define NODEFLAG "[NODES]"
#define DIRFLAG  "[DIRS]"
#define ENDLIST  "[END]"
#define INT       6    /* number of chars needed to represent and integer */

#define nl() printf("\n");

/* store file area paths in dirlist */
char dirlist[MAXDIRS][MAXPATH];
int secure;
char array[MAXELM][MAXLINE];   /* temp array */
int nodelist[MAXNODE];     /* store nodes here */

char work_dir[MAXPATH];
char temp_dir[MAXPATH];
char this_node[INT];
char file_minor[INT];
char remote_minor[INT];

/* Name of WWIV chain.txt file */
char chainfile[MAXPATH];

/* From skeleton.c */
#define v407


int    usernum,             /* user number for the user */
       age,                 /* age of the user */
       screenchars,         /* chars/line user has specified */
       screenlines,         /* lines/screen user has specified */
       sl,                  /* sec lev for user (0-255) */
       so,                  /* non-zero if user is sysop (sl=255) */
       cs,                  /* non-zero if user is co-sysop */
       okansi,              /* non-zero if user can support ANSI */
       incom,               /* non-zero if user is calling remotely */
       comport;             /* com port user is on */
char   name[81],            /* name/alias of user */
       realname[81],        /* real name of user */
       callsign[10],        /* amateur radio callsign of user */
       sex,                 /* sex of user, M or F */
       laston[81],          /* date user was last on */
       gfiles[81],          /* directory for text files, ends in \ */
       data[81],            /* directory for non-text files, ends in \ */
       sysoplog[81],        /* full path & filename for sysop log */
       curspeed[81];        /* speed user is on at, "KB" if local */
double gold,                /* gold user has */
       timeallowed,         /* number of seconds before user logged off */
       version;             /* version of WWIV running under */


#ifdef v407

/* function pointers for BBS functions.  ONLY used for 4.07 or later. */

void far interrupt (*inli)(char *, char *, int, int);
void far interrupt (*checka)(int *, int *);
void far interrupt (*pla)(char *, int *);
void far interrupt (*outchr)(char);
void far interrupt (*outstr)(char *);
void far interrupt (*nl)();
void far interrupt (*pl)(char *);
int  far interrupt (*empty)();
char far interrupt (*inkey)();
unsigned char far interrupt (*getkey)();
void far interrupt (*input)(char *, int);
void far interrupt (*inputl)(char *, int);
int  far interrupt (*yn)();
int  far interrupt (*ny)();
void far interrupt (*ansic)(int);
char far interrupt (*onek)(char *);
void far interrupt (*prt)(int, char *);
void far interrupt (*mpl)(int);

void far **funcs;

#endif

int read_in_data(char *fn)
{
  char buf[1024];
  char *ptr[30],*ss,s[81];
  int i,f,len,i1;
  float fl;

  f=open(fn,O_RDONLY | O_BINARY);
  if (f<0) {
    return(-1);
  }
  i1=1;
  ptr[0]=buf;
  len=read(f,(void *)buf,1024);
  close(f);
  for (i=0; i<len; i++)
    if (buf[i]==13) {
      buf[i]=0;
      ptr[i1++]=&buf[i+2];
    }
  while (*ptr[6]==32)
    ++(ptr[6]);
  while (*ptr[15]==32)
    ++(ptr[15]);
  usernum=atoi(ptr[0]);
  strcpy(name,ptr[1]);
  strcpy(realname,ptr[2]);
  strcpy(callsign,ptr[3]);
  age=atoi(ptr[4]);
  sex=*ptr[5];
  sscanf(ptr[6],"%f",&fl);
  gold=(double)fl;
  strcpy(laston,ptr[7]);
  screenchars=atoi(ptr[8]);
  screenlines=atoi(ptr[9]);
  sl=atoi(ptr[10]);
  so=atoi(ptr[11]);
  cs=atoi(ptr[12]);
  okansi=atoi(ptr[13]);
  incom=atoi(ptr[14]);
  sscanf(ptr[15],"%f",&fl);
  timeallowed=(double)fl;
  strcpy(gfiles,ptr[16]);
  strcpy(data,ptr[17]);
  strcpy(sysoplog,gfiles);
  strcat(sysoplog,ptr[18]);
  strcpy(curspeed,ptr[19]);
  comport=atoi(ptr[20]);

  version=-1.0;

  funcs=(void far *)getvect(0x6a);
  inli=funcs[0];
  checka=funcs[1];
  pla=funcs[2];
  outchr=funcs[3];
  outstr=funcs[4];
  nl=funcs[5];
  pl=funcs[8];
  empty=funcs[9];
  inkey=funcs[10];
  getkey=funcs[11];
  input=funcs[12];
  inputl=funcs[13];
  yn=funcs[14];
  ny=funcs[15];
  ansic=funcs[16];
  onek=funcs[17];
  prt=funcs[18];
  mpl=funcs[19];
  return(0);
}

/* My stuff */

struct time tm;


void main(int argc, char *argv[])
{
  char s[MAXLINE];
  char outstr[128];
  FILE *fi;
  int i;
  int num_read,nodes;

  colour(3);
  printf("Compile date and time %s %s",__DATE__,__TIME__);
  colour(0);
  nl();
  if (argc!=2){
     printf("usage: fremote chainfile\n");
     exit(0);
  }
  else {
     strcpy(chainfile,argv[1]);
  }

  if (read_in_data(chainfile)==-1) {
    fprintf(stderr,"%s: %s not found\n",NAME,chainfile);
    exit(ERROR);
  }

  nl();
  colour(4);
  printf(" %s %s By Quantum, #1@6300 - Copyright(c) 1991 Andrew Gaunt. ",NAME,VERSION);
  colour(0);
  nl();
  nl();

  /* Open configuration file, current directory */
  if ( (fi=fopen(CONFIGFLE,"r"))==NULL){
     colour(6);
     printf("Can't read config file %s.\n",CONFIGFLE);
     exit(ERROR);
     colour(0);
  }

  /* Read config file into temp array */
  if ( (num_read=readin_array(fi,MAXELM)) < 11){
    colour(6);
    printf("Config file %s too small, %d items read.",CONFIGFLE,num_read);
    colour(0);
    nl();
  }
  fclose(fi);

  /* print_array(); /* DEBUG */
  strcpy(work_dir,array[0]);
  strcpy(temp_dir,array[1]);
  strcpy(this_node,array[2]);
  strcpy(file_minor,array[3]);
  strcpy(remote_minor,array[4]);
  secure=atoi(array[5]);
  nodes=make_nodelist();
  make_dirlist();

/*  print_nodelist(); /* DEBUG */


    /* Check for remote request data files from other nodes */ 
    sprintf(s,"f_recv %s %sexternal.net %sexternal.net %s",remote_minor,data,temp_dir,work_dir);
    system(s);

  for(i=0;i<nodes;i++){
    sprintf(s,"%s%d.req",work_dir,nodelist[i]);
    printf("Node %d, ",nodelist[i]);
    if (readable(s)!=0){
      printf("none\n");
      sprintf(s,"No requests from %d.\n",nodelist[i]);
      logtosysop(s);
      continue;  
    }
    printf("processing\n");


    /* Open request file in work area */
    sprintf(s,"%s%d.req",work_dir,nodelist[i]);
    if ( (fi=fopen(s,"r"))==NULL){
       colour(6);
       printf("Can't read %s\n",s);
       exit(ERROR);
       colour(0);
    }

    /* Use the temp array to store data from remote system's request file */
    if ( (num_read=readin_array(fi,MAXELM)) < 1){
      colour(6);
      printf("Nothing to process @%d, %d items read.",nodelist[i],num_read);
      colour(0);
      nl();
    }
    /* Send the requested files to the remote system */
    remote(num_read);

    /* Remove remote request data file */
    sprintf(s,"%s%d.req",work_dir,nodelist[i]);
    unlink(s);
  }
  colour(4);
  printf(" [%s:%s] Complete ",NAME,VERSION);
  colour(0);
  nl();
  exit(OK);
}

remote(num_read)
int num_read;
{
  char outstr[80];
  char node[10];
  char filename[MAXFILE+MAXEXT];
  char ext[MAXEXT];
  char batfile[MAXPATH];
  char s[MAXPATH];
  int i,j;
  int found;
  FILE *f;

  colour(3);
  printf("Searching directories");
  colour(0);
  nl();
  for(i=0;i<num_read;i+=2){
     strcpy(node,array[i]);
     if(check_filename(array[i+1])==ERROR){
       sprintf(s,"Bad filename \"%s\" from @%s.\n",array[i+1],node);
       logtosysop(s);
       continue;
     }
     strcpy(filename,array[i+1]);

     if ( check_node(atoi(node))==ERROR){
        colour(6);
        printf("Node @%s not in list.",node);
        colour(0);
        nl();
        sprintf(s,"Invalid node: \"%s\" to @%s.\n",filename,node);
        logtosysop(s);
        continue;
     }

     found=0;
     for(j=0;j<=MAXDIRS;j++){
       if(dirlist[j][0]=='\0' || mykbhit()){
          break;
       }
       sprintf(s,"%s%s",dirlist[j],filename);
       if(readable(s)==0){
          found=1;
          printf("Found %s%s\n",dirlist[j],filename);
          sprintf(s,"f_send %s %s %s %s%s %s 1",node,this_node,file_minor,dirlist[j],filename,data);
          system(s);
          sprintf(s,"Sent \"%s\" to @%s.\n",filename,node);
          logtosysop(s);
          continue;
       }
    }
    if(found==0){
      colour(6);
      printf("File \"%s\" not found.",filename);
      colour(0);
      nl();
      sprintf(s,"File \"%s\" not found for @%s\n",filename,node);
      logtosysop(s);
    }
  }
  return(0);
}


/* if new is [0-7] then change colour */
colour(code)
short code;
{
  if(!okansi){
    return(0);
  }
  if (code<=7 && code>=0 ){
    printf("%c%d",'\003',code);

  }
  return(OK);
}

int readable(f)
char f[];
{
  FILE *fp;
  if ( (fp=fopen(f,"r")) != NULL){
    fclose(fp);
    return(0);
  }
  fclose(fp);
  return(1);
}

int fgetline(s,max,fp)
char s[];
int max;
FILE *fp;
{
  int i,c;
  i=0;
  while ( (c=fgetc(fp)) != EOF){
    if (c=='\n' || i>=max || c=='\t' ){
      break;
    }
    /* Comments begin with # and end with newline */
    if (c=='#'){
      while( (c=fgetc(fp))!='\n' ){
      }
      continue;
    }
    s[i]=c;
    i++;
  }
  s[i]='\0';
  return(i);
}

logtosysop(s)
char s[];
{
  FILE *fo;
  char f[MAXPATH];

  /* Don't log if Sysop and not-remote */
  if (incom==0 && sl==255){
    return(0);
  }

  sprintf(f,"%s",sysoplog);
  if ( (fo=fopen(f,"a")) != NULL){
    fprintf(fo,"   %s:%s",NAME,s);
  }
  else{
    colour(6);
    printf("Can't append to \"%s%s\"\n",gfiles,sysoplog);
    colour(0);
  }
  fclose(fo);
  return(OK);
}

int init_array()
{
	int i;
	i=0;
	for (i=1;i<MAXELM;i++){
		strcpy(array[i],"");
		i++;
	}
	return(OK);
}



/* Read from fi up to max number of items into array */
/* and return number of items read */
int readin_array(fi,max)
FILE *fi;
int max;
{
	int i;
	char s[MAXLINE];


	init_array();
	i=0;
	while ( i<max ){
		if ( fgetline(array[i],MAXLINE,fi) == NULL){
			break;
		}

/*   		printf("\t%d:[%s]\n",i,array[i]); /* FOR DEBUG */

 		if ( (strcmp(array[i],"")) == NULL){
			break;
		}

		i++;
		if ( i >= MAXELM ){
			colour(6);
			printf(s,"Config file too large, array full: %d\n",MAXELM);
			colour(0);
			nl();
			return(i);
		}
	}
	return(i);
}

int make_dirlist()
{
	char s[MAXLINE];
	int i,j,f;

	f=0,j=0;
	for(i=0;i<MAXELM;i++){
		if (strcmp(array[i],DIRFLAG) == NULL){
			f=1;
			continue;
		}
		if (strcmp(array[i],ENDLIST) == NULL){
			strcpy(dirlist[j],"");
			break;
		}
		if(f==1){
			if(j>=MAXDIRS){
				colour(6);
				printf("Too many directories: %d.\n",j);
				colour(0);
				strcpy(dirlist[j],"");
				return(-1);
			}
			strcpy(dirlist[j],array[i]);
/*  			printf("dir %d %s\n",j,dirlist[j]); /* DEBUG */
			j++;
		}
	}
	return(j);
}

int make_nodelist()
{
	char s[MAXLINE];
	int i,j,f;

	f=0,j=0;
	for(i=0;i<MAXELM;i++){
		if (strcmp(array[i],NODEFLAG) == NULL){
			f=1;
			continue;
		}
		if (strcmp(array[i],DIRFLAG) == NULL){
			nodelist[j]=0;
			break;
		}
		if(f==1){
			if(j>=MAXNODE){
				colour(6);
				printf("Too many nodes: %d.\n",j);
				colour(0);
				nodelist[j]=0;
				return(-1);
			}
			nodelist[j]=atoi(array[i]);
/* 			printf("node %d %d\n",j,nodelist[j]); /* DEBUG */
			j++;
		}
	}
	return(j);
}

check_node(n)
int n;
{
	int i;
	for(i=0;nodelist[i]>0;i++){
		if(n==nodelist[i]){
			return(OK);
		}
	}
	return(ERROR);
}

print_nodelist()
{
  int i;
  colour(3);
  printf("<< Nodelist >>");
  colour(1);
  nl();
  for (i=0;i<MAXELM;i++){
     if(nodelist[i]==0 ||mykbhit()){
         break;
     }
     printf("%03d. @%-04d\n",i,nodelist[i]);
  }
  colour(3);
  printf("<< END >>");
  colour(0);
  nl();
  return(OK);
}

print_array()
{
  int i;
  nl();
  for (i=0;i<MAXELM;i++){
     if(mykbhit()){
         break;
     }
     printf("%03d. %s\n",i,array[i]);
  }
  nl();
  return(OK);
}

mykbhit()
{
  long i,j;
  int c;
  static short pause;

  if(kbhit()){
    c=getch();
    switch (tolower(c)) {
      case 'p':
        if (pause==0){
          pause=1;
          time(&i);
          while (!kbhit()){
            time(&j);
            /* Warn user if paused more than 10 seconds */
            if (j>i+PAUSEWARN){
              printf("\007[PAUSED]\b\b\b\b\b\b\b\b");
              time(&i);
            }
          }
        }
        else{
          pause=0;
        }
        return(0);

      case '\n':
      case ' ':
        if (pause==0)
          return(1);
      default:
        return(1);
    }
  }
  return(OK);
}

check_filename(f)
char f[];
{
	int i;
	int dot;
	dot=0;
	for(i=0;i<strlen(f);i++){
		switch(f[i]) {
			case '.':
				dot++;
				break;
			case '\\':
			case '/':				
				dot=2;
		}
		
	}
/*
 	if (i>(MAXFILE)){
		colour(6);
		printf("Filename too long\t");
		colour(0);
		return(ERROR);
	}
*/
	if(dot>1){
		colour(6);
		printf("Bad Filename\n");
		colour(0);
		return(ERROR);
	}
	return(OK);
}
