/* Yapp.c   YAPP protocol for FBB forwarding in CBBS.

   Copyright Peter Hardie VE5VA  1993

*/

#include "mb.h"



#define NUL 0
#define SOH 1
#define STX 2
#define EOT 4
extern unsigned char rdchar();
extern short debug;
/* rflag is in ser.c. It indicates, when on that rdchar should not start
   the next I/O
*/
extern short rflag;
/* rdblock reads a block of the specified number of bytes into the buffer.
   If the length is specified as -1 then a null terminated string is read.
   If rdblock returns non-zero then it has failed.
*/
long tempcount;   /* Actually only used in debugging */
extern unsigned long textsize;
extern char fbb_flag,tmpstr[];
short buf_index;
short buf_num;
short huf_error;
short yapp_eot;
short block_cancel = 0; /* Set to one by i/o routine if SYSOP hits ^F */
short checksum;
unsigned char *yapp_buf;
extern short restart_done;
char *out_buf_adr;        /* output buffer */
char *in_buf_adr;         /* input buffer */
short out_index;
extern FILE *infl;
FILE *tfl,*ofl;
snd_yapp()
{
   register char *q;
   register PORTS *p;
   register FILE *fl;
   register int i;

   restart_done = 0;
   block_cancel = 0;
   p = port;
   sprintf(p->line, "%s%u", msgdir, port->mmhs->number);
   if((fl = fopen(p->line, "rb")) is NULL) {
      printf("Can't find input file %s\n",p->line);
      return(1);
   }
   if((infl = fopen("t:fbb.tmp","w+b")) == NULL) {
      printf("Can't create temporary  file t:fbb.tmp\n");
      fclose(fl);
      return(2);
   }
   /* Initialize output buffer */
   out_index = 0;
tempcount = 0;
   /* send the title */
   puthuf(SOH);
   puthuf(0);     /* Filled in later as length of data */
   q = p->mmhs->title;
   ttputs("Sending Compressed Msg - title:\n");
   ttputs(q);
   ttputs("\n");
   while(*q && (*q != '\n'))puthuf(*q++);
   puthuf(0);
   puthuf('0');   /* Offset length is always zero */
   puthuf(0);
   closehuf();    /* Force transmission of the header */
   /* Now, while that is being sent, we have a bit of time to create a
      temporary file containing the processed message so that we can find
      its true length with LF replaced by CR/LF and my R: header.
      I have to replace LF by CR/LF anyway because IBM systems expect
      it. If we are talking to another C-BBS it will remove those idiotic
      CRs.
      This whole process is done not just so that I can find the length
      of the message (in which case the file wouldn't be needed), but also
      because the encoding algorithm provided in the FBB distribution
      requires a file descriptor as input and I haven't got around to
      making it work without one.
   */
   curtim();
   fbb_flag = 1;
   prtx(mm[4]);
   fbb_flag = 0;
   q = tmpstr;
   fputs(tmpstr,infl);
   fseek(fl, (long)RECSIZE, 0);
if(debug)tfl = fopen("t:fbb.xmt","wb");
   while(fgets(tmp->scr, scrmax, fl) isnt NULL) {
      if (chkdis()) {
if(debug)fclose(tfl);
         fclose(fl);
         fclose(infl);
         return(3);
      }
      q = tmp->scr;
      while(*q && (*q != '\n'))q++;
      *q++ = '\r';
      *q++ = '\n';
      *q = 0;
      fputs(tmp->scr,infl);
   }
   fclose(fl);
   rewind(infl);
   checksum = 0;
   /* This test for cmpok is only really necessary if I have also
      implemented the lzc routine. At the moment, I haven't.
   */
   if(s_mart & cmpok) {
      i = Encode();
   }
#ifdef MCH_ZOO
   else {
      i = lzc();
   }
#endif
   if(i) {
      ttputs("Problem in encode or console abort\n");
      fclose(infl);
if(debug)fclose(tfl);
      return(4);
   }
   /* Send EOT and checksum */
   out_index = 0;
   i = checksum;
   puthuf(EOT);
   puthuf((-i)&0xff);
   sendblock(out_buf_adr,2);
   fclose(infl);
/* unlink("t:fbb.tmp"); */
   ttputs("File Sent\n");
if(debug)fclose(tfl);
   return(0);
}

rcv_yapp(infile)
char *infile;
{
   register int i;
   register PORTS *p;
   register char *q;
   char *r;
   unsigned char offset[10],c;
   unsigned char intitle[200];

   restart_done = 0;
   block_cancel = 0;
   yapp_eot = 0;
   p = port;
   out_index = 0;
   checksum = 0;
   if((p->fl = fopen(infile, "wb")) is NULL) {
      p->msg = mcant;
      return(1);
   }
   fill(tmp->scr, '.', RECSIZE);
   fwrite(tmp->scr,256,1, p->fl);
   /* First, read the header information */
   rflag = 1;
   if((i = rdchar()) != SOH) {
      printf("No SOH at start of compressed forward - %02x\n",i);
err_exit:
      fclose(p->fl);
      unlink(infile);
      restart();
      return(1);
   }
   /* Get the message header length */
   if(rdblock(&c,1))goto err_exit;
if(debug) {
   sprintf(tmpstr,"Length = %d\n",c);
   ttputs(tmpstr);
}
/*   if(rdblock(p->mmhs->title,-80))return(1);*/
/* FBB can blow up and send a title longer than 80 characters
   So this code reads a long title into a temporary string and then
   copies only, at most, 79 characters into the title string
*/
   if(rdblock(intitle,-195))goto err_exit;
   strncpy(p->mmhs->title,(char *)intitle,79);
t_stamp();
   ttputs("Receiving compressed message - title:\n");
   ttputs(p->mmhs->title);
   ttputs("\n");
/* At the moment this is ignored even by FBB.
   Not any longer. FBB now implements a protocol which allows the
   transmission of part of a file starting from where the message was
   interrupted.
   I haven't implemented this and indicate to FBB that I don't do it,
   so this next block is irrelevant.
*/
   if(rdblock(&offset[0],-8))goto err_exit;
if(debug)ofl = fopen("t:fbb.rcv","wb");
   huf_error = 0;
   buf_index = 257;
   buf_num = 0;
   filesize = 0;
tempcount = 0;
   if(s_mart & cmpok) {
      i = Decode();
   }
#ifdef MCH_ZOO
   else {
      i = lzd();
   }
#endif
   if(i) {
      fclose(port->fl);
      unlink(infile);
t_stamp();
      ttputs("Decoding error or console abort\n");
      return(1);
   }
   fclose(p->fl);
   if(!yapp_eot) {
if(debug)fclose(ofl);
      if(rdblock(&c,1))return(1);
      restart();
      if(c != EOT) {
t_stamp();
         printf("EOT not found - %02x\n",c);
/*         unlink(infile);*/
         return(1);
      }
if(debug)printf("OTHER_EOT\n");
   }

   checksum += rdchar();
   if(checksum & 0xFF) {
t_stamp();
      printf("Checksum error in FBB compressed forward\n");
      unlink(infile);
      return(1);
   }
   ttputs("Done\n");
   return(0);
}
/* Somehow I have to modify this routine so that if it sees
   *** DISCO
   it will return an error and cause the whole forward to come to a crashing
   halt.
*/
unsigned char gethuf()
{
   register int i;
   register unsigned char *q;
   unsigned char c;

   if(yapp_eot)return(0);
   if(buf_index >= buf_num) {
      if(rdblock(&c,1) || (c == EOT)) {
         restart();
if(debug) {
  printf("YAPP-EOT\n");
  fclose(ofl);
}
         yapp_eot = 1;
         return(0);
      }
      if(c != STX) {
         restart();
         huf_error = 1;
         printf("Missing STX in compressed forward - %02x\n",c);
         return(0);
      }
      buf_index = 0;
      if(rdblock(&c,1)) {
         restart();
if(debug) {
  printf("YAPP-LEN-ERROR\n");
  fclose(ofl);
}
         huf_error = 1;
         yapp_eot = 1;
         return(0);
      }
      buf_num = c;
      if(buf_num == 0)buf_num = 256;
      if(rdblock(yapp_buf,buf_num)) {
         restart();
if(debug) {
  printf("YAPP-BLK-ERROR\n");
  fclose(ofl);
}
         huf_error = 1;
         yapp_eot = 1;
         return(0);
      }
if(debug) {
  fwrite(yapp_buf,buf_num,1,ofl);
  tempcount++;
  printf("Got %3ld length = %d\n",tempcount,buf_num);
}
      q = yapp_buf;
      i = buf_num;
      do {
         checksum += *q++;
      } while(--i);
   }
if(s_mart & zoook)putc(*(yapp_buf+buf_index),stdout);
   return(*(yapp_buf+buf_index++));
}
putdec(cc)
int cc;
{
   register unsigned char c;
   c = cc&0xff;
   if(c != '\r') {
      *(out_buf_adr + out_index++) = c;
      filesize++;
      if(out_index == 256) {
         fwrite(out_buf_adr,256,1,port->fl);
         out_index = 0;
      }
   }
}
closedec()
{
   if(out_index) {
      fwrite(out_buf_adr,out_index,1,port->fl);
      out_index = 0;
   }
}
puthuf(cc)
int cc;
{
   register unsigned char c;
   c = cc & 0xff;
   checksum += c;
   *(out_buf_adr + out_index++) = c;
   if(out_index == 251) {
      *(out_buf_adr + 1) = out_index - 2;
      out_index = 2;
if(debug) {
  fwrite(out_buf_adr+2,249,1,tfl);
  printf("Put %3ld length = 249\n",tempcount++);
}
      return(sendblock(out_buf_adr,251));
   }
   return(0);
}
closehuf()
{
   register int i;

   if(out_index > 2) {
      *(out_buf_adr + 1) = out_index - 2;
      sendblock(out_buf_adr,out_index);
if(debug) {
  fwrite(out_buf_adr+2,out_index-2,1,tfl);
  printf("Put %3ld length = %d\n",tempcount++,out_index-2);
}
      out_index = 2;
      *out_buf_adr = STX;
   }
}
