/* 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 "fmenu"
#define VERSION "V2.1"

#define MENUFILE "FMENU.MSG"
#define QUEUE "SENDQUE.BAT"
#define QDATA "QUE.DAT"

#define CONFIGFLE "fmenu.cfg" /* Config file for this program, list of Nodes */
#define MAXDIRS  64  /* maximum number of file areas */

#define MAXLINE 128
#define KEYWAIT 120L  /* number of seconds to wait for no keys pressed */
#define PAUSEWARN 20L /* Warn user if paused more than PAUSEWARN secs */

#define OK    0
#define ERROR   1
#define TMOUT 2

#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");

void purgkey();
void prompt();
void inline();
int charin();


/* 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;

  if (argc!=2){
     printf("usage: fmenu chain_file\n");
     exit(ERROR);
  }
  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();
colour(3);
printf("Compiled %s %s",__DATE__,__TIME__);
colour(0);
nl();
nl();

/* Read in the 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);
}

if ( (i=readin_array(fi,MAXELM)) < 11){
  colour(6);
  printf("Config file %s too small, %d items read.",CONFIGFLE,i);
  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]);
make_nodelist();
make_dirlist();

menu_main();
exit(OK);
}

menu_main()
{
  char outstr[80];
  char node[10];
  char filename[MAXFILE+MAXEXT];
  char ext[MAXEXT];
  char datfile[MAXPATH];
  char s[MAXPATH];
  int i,j;
  FILE *f;
  long T;

  colour(0);
  nl();
  colour(2);
  strcpy(node,"0");
  printmenu(9);
  printf("Welcome ");
  if (sex=='M'){
    printf("Mr. ");
  }
  else{
    printf("Ms. ");
  }
  printf("%s, how may I assist you?\n\n",name);
  colour(0);
  printmenu(0);
  while (1) {
    purgkey();
    gettime(&tm);
    colour(3);
    printf("\n%02d:%02d:%02d\n",tm.ti_hour,tm.ti_min,tm.ti_sec);
    colour(2);
    printf("Command (h=help) ");
    colour(4);
    strcpy(outstr,"?");
    readf("A",outstr,KEYWAIT);
    colour(0);
    nl();
    switch(outstr[0]) {


      case 'e':
      case 'E':
	exit(OK);

      case '1':
      case 's':
      case 'S':
        colour(2);
        printf("Enter filename send: ");
        colour(4);
        readf("uuuuuuuuuuuu$",outstr,KEYWAIT);
        colour(0);
        nl();
        if(check_filename(outstr)==ERROR){
          sprintf(s,"Send; Bad filename \"%s\" to @%s.\n",outstr,node);
          logtosysop(s);
          break;
        }
 	strcpy(filename,outstr);
        colour(3);
        printf("<< Searching Directories >>\n");
        colour(0);
        for(i=0;i<=MAXDIRS;i++){
          if(dirlist[i][0]=='\0' || mykbhit()){
            break;
          }

          sprintf(s,"%s%s",dirlist[i],filename);
          colour(3);
          printf("< %s >\n",dirlist[i]);
          colour(0);
          if (readable(s)==0){
            colour(5);
            printf("\"%s\" (Y,N,Q) :",filename);
            colour(4);
            readf("u",outstr,KEYWAIT);
            colour(0);
            nl();
            if(outstr[0]=='Y') {
              colour(2);
              printf("Node number to send to [%s] :",node);
              colour(4);
              printf("@");
              strcpy(outstr,node);
              readf("#####$",outstr,KEYWAIT);
              strcpy(node,outstr);
              colour(0);
              nl();
              if ( check_node(atoi(node))==ERROR){
                 colour(6);
                 printf("Node @%s not in list.",node);
                 colour(0);
                 nl();
                 if(sl<secure){
                     continue;
                 }
              }
              if(atoi(node)<1){
                colour(6);
                printf("Ooooops!");
                colour(0);
                nl();
                continue;
              }
              nl();
              colour(5);
              strcpy(outstr,"Y");
              printf("Send file now [Y] ? ");
              colour(4);
              readf("u",outstr,KEYWAIT);
              colour(0);
              nl();
              if(outstr[0]=='Y') {
                colour(5);
                sprintf(s,"Send file %s%s to %s",dirlist[i],filename,node);
                printf("\n%s\n",s);
                sprintf(s,"f_send %s %s %s %s%s %s 1",node,this_node,file_minor,dirlist[i],filename,data);
                system(s);
                sprintf(s,"Sent \"%s\" to @%s.\n",filename,node);
                logtosysop(s);
                strcpy(outstr,"Y");
                colour(0);
              }
              else{
                sprintf(datfile,"%s%s",work_dir,QUEUE);
                if( (f=fopen(datfile,"a")) == NULL ){
                  colour(6);
                  printf("Can't create batch file queue, \"%s\".\n");
                  sprintf(s,"Error creating que file\n");
                  logtosysop(s);        
                }
                else{
		  fprintf(f,"REM %s #%d\n",name,usernum);
                  fprintf(f,"fsend %s %s %s %s%s %s 1\n",node,this_node,file_minor,dirlist[i],filename,data);
                  fprintf(f,"REM\n");
                  colour(3);
                  printf("<< Queueing file \"%s\" >>\n",filename);
                  sprintf(s,"File %s queued.\n",filename);
                  logtosysop(s);
                }
                fclose(f);
                sprintf(datfile,"%s%s",work_dir,QDATA);
                if( (f=fopen(datfile,"a")) == NULL ){
                  colour(6);
                  printf("Can't create queue data file, \"%s\".\n");
                  sprintf(s,"Error creating queue data file\n");
                  logtosysop(s);        
                }
                else{
                  time(&T);
                  printf("%s%s\t%d\t%s\t%lu\n",dirlist[i],filename,usernum,node,T);
                  fprintf(f,"%s%s\t%d\t%s\t%lu\n",dirlist[i],filename,usernum,node,T);
                  colour(0);
                  fclose(f);
                }
              }
            }
            if(outstr[0]=='N') {
              continue;
            }
            if(outstr[0]=='Q') {
              break;
            }
          }
        }
        colour(3);
        printf("<< Directory Search Complete >>\n");
        colour(0);
        break;

      case '2':
      case 'r':
      case 'R':
        sprintf(s,"Receive file minor type %s.\n",file_minor);
        logtosysop(s);
	sprintf(s,"%sexternal.net",data);
        if(readable(s)!=0){
	        sprintf(s,"Nothing to receive.\n");
	        logtosysop(s);
	        printf("%s",s);
		break;
	}		
        colour(5);
        printf("%s",s);
        sprintf(s,"f_recv %s %sexternal.net %sexternal.net %s",file_minor,data,temp_dir,work_dir);
        system(s);
        colour(0);
        break;

      case '3':
      case 'f':
      case 'F':
        sprintf(s,"List files in work area.\n");
        logtosysop(s);
        sprintf(s,"F_DIR %s",work_dir);
        colour(0);
        system(s);
        break;

      case '4':
      case 'd':
      case 'D':
        if(sl<secure){
          colour(6);
          printf("Sorry, your security level (%d) is not high enough, you need %d.\n",sl,secure);
          break;
        }
        colour(2);
        printf("File to delete in work area : ");
        strcpy(outstr,"");
        colour(4);
        readf("uuuuuuuuuuuuu",outstr,KEYWAIT);
        colour(0);
        nl();
        if(check_filename(outstr)==ERROR || strcmp(outstr,"")==NULL){
          sprintf(s,"Tried to delete \"%s\"\n",outstr);
          logtosysop(s);
          break;
        }
        strcpy(filename,outstr);
        if(strcmp(filename,"")==NULL){
          break;
        }
        sprintf(s,"%s%s",work_dir,filename);

        if(readable(s)==0){
          colour(3);
          unlink(s);
          sprintf(s,"Deleted \"%s\" in work area.\n",filename);
          printf(s);
          logtosysop(s);
        }
        else{
          colour(6);
          sprintf(s,"Failed to delete \"%s\" in work area\n",filename);
          printf(s);
          logtosysop(s);
        }
        colour(0);
        break;

      case '5':
      case 'q':
      case 'Q':
/*
        printf("Node files requested from [%s] :",node);
        colour(4);
        printf("@");
        strcpy(outstr,node);
        readf("#####$",outstr,KEYWAIT);
        colour(0);
        nl();
        strcpy(node,outstr);
        sprintf(s,"%s%s.req",work_dir,node);
        colour(3);
        printf("< Send Queue %s >\n",s);
        colour(0);
        type(s,BREAKON);
        colour(3);
        printf("< END >\n");
*/
        colour(0);
        sprintf(s,"%s%s",work_dir,QDATA);
        colour(3);
        printf("< Send Queue %s >\n",s);
        colour(0);
        type(s,BREAKON);
        colour(3);
        printf("< END >\n");
        colour(0);
        sprintf(s,"Viewed queue file.\n");
        logtosysop(s);
        break;
    
      case '6':
      case 'l':
      case 'L':
        if(sl<secure){
          colour(6);
          printf("Sorry, your security level (%d) is not high enough, you need %d.\n",sl,secure);
          break;
        }
        colour(2);
        printf("File to view with LNET [EXTERNAL.NET] : ");
        strcpy(outstr,"EXTERNAL.NET");
        colour(4);
        readf("uuuuuuuuuuuuu",outstr,KEYWAIT);
        colour(0);
        nl();
        strcpy(filename,outstr);
        sprintf(s,"LNET %s\n",filename);
        logtosysop(s);
        sprintf(s,"F_LNET %s",filename);
        colour(2);
        system(s);
        colour(0);
        break;

      case '7':
      case 'a':
      case 'A':
        colour(2);
        printf("Archive to view in work area : ");
        colour(4);
        readf("uuuuuuuuuuuuu",outstr,KEYWAIT);
        colour(0);
        nl();
        strcpy(filename,outstr);
        sprintf(s,"Archive view %s\n",filename);
        logtosysop(s);
        sprintf(s,"F_FV %s%s",work_dir,filename);
        colour(0);
        system(s);
        colour(0);
        break;

      case '8':
      case 'v':
      case 'V':
        colour(2);
        printf("Enter filename mask [*.*] : ");
        colour(4);
        strcpy(outstr,"*.*");
        readf("uuuuuuuuuuuu$",outstr,KEYWAIT);
        colour(0);
        nl();
        strcpy(filename,outstr);
        colour(3);
        printf("<< Searching Directories >>");
        colour(0);
        nl();
        sprintf(s,"View filenames, mask=%s\n",filename);
        logtosysop(s);
        for(i=2;i<=MAXDIRS;i++){
          if(dirlist[i][0]=='\0' || mykbhit()){
            break;
          }
          colour(3);
          printf("< %s >",dirlist[i]);
          colour(0);
          nl();
          sprintf(s,"F_DIR %s%s",dirlist[i],filename);
          system(s);
	}
        colour(3);
        printf("<< Search Complete >>");
        colour(0);
        nl();
        break;

      case '9':
      case 'n':
      case 'N':
        print_nodelist();
        sprintf(s,"Nodelist\n");
        logtosysop(s);
        break;


      case '0':
      case 'g':
      case 'G':
        colour(2);
        printf("Enter filename to request: ");
        colour(4);
        readf("uuuuuuuuuuuu$",outstr,KEYWAIT);
        colour(0);
        nl();
        if(check_filename(outstr)==ERROR || strcmp(outstr,"")==NULL){
          sprintf(s,"Request; Bad or null filename \"%s\" to @%s.\n",outstr,node);
          logtosysop(s);
          break;
        }
	strcpy(filename,outstr);
	colour(2);
        printf("Node number to request file from [%s] :",node);
        colour(4);
        printf("@");
        strcpy(outstr,node);
        readf("#####$",outstr,KEYWAIT);
        strcpy(node,outstr);
        colour(0);
        nl();			
        if ( check_node(atoi(node))==ERROR){
           colour(6);
           printf("Node @%s not in list.",node);
           colour(0);
           nl();
           break;
        }
        nl();
        sprintf(datfile,"%s%s.req",work_dir,this_node);
        if( (f=fopen(datfile,"a")) == NULL ){
           colour(6);
           printf("Can't create request data file, \"%s.req\".\n",this_node);
           sprintf(s,"Error creating request data file %s.req\n",this_node);
           logtosysop(s);        
        }
        else{
           printf("Get %s from %s\n",filename,node);
           fprintf(f,"%s\t%s\n",this_node,filename);
        }
        sprintf(s,"Requested %s from @%s\n",filename,node);
        logtosysop(s);        
        colour(0);
        fclose(f);

	sprintf(s,"%s%s.req",work_dir,this_node);
	if(readable(s)==0){
		colour(5);
		printf("Sending file requests.");
		colour(0);
		nl();
	        sprintf(s,"f_send %s %s %s %s%s.req %s 0",node,this_node,remote_minor,work_dir,this_node,data);
		system(s);
	        sprintf(s,"%s%s.req",work_dir,this_node);
		unlink(s);
		colour(0);
	}
	break;


      case 'h':
      case 'H':
        printmenu(1);
        break;

      default:
        printmenu(0);
        break;
    }
  }
}


/*********************************************************************/

readf(format,outstr,maxwait)
char format[];
char outstr[];
long maxwait;
{
  char s[MAXLINE+1];
  int i,j;
  int c,inlen,outlen;

  outlen=0;
  inlen=strlen(format);


/* fprintf(stderr,"format=[%s]\nlen=%d\nmaxwait=%d\n",format,strlen(format),maxwait); */

  inline(inlen);
  i=0;j=0;
  while( j<inlen && ( (c=charin(maxwait)) != TMOUT ) ){
    if (c==TMOUT){
      return(TMOUT);
    }
/*    c=charin(maxwait); */
/* fprintf(stderr,"\nformat[%d]:%c\tc:%c\t",i,format[i],c); */
    if (c=='\r'){
      break;
    }

    if (c=='\b'){
      if(j>0){
        fprintf(stdout,"\b_\b");
        i--;
        j--;
        outlen--;
      }
      continue;
    }

    /* Enter or Carrige return */
    if (format[i]=='$') {
      if (!iscntrl(c)){
        prompt("< type enter/<cr> >",inlen,outlen);
        continue;
      }
    }

    /* Control character */
    if (format[i]=='^') {
      if (!iscntrl(c)){
        prompt("< type a control character >",inlen,outlen);
        continue;
      }
    }

    /* Decimal Digit */
    if (format[i]=='#') {
      if (!isdigit(c)){
        prompt("< type a digit >",inlen,outlen);
        continue;
      }
    }


    /* Graph  */
    if (format[i]=='g') {
      if (!isgraph(c)){
        prompt("< type a graphic char >",inlen,outlen);
        continue;
      }
    }

    /* Lower case */
    if (format[i]=='l') {
      if(isupper(c)){
        c=tolower(c);
      }
    }

    /* Upper case */
    if (format[i]=='u') {
      if(islower(c)){
        c=toupper(c);
      }
    }

    /* Printable */
    if (format[i]=='p') {
      if (!isprint(c)){
        prompt("< type a printable char. >",inlen,outlen);
        continue;
      }
    }

    /* Punctuation */
    if (format[i]=='.') {
      if (!ispunct(c)){
        prompt("< use punctuation >",inlen,outlen);
        continue;
      }
    }

    /* White Space */
    if (format[i]==' ') {
      if (!isspace(c)){
        prompt("< type space/tab or enter >",inlen,outlen);
        continue;
      }
    }

    /* Anything ASCII */
    if (format[i]=='?') {
      if (!isascii(c)){
        prompt("< use ascii >",inlen,outlen);
        continue;
      }
    }

    i++;

    outstr[j]=c;
    fprintf(stdout,"%c",outstr[j]);
    j++;
    outstr[j]='\0';
    outlen=strlen(outstr);
  }
  return(0);
}

int charin(maxwait)
long maxwait;
{
  long t0,t1;
  time(&t0);
  while (!kbhit()) {
    time(&t1);
    if(t1>t0+maxwait){
      colour(6);
       printf("< Keyboard timeout >\n");
      colour(0);
      exit(TMOUT);
    }
  }
  return(getch());
}


void purgkey()
{
  /* clear out buffer if key(s) has been hit*/
  /* and place cursor at start of line */
  if (kbhit()){
    putchar('\n');
  }
  while(kbhit()) {
    getch();
  }

}

void prompt(s,i,o)
char *s[];
int i,o;
{
  int j;
  colour(6);
  fprintf(stdout,"%s",s);
  colour(4);
  while (!kbhit()){
  }
  for(j=0;j<strlen(s);j++){
    fprintf(stdout,"\b \b");
  }
  for(j=0;j<(i-o);j++){
    fprintf(stdout,"_");
  }
  for(j=0;j<(i-o);j++){
    fprintf(stdout,"\b");
  }
}

void inline(l)
int l;
{
  int i;
  for(i=0;i<l;i++){
    fprintf(stdout,"_");
  }
  for(i=0;i<l;i++){
    fprintf(stdout,"\b");
  }
}


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);
}


/* search through def'd menu file and printout appropriate menu */
printmenu(menu)
int menu;
{
  char line[MAXLINE];
  char s[MAXPATH];
  FILE *fi;
  short flag;
  sprintf(s,"%s%s",gfiles,MENUFILE);
/*   printf("s=%s\n",s); */
  if ( (fi=fopen(s,"r")) == NULL){
    colour(6);
    fprintf(stderr,"FATAL ERROR: can't read menufile, %s.\n",s);
    colour(0);
    exit(ERROR);
  }
  flag=0;
  while (fgets(line, MAXLINE,fi) != NULL){
    if (line[0] == '`'){
      sprintf(s,"`%02d",menu);
/*       printf("line=%s s=%s\n",line,s); */
      if(strncmp(line,s,3) == NULL){
        flag=1;
        continue;
      }
      else{
        if (flag==1){ /* stop searching, found once */
          break;
        }
        flag=0;
      }
    }
    if (flag==1){
      printf("%s",line);
    }
  }
  fclose(fi);
/*   printf("End\n") */
  return(OK);
}

/* 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 find_dirs()
{
  FILE *fp;
  char line[MAXPATH];
  int i,j;
  i=0;

  sprintf(line,"%s%s",data,dirfile);
  if ( (fp=fopen(line,"r")) == NULL) {
     colour(6);
     printf("< No \"%s\" >\n",data,line);
     colour(0);
     fclose(fp);
     return(-1);
     }
       else{
       colour(3);
       if(sl<secure){
          printf("< Reading directories >\n",line);
       }
       else{
          printf("< Reading directories in \"%s\" >\n",line);
       }
       colour(0);

      while (fgetline(dirlist[i],MAXLINE,fp) != NULL){
        if ( (strcmp(dirlist[i],"")) == NULL){
           break;
        }
        i++;
        if ( i >= MAXDIRS ){
          colour(6);
          printf("Too many directories, buffer full: %d lines\n",MAXDIRS);
          colour(0);
          break;
        }
      }
      fclose(fp);
      return(0);
   }
}
*/

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 type(f,i)
char *f;
int i;
{
	int c;
	FILE *fp;

	if ((fp = fopen(f, "r")) == NULL) {
		colour(5);
		printf("\"%s\" is empty or not found.",f);
		colour(0);
		nl();
		return(1);
	}
	else {
		/* type out until eof or key is hit */
		while ( (c=fgetc(fp)) != EOF ) {
			fputc(c,stdout);
			if ( (i==0) && mykbhit()){
				break;
			} 
		}
		purgkey();
		fclose(fp);
	}
	return(0);
}

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);
}

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);
}
