/*
 *  FILES.C - Server for the W0RLI MailBox V10.xx
 *
 *  Copyright (C) 1989
 *  Peter Meiring
 *  13 Venn Crescent,
 *  Hartley, Plymouth.
 *  PL3 5PJ
 *
 *  This code may be freely used and copied for non-commercial uses.
 *
 *  s files files.exe files.out H8 files.in H8
 *
 *  See SERVER.DOC for further details.
 *
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dir.h>
#include <ctype.h>
#include <string.h>

#define BUFSIZE 256

/*
 *  Copyright storage:
 */

char *copyright = "FILES 1.03  Copyright (c) Peter Meiring, G0BSX, 1989.\n";

/*
 *  Some buffer space.
 */

#define ln_buf 512

char buf[ln_buf];

/*
 *  End-of-message mark.
 */

char *mark    = "/EX\n";

/*
 *  File used by this program to read initialisation Data
 */

char *datfile = "/bbs/config.mb";
/*
 *  File the MailBox will create, and this server will read.
 */

char *infile  = "files.out";

/*
 *  File this server will create, and the MailBox will read.
 */

char *outfile = "files.in";

/*
 *  Data structures for the W0RLI filing system.
 */

static struct { char letter;
         char path[80] ;
         char name[80] ;
         int  ok    ; }  root[32];
static int ne;

/* Copy file */

copyfile(filename,fp)
FILE *fp;
char *filename;
{
    int i, dn;
    char *st, *n1, *n2;
    FILE *datafile;
    char tmp[128];
    long nb, nl, ln;

    for(dn=0;((root[dn].letter!=toupper(*filename))&&(dn < ne));dn++)

    if( (dn == ne) || (root[dn].ok == 0) ) {
      fprintf(fp,"Directory Area %c: not found\n",*filename);
      return 1;
    }

    for(i=1;(ispunct(filename[i])||isspace(filename[i]));i++);

    for(n1 = filename+i;((*n1!=' ')&&(*n1!='\0'));n1++);
    if(*n1==' ') {
      *n1++ = '\0';
      while(*n1==' ') n1++ ; }
    for(n2 = n1;((*n2!=' ')&&(*n2!='\0'));n2++);
    if(*n2==' ') {
      *n2++ = '\0';
      while( *n2==' ' ) n2++; }

    nb = atol(n1);
    nl = atol(n2);

   if(nl==0) {
      if(nb==0) {
        nb = 1L;
        nl = 65535L; }
      else {
        nl = nb ;
        nb = 1 ; } }

    strcpy(tmp, root[dn].path);
    strcat(tmp, filename+i);

    fprintf(fp, "Full path: %s\n",tmp);

    if ((datafile = fopen(tmp, "r")) == NULL) {
       fprintf(fp,"File: %s not found \n", filename);
       return 1;
    }
    fprintf(fp, "Directory: %c: %s\n     File: %s",root[dn].letter,
            root[dn].name, filename +i);

    if ((atol(n1)!=0) && (atol(n2)==0))
      fprintf(fp, "   Lines 1 to %ld", nl);
    else if((atol(n2)!=0))
      fprintf(fp, "   Lines %ld to %ld",nb,nl);
    fprintf(fp, "\n\n");

    st = fgets(buf, ln_buf, datafile) ;
    ln = 1L;
    while (st != NULL)
    {
       if((nb<=ln)&&(ln<=nl)) fputs(buf, fp);
       st = fgets(buf, ln_buf, datafile);
       ln++;
    }
    fclose(datafile);
    return 0;
}

stripcr( line )
char *line;
{
  int i;
  for(i=1;i<strlen(line);i++)
    if(line[i]=='\n')
        line[i]='\0' ;
}
char *
skip(buf, fp)
char *buf;
FILE *fp;
{
  char *sts;
  sts = fgets( buf, ln_buf, fp);
  while( ((*buf == ';') || (*buf == '\n')) && (sts != NULL))
    sts = fgets(buf, ln_buf, fp) ;
  return sts;
}

int getdirs()
{
  FILE *fp;
  int n;
  char *st;

  if((fp = fopen(datfile, "r")) == NULL) return -1;

/*
 *  Skip the first section of the config file.
 */

  st = fgets(buf, ln_buf, fp);

  while ( (strncmp(buf, "***", 3)) && (st != NULL))
     st = fgets(buf, ln_buf, fp);
/*
 *  Read the files section (three lines per entry)
 */

  st = skip(buf, fp);
  n=0;
  while( (strncmp(buf, "***", 3)) && (st != NULL)) {

/*
 *  Extract parameters
 */
    root[n].letter = toupper(*buf);
/*    if( index(buf, "D") > -1 || index(buf, "d") > -1 ) 
*/      root[n].ok = 1;
/*    else
      root[n].ok = 0; 
*/      st = skip(buf, fp);
      if (!strncmp(buf, "***",3) || (st == NULL)) return -1;
      strcpy(root[n].path, buf);
    stripcr(root[n].path);

    st = skip(buf, fp);
    if ((!strncmp(buf, "***", 3)) || (st == NULL)) return -1;
    strcpy(root[n].name, buf);
    stripcr(root[n].name);

    st = skip(buf, fp);
    n++;
  }
  fclose(datfile);
  return n;
}

void
doroot(fp)
FILE *fp;
{
  int dn;

  fputs("Directories Available:\n",fp);
  if( ne == 0 )
    fputs("None!\n",fp);
  else
    for(dn=0;dn<ne;dn++)
      fprintf(fp, "%c: %s\n",root[dn].letter, root[dn].name);
}

getdir( fp, name )
char *name;
FILE *fp;
{
  struct ffblk *fbuf;

  if( findfirst( name, fbuf, 0xFFFF ) == 0 )
	printf("%12s %8ld\n", fbuf->ff_name, fbuf->ff_fsize);
  while( findnext( fbuf ) == 0)
	printf("%12s %8ld\n", fbuf->ff_name, fbuf->ff_fsize);
}

dodir(path,fp)
FILE *fp;
char *path;
{
  char tmp[128];
  int dn;
  char dc;

  dc = toupper(*path++);
/*  while (*path && !isalpha(*path)) path++ ;
*/
  for(dn=0;((root[dn].letter!=dc)&&(dn < ne));dn++) ;

  if(dn>=ne) {
    if (isalpha(dc))
      fprintf(fp, "Directory Area: %c not found\n",dc);
    else
      doroot(fp);
    return 0; }

  fprintf(fp, "Directory Listing of  %c: %s\n\n",dc, root[dn].name);
  strcpy(tmp, root[dn].path);
/*  if (*path) strcat(tmp, path) ;
  else */
  strcat(tmp,"*.*");

  if (getdir(tmp,fp))
    fprintf(fp,"Path: %s not found",tmp);
  fprintf(fp,"\n");
  return 0;
}

void
rfc822(from, to, subject, fp)
char *from, *to, *subject;
FILE *fp;
{
  fprintf(fp, "From: %s", from);
  fprintf(fp, "To: %s", to);
  fprintf(fp, "Subject: Files Cmd: %s", subject);
  fputs("\n", fp);
}

main(argc, argv)
int argc;
char *argv[];
{
  FILE *in, *out;
  char *st, *tail, *fname, *ptr, from[32], to[32], subject[64] ;
  int n, ok;

/*
 *   Open and read the initialisation file: reqxxx.dat in the root directory
 */
  ok = 0;
  puts(copyright);

/*
 *  Initialise the Filing Database
 */

  if ((ne = getdirs()) == -1) {
    printf("FILES: Unexpected end of file in: %s\n", datfile);
    exit(1);
  }

/*
 *  Open the input file.
 *  If not possible, exit with return code 1 to signal
 *  the MailBox that the server failed.
 */

  if ((in = fopen(infile, "r")) == NULL) exit(1);

/*
 *  Open the output file.
 *  If not possible, exit with return code 1 to signal
 *  the MailBox that the server failed.
 */

  if ((out = fopen(outfile, "w")) == NULL) exit(1);

  st = fgets(buf, ln_buf, in);
  while (st != NULL)
  {

/*
 *  Read the rfc-822 header placed into the message by the MailBox.
 *  The end of header is marked by a blank line.
 */

    while(*buf != '\n')
    {

/*
 *  Find end of keyword.
 *  Terminate string at end of keyword.
 */

      tail = strchr(buf, ' ');
      *tail++ = '\0';

/*
 *  Make the new rfc-822 header.
 */

      if      (!strcmp(buf, "To:"))      strcpy(from, tail);
      else if (!strcmp(buf, "From:"))    strcpy(to, tail);
      else if (!strcmp(buf, "Subject:")) {
                strcpy(subject, tail);
		strcpy( fname, tail); }
      st = fgets(buf, ln_buf, in);
    }

/*
 *  Now that the rfc-822 header has been read, and a new one created,
 *  copy the text of the message from the input to the output.
 */
    stripcr(fname) ;

    if( toupper(*fname) == 'W' ) {
      rfc822(from, to, subject, out);
      dodir(fname+1, out);
      fputs(mark, out);
      ok = 1; }
    else if (toupper(*fname) == 'D' ) {
      rfc822(from, to, subject, out);
      copyfile(fname+1,out) ;
      fputs(mark, out);
      ok = 1; }

    while ((st != NULL) && stricmp(buf, mark))
    {
      st = fgets(buf, ln_buf, in);
      if( toupper(*buf) == 'W' ) {
        strcpy(subject, buf);
        stripcr(buf);
        rfc822(from, to, subject, out);
        dodir(buf+1, out);
        fputs(mark, out); 
        ok = 1; }
      else if (toupper(*buf) == 'D' ) {
        strcpy(subject, buf);
        stripcr(buf);
        rfc822(from, to, subject, out);
        copyfile(buf+1,out) ;
        fputs(mark, out);
        ok = 1; }
    }
    if( !ok ) {
      rfc822(from, to, "NONE\n", out);
      fputs("FILES: No valid command found in Subject or Message\n", out);
      fputs(mark, out); }

/*
 *  Go on to the next message.
 */

    if (st != NULL) st = fgets(buf, ln_buf, in);
  }

/*
 *  All the incoming messages have been processed,
 *  and an outgoing message created for each one.
 */

  fclose(in);
  fclose(out);

/*
 *  Delete the input file.
 *  The MailBox appends messages to this file, this server must delete it.
 */

  unlink(infile);

/*
 *  Exit with return code 0 to signal the MailBox that
 *  the server completed it's processing normally.
 *  The MailBox will then read our output file,
 *  and create messages from it.
 */

  exit(0);
}
