/************************************************************************
 *
 *       HD6PRI.C 	Superkermit protocol modules and primitives.
 *
 ***********************************************************************/  
 
#include "hd6ker.h"
 
/*
 *     r d a t a
 *
 *     Receive data
 *     The receiving of file attribute packets is handled in this module!
 *
 */
 
char rdata()
{
    int num, len;                     /* Packet number, length */
    unsigned int j;
    unsigned int k_size = 0;
    char *bufp, *start, c, d;             /* attribute pointers */
    float byte_size;
    double byte_sz, atof();
    char filnam1[50];                   /* Holds the converted file name */
 
    if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
 
    switch(rpack(&len,&num,packet))     /* Get packet */
    {
 
 /* code added to ACK and use attrib packets if received [FRANK DREANO] */
 
          case 'A':
              if (num != n) {             /* Right packet number or not */
                 if (oldtry++ > MAXTRY)
                    return('A');          /* too many retries, abort */
              if (num == ((n==0) ? 63:n-1))  {  /* duplicate ? */
                 spack('Y',num,0,xnull);   /* Yes, re-ACK it */
                 numtry = 0;              /* Reset try counter */
                 return(state);           /* stay in this state */
                 }
              else return('A');
              }
           /* got the right attrib packet */
              spack('Y',n,0,xnull);       /* ACK the attribute */
              oldtry = numtry;            /* Reset try counters */
              numtry = 0;                 /* Reset try counter */
              n = (n+1)%64;               /* bump packet counter */
 
          bufp = packet;
          while ((*bufp) != '\0') { /* process the attributes */
             switch(*bufp++) {
              case '1':
                    d = *bufp;
                    j = (*bufp) - ' ';
                    *bufp = '+';
                    start = bufp; byte_sz = 0;
                    bufp = ++bufp + j;
                    c = *bufp;
                    *bufp = ' ';   /* terminate flting point string */
                    byte_sz = atof(start);
                    if (debug)
                      fprintf(dfp,"\nThe file size is: %7.f bytes.\n", byte_sz);
                    *bufp = c;
                    *start = d;
                    break;
              case '#':   /* just eat all other non-file size attribs */
              case '.':
                    j = (*bufp++) -  ' ';
                    bufp = bufp + j;
                    break;
              case '!':
                    j = (*bufp++) -  ' ';
                    start = bufp; k_size = 0;
                    bufp = bufp + j;
                    c = *bufp;
                    *bufp  = '\0'; /* terminate integer string */
                    k_size = atoi(start);
          if (debug) fprintf(dfp,"\nThe file size is: %u Kilobytes.\n", k_size);
                    *bufp = c;
                    break;
               default:
                   j = (*bufp++) -  ' ';
                   bufp = bufp + j;
          if (debug) fprintf(dfp,"\nThe attribute is not recognized.");
                   break;
               } /* end switch */
           } /* end while */
 
  /* got the incoming file size lets make contiguous efficient space */
  
              if ((k_size == 0) && (byte_sz != 0)) 
                  k_size = byte_sz / 1000;
              k_size = 32 * ((k_size + 32 - 1)/32); /* round out */    
              k_size = k_size * 2;
              getfiles[49] = 0;
              strcpy(filnam1, getfiles);     /* Copy filename */
              if (k_size > 64) {
                  if (debug) fprintf(dfp,"\nCI growth size is: %u.\n", k_size);
                  fclose(fp);
                  sprintf(cmdstg,">SYSLIB2>MFA %s -GRSZ %u ", filnam1, k_size);
                  if ((cmdstat = system(cmdstg)) != 0)
              fprintf(stderr,"\nCould not modify <%s> growth size.", filnam1);
              if ((fileimage == FOREIGN) || (fileimage == BINARY)) 
                  fp = fopen(filnam1,"ab");
                  else
                    fp = fopen(filnam1, "a");
                  } /* end if */
                 
          if (fileimage == FOREIGN) {  /* stuff the attributes in the files */
                sprintf(cmdstg,"%s\n",packet);
                fputs(cmdstg, fp);
                }  
 
      /* end of attribute decoding and use [FRANK DREANO] */
 
              return('D');                /* stay in this state */
 
          case 'D':                       /* Got Data packet */
              if (num != n)               /* Right packet? */
              {                           /* No */
                    if (oldtry++ > MAXTRY)
                        return('A');        /* If too many tries, abort */
                    if (num == ((n==0) ? 63:n-1)) { /* duplicate?   */
                        spack('Y',num,0,xnull); /* Yes, re-ACK it    */
                        numtry = 0;         /* Reset try counter    */
                        return(state);      /* Don't write out data! */
                    }
                    else return('A');       /* sorry, wrong number */
              }
 
              /* Got data with right packet number */
              if ( (num = decode(packet,len)) != 0 ) {
                    error("Trouble writing file, OS code %xx",num);
                    return('A');
              }
              spack('Y',n,0,xnull);           /* Acknowledge the packet */
              n = (n+1)%64;               /* Bump packet number, mod 64 */
              oldtry = numtry;            /* Reset the try counters */
              numtry = 0;                 /* ... */
              return('D');                /* Remain in data state */
 
          case 'F':                       /* Got a File Header */
              if (oldtry++ > MAXTRY)
                    return('A');            /* If too many tries, "abort" */
              if (num == ((n==0) ? 63:n-1)) /* Else check packet number */
              {                           /* It was the previous one */
                    spack('Y',num,0,xnull);     /* ACK it again */
                    numtry = 0;             /* Reset try counter */
                    return(state);          /* Stay in Data state */
              }
              else return('A');           /* Not previous packet, "abort" */
 
          case 'Z':                       /* End-Of-File */
              if (num != n) return('A');  /* Must have right packet number */
              spack('Y',n,0,xnull);           /* OK, ACK it. */
              fflush(fp);                 /* Flush all buffers */
              fclose(fp);                 /* Close the file */
              fp = NULL;
              
       /* if attributes were used shrink file then reset growth size */
  
            if ((senda) && (sattrib)) {
                  sprintf(cmdstg,">SYSLIB2>SHRINK %s", filnam1);
                  system(cmdstg);
                  sprintf(cmdstg,">SYSLIB2>MFA %s -GRSZ 20", filnam1);
                  if ((cmdstat = system(cmdstg)) != 0)
              fprintf(stderr,"\nCould not reset <%s> growth size.", filnam1);
              }
 
              if (debug) {
                 if ( (len != 0) && (*packet == 'D') )
                fprintf(dfp, "\nFile <%s> truncated by local Kermit\n",filnam);
                    else
                       fprintf(dfp,"\nFile <%s> received OK\n",filnam1);
                 }
              n = (n+1)%64;               /* Bump packet number */
              return('F');                /* Go back to Receive File state */
 
          case 'E':                       /* Error packet received */
              prerrpkt(packet);           /* Print it out and */
              return('A');                /* abort */
 
          case FALSE:                     /* Didn't get packet */
              spack('N',n,0,xnull);           /* Return a NAK */
              return(state);              /* Keep trying */
 
          default:
              error(badpack,prompt,type);
              return('A');       /* Some other packet, "abort" */
    }
}                       /* End of rdata()               */
 
 
/*
 *     r f i l e
 *
 *     Receive file header
 *
 */
 
char rfile()
{
    int num, len;                       /* Packet number, length */
    char filnam1[50];                   /* Holds the converted file name */
 
    if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
 
    switch(rpack(&len,&num,packet))     /* Get a packet */
    {
 
          case 'S':                       /* Send-Init, maybe our ACK lost */
              if (oldtry++ > MAXTRY) return('A'); /* If too many tries "abort" */
              if (num == ((n==0) ? 63:n-1)) { /* Previous packet, mod 64? */
                    len = spar(packet);           /* our Send-Init parameters */
                    spack('Y',num,len,packet);
                    numtry = 0;             /* Reset try counter */
                    return(state);          /* Stay in this state */
              }
              else return('A');           /* Not previous packet, "abort" */
 
          case 'Z':                       /* End-Of-File */
              if (oldtry++ > MAXTRY) return('A');
              if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */
              {                           /* Yes, ACK it again. */
                    spack('Y',num,0,xnull);
                    numtry = 0;
                    return(state);          /* Stay in this state */
              }
              else return('A');           /* Not previous packet, "abort" */
 
          case 'F':                       /* File Header (just what we want) */
              if (num != n) return('A');  /* The packet number must be right */
              decfil(packet, getfiles, len);  /* 'unrepeat' filename */
              getfiles[49] = 0;              /* terminate the string */
              strcpy(filnam1, getfiles);     /* Copy filename */
 
              if (filnamcnv) {            /* Convert upper case to lower */
                    for (filnam=filnam1; *filnam != '\0'; filnam++)
                        if (*filnam >= 'A' && *filnam <= 'Z')
                              *filnam |= 040;
                    filnam = filnam1;
              } 
      /* should have gotten a file attribute packet instead */
 
/*  if ((fileimage == FOREIGN) && ((senda == FALSE) || (sattrib == FALSE))) {
       error(noattrib, prompt);
       return('A');
       }  */
               for (filnam=filnam1; *filnam != '\0'; filnam++)
               if (*filnam == ',') {
                  *filnam++ = '\0'; 
 			      *filnam = '\0'; 
			      break;
			      } /* end for */
               filnam = filnam1;
 
       if ((fileimage == BINARY) || (fileimage == FOREIGN)) {  
 
              /*  create and open binary/foreign type file  */
 
               if (debug) fprintf(dfp,
                             "\nDeleting <%s> if it exists.",filnam1);
                 sprintf(cmdstg,">SYSLIB2>DL %s -BF", filnam1);
 
               if ( ((cmdstat = system(cmdstg)) !=0) && (debug) )
                    fprintf(dfp,
                         "\nFile not deleted; as it did not already exist.");
               cmdstat = 0;
         if (fileimage == BINARY)
      sprintf(cmdstg, ">SYSLIB2>CR %s -F_REL -LRSZ %d -SZ 0", filnam1, lrsz_6);
         if (fileimage == FOREIGN)
      sprintf(cmdstg, ">SYSLIB2>CR %s -SEQ -DATA_CODE BINARY -SZ 0", filnam1);
                 
               if ((cmdstat = system(cmdstg)) != 0) {
                     syserr("system");
                     return('A');
                     } /* end if */
              if (debug) fprintf(dfp,"\nOpening <%s> for receiving.",filnam1);
              fp=fopen(filnam1,"ab");
              } /* end if */
 
              else {         /* open ASCII type file  */
                   if (dlflag) {  /* overwrite existing file if flag set */
                       if (debug) fprintf(dfp,
	      	                    "\nDeleting <%s> if it exists.",filnam1);
                       sprintf(cmdstg,">SYSLIB2>DL %s ", filnam1);
                       if ( ((cmdstat = system(cmdstg)) !=0) && (debug) )
               fprintf(dfp,"\nFile not deleted; as it did not already exist."); 		
                       }  /* end if */
                   if (debug) fprintf(dfp,
                                 "\nOpening <%s> for receiving.",filnam1);
                   fp=fopen(filnam1,"a");
                   } /* end else */
 
              if (fp == NULL) {
                    error("%sCannot create <%s>",prompt,filnam1);
                    return('A');
                    } /* end if */
                    else                        /* OK, give message */
                    if (debug) fprintf(dfp,"\nReceiving %s as %s",packet,filnam1);
                    
  /* stuff dummy attribute in foreign file if the PC didn't send any */
  
  if ((fileimage == FOREIGN) && ((senda == FALSE) || (sattrib == FALSE))) 
              fputs(",I\n", fp);
 
              spack('Y',n,0,xnull);       /* Acknowledge the file header */
              oldtry = numtry;            /* Reset try counters */
              numtry = 0;                 /* ... */
              n = (n+1)%64;               /* Bump packet number, mod 64 */
              return('D');                /* Switch to Data state */
 
          case 'B':                       /* Break transmission (EOT) */
              if (num != n) return ('A'); /* Need right packet number here */
              spack('Y',n,0,xnull);           /* Say OK */
              if (debug) fprintf(dfp,"All files received\n");
              return('C');                /* Go to complete state */
 
          case 'E':                       /* Error packet received */
              prerrpkt(packet);           /* Print it out and */
              return('A');                /* abort */
 
          case FALSE:                     /* Didn't get packet */
              spack('N',n,0,xnull);           /* Return a NAK */
              return(state);              /* Keep trying */
 
          default:
              error(badpack,prompt,type);
              return ('A');       /* Some other packet, "abort" */
    }
}                       /* End rfile()                  */
 
/*
 *     r i n i t
 *
 *     Receive initalization
 *
 */
 
char rinit()
{
    int len, num;                       /* Packet length, number */
    bctu = 1;      /* type-1 blk chk at first */
    if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */
 
    switch(rpack(&len,&num,packet))     /* Get a packet */
    {
          case 'S':                       /* Send-Init */
              rpar(packet,len);
              len = spar(packet);
              spack('Y',n,len,packet);      /* ACK with my parameters */
              oldtry = numtry;            /* Save old try count */
              numtry = 0;                 /* Start a new counter */
              n = (n+1)%64;               /* Bump packet number, mod 64 */
              bctu = bctr;                /* use agreed blk chk type */
              return('F');                /* Enter File-Receive state */
 
          case 'E':                       /* Error packet received */
              prerrpkt(packet);           /* Print it out and */
              return('A');                /* abort */
 
          case 'I':                       /* Init-parameters      */
              rpar(packet,len);
              len = spar(packet);
              spack('Y',n,len,packet); /* ack with our parameters */
              n = (n+1)%64;               /* Bump packet number, mod 64 */
              bctu = bctr;                /* use agreed block check type */
              return(state);              /*  & continue          */
 
          case FALSE:                     /* Didn't get packet */
              spack('N',n,0,xnull);           /* Return a NAK */
              return(state);              /* Keep trying */
 
          default:
              error(badpack,prompt,type);
              return('A');       /* Some other packet type, "abort" */
    }
}                       /* End rinit()                          */
 
/*
 *     r p a c k
 *
 *     Read a packet
 *     Modified for extended packets [FRANK DREANO]
 */
 
rpack(len,num,data)
int *len, *num;                         /* Packet length and number */
char *data;                             /* Packet data */
{
    int j,i,done,k,s;            /* Data character number, loop exit */
    register char *bufp, *datap;            /* 'fast' array indexes */
    int maxlx1, maxlx2;                   /* extended packet length */
    unsigned char pcb[4];                /* block check char array */
    char  t,                               /* Current input character */
          rlongp,                        /* extended packet flag */
          buffer[MAXPACKSIZ + 6];                /* area to do CRC block checks */
 
    timoset(timint);         /* set timeout                     */
/* The way timeouts are handled is that the flag stays clear, indicating
          that a timeout has occurred, until it is set to a value again
          by the next call to timoset().  This means that the effect can
          run up thro' the procedures without using longjmp().    */
 
    rlongp = FALSE;
    t = 0;
    *len = 0;                           /* in case times out    */
    while (t != SOH) {                  /* Wait for packet header */
          t = cread() & (char)0x7f;
    }
    timocan();
    done = FALSE;                       /* Got SOH, init loop */
    while (!done)                       /* Loop to get a packet */
    {
          t = cread();                  /* Get character */
          if (t == SOH) continue;       /* Resynchronize if SOH */
          bufp = buffer;                /* init buffer pointer */
          *bufp++ = t;                  /* Start the checksum */
          *len = unchar(t) - bctu - 2;  /* Character count */
          if (*len == -(bctu+2)) rlongp = TRUE;    /* long packets */
 
          t = cread();                  /* Get character */
          if (t == SOH) continue;       /* Resynchronize if SOH */
          *bufp++ = t;                  /* Update checksum */
          *num = unchar(t);             /* Packet number */
 
          t = cread();                  /* Get character */
          if (t == SOH) continue;       /* Resynchronize if SOH */
          *bufp++ = type = t;           /* Update checksum */
/* extended packet modifications [FRANK DREANO] */
          if (rlongp == TRUE) {
 
             t = cread();
             if (t == SOH) continue;
             *bufp++ = maxlx1 = t;      /* Get extended length */
 
             t = cread();
             if (t == SOH) continue;
             *bufp++ = maxlx2 = t;      /* Get extended length */
 
             t = cread();
             if (t == SOH) continue;
/* got all of extended packet header; do checksum and length computes */
             *bufp = '\0';
             if (t != tochar(chk1(buffer))) {     /* compute hdr sum */
             if (debug)
                fprintf(dfp,
                    "\nExtended hdr chksum error: rec'd %xx computed %xx;",
                                               t, tochar(chk1(buffer)));
                return(FALSE);
                } /* end if */
             *bufp++ = t;
             *len = unchar(maxlx1) * 95 + unchar(maxlx2) - bctu;
             } /* end if */
 
          datap = data;
          for (i=0; i<*len; i++) {           /* The data itself, if any */
              t = cread();                   /* Get character */
              if (t == SOH)
                    break;                   /* Resynch if SOH */
              *bufp++ = *datap++ = t;        /* Update checksum */
          }
          if (t == SOH)
              continue;
          *bufp = *datap = '\0';             /* Terminate the strings */
 
/*  At this point the data for an entire packet should have been read in    */
/*  so print it and do the block checks...type 1, 2, or 3.  [FRANK DREANO]  */
 
    if (debug) fprintf(dfp,"\n Packet %d received; ",*num);
    if (debug>1) {                       /* Display incoming packet */
          fprintf(dfp," type: %c;",type);
          fprintf(dfp," num:  %d;",*num);
          fprintf(dfp," len:  %d.",*len);
          if (*len != 0) {
          j = 0;
              while (j < *len) {
                 fprintf(dfp,"\n  data: <");
                 i=0;
                 while ((i < 60 ) && (j < *len)) {
                       putc(data[j++],dfp);
                       i++;
                       } /* end while */
                 putc('>',dfp);
}   }   }
 
       for (s=0; s<bctu; s++) {   /* get all of the block check characters */
           t = cread();
           if (t == SOH) break;    /* Get out of loop if SOH */
           pcb[s] = t;
           } /* end for */
 
       if (t == SOH) continue;     /* Resynch if SOH */
       pcb[s] = '\0';              /* terminate the string */
       done = TRUE;                /* I have now read EVERYTHING ! */
       } /* end outermost while */
 
       switch (bctu) {
           case 1:
               if (unchar(*pcb) != chk1(buffer)) {
                  if (debug)
                     fprintf(dfp,"\n bad checksum: rec'd %xx computed %xx; ",
                                  unchar(*pcb), chk1(buffer));
                  return(FALSE);
               } /* end if */
               break;
           case 2:
               s = unchar(*pcb) << 6;
               s = s | unchar(pcb[1]);
               if (s != chk2(buffer)) {
                   if (debug)
                     fprintf(dfp,"\n bad checksum: rec'd %xx computed %xx; ",
                                   s, chk2(buffer));
                   return(FALSE);
               } /* end if */
               break;
           case 3:
               s = unchar(*pcb) << 12;
               s = s | unchar(pcb[1]) << 6;
               s = s | unchar(pcb[2]);
               if (s != chk3(buffer)) {
                   if (debug)
                     fprintf(dfp,"\n bad checksum: rec'd %xx computed %xx; ",
                                   s, chk3(buffer));
                  return(FALSE);
               } /* end if */
               break;
           default:
               if (debug)
                  fprintf(dfp,"\n packet format is invalid");
               return(FALSE);
           } /* end switch */
 
    flushinput();
 
    return(type);                       /* All OK, return packet type */
}                               /* End of rpack()                       */
 
/*
 *     r p a r
 *
 *     Get the other side's send-init parameters
 *     Modified for extended packets [FRANK DREANO]
 */
 
rpar(data,len)
char    *data, len;
/* Set up incoming parameters to either what has been received
          or, if nil, to defaults.
  No return-code.                                               */
{
    char        p;
    int         olen,   /* original recv-init packet length */
                rpsiz;  /* remote's packet length */
 
    olen = len;
    spsiz = 80;                 /* send packet-length 80 chars   */
    timint = MYTIME;            /* timeout as defined           */
    eol = CR;                   /* terminator normally CR       */
    quote = '#';                /* standard control-quote char  */
    rptflg = FALSE;             /*  nor repeat-quoting          */
    sattrib = FALSE;            /* no attribute packets yet     */
 
    while (len-- > 0) {
          p = data[len];
 
          switch (len) {          /* for each parameter           */
 
            case 0:                       /* MAXL                     */
              rpsiz = unchar(p);
    /* loop goes backwards so set spsiz to what was negotiated */
              spsiz = (spsiz < 95) ? rpsiz : spsiz;
              break;
 
            case 1:                       /* TIME                 */
              timint = (unchar(p) < 5) ? 5 : unchar(p);
              break;
 
            case 2:                       /* NPAD                 */
              pad = unchar(p);
              break;
 
            case 3:                       /* PADC                 */
              padchar = ctl(p);
              break;
 
            case 4:                       /* EOL                  */
              eol = unchar(p);
              break;
 
            case 5:                       /* QCTL                 */
              quote = p;
              break;
 
            case 6:                       /* QBIN                 */
              if (image == 2) {
                    if (p == 'Y')
                        qu8 = '&';
                    else if (isalnum(p) == 0) /* provided punctuation */
                        qu8 = p;
                    else
                        image = 0;
                    break;
              }
              break;
 
            case 7:                       /* BLOCK CHECK TYPE */
               bctr = p - '0';
               bctr = (bctr < 1 || bctr > 3) ? 1 : bctr;
               break;
 
            case 8:                       /* REPT                 */
              if (p == '~')
               rptflg = TRUE;
              break;
 
  /* extended packet additions [FRANK DREANO]
     This routine sets 2 variables slongp = TRUE/FALSE for extended
     packets on/off and spsiz = negotiated packet length. */
 
            case 9:
            if (slongp == TRUE) {     /* did user ask for extended packets ? */
              if (((unchar(p) & 0x02)) == 0x02) {
                    spsiz = MAXPACKSIZ;  /* 2000 bytes */
                    rpsiz = 500;   /* set default extended packet length */
                    if (olen > 9)
                          rpsiz = unchar(data[11]) * 95 + unchar(data[12]);
                    /* set final negotiated size no matter what */
                    spsiz = (spsiz < rpsiz) ? spsiz : rpsiz;
                    if (debug)
                       fprintf(dfp,"\nExtended packets used size: %d.", spsiz);
                    } /* end if */
                    else
                       slongp = FALSE; /* turn extended packets off */
               } /* end if */          /* if CAPAS bit not set */
             if (((unchar(p) & 0x08)) == 0x08)  /* user likes attrib packets */
                    sattrib = TRUE;
              break;
 
            default:                      /* CHKT, CAPAS etc.     */
              break;
 
    }   }                       /* end while & outer switch     */
 
    if ( (qu8 == 0) && (image == 2) )   /* invalid tseting      */
          image = 0;
    if (debug) fprintf(dfp,
"\nParms recd in: Fileimage: %d, image: %d, q_char: %c, rptflg: %s, bchk: %d.",
fileimage,image,qu8,logicval[-rptflg],bctr);              
/*
"\nParms rec'd in: 8th-bit tseting is %d, char is %c, reptflag %s, chktype %d.",
image,qu8,logicval[-rptflg],bctr); */
    return;
}                       /* End of rpar()                        */
 
/*
 *     s b r e a k
 *
 *     Send break (EOT)
 *
 */
 
char sbreak()
{
    int num, len;                       /* Packet number, length */
    if (numtry++ > MAXTRY) return('A'); /* If too many tries "abort" */
 
    spack('B',n,0,packet);              /* Send a B packet */
    switch (rpack(&len,&num,recpkt))    /* What was the reply? */
    {
          case 'N':                       /* NAK, just stay in this state, */
              num = (--num<0 ? 63:num);   /* unless NAK for previous packet, */
              if (n != num)               /* which is just like an ACK for */
                    return(state);        /* this packet so fall thru to... */
 
          case 'Y':                       /* ACK */
              if (n != num) return(state); /* If wrong ACK, fail */
              numtry = 0;                 /* Reset try counter */
              n = (n+1)%64;               /* and bump packet count */
              return('C');                /* Switch state to Complete */
 
          case 'E':                       /* Error packet received */
              prerrpkt(recpkt);           /* Print it out and */
              return('A');                /* abort */
 
          case FALSE: return('C');        /* Receive failure, count as OK */
/* If timed out or etc. when completing, likely other end has gone away */
 
          default:
              error(badpack,prompt,type);
              return ('A');       /* Other, "abort" */
   }
}                       /* End sbreak()                         */
 
/*
 *     s d a t a
 *
 *     Send file data
 *
 */
 
char sdata()
{
    int num, len;   					/* Packet number, length */
 
    if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
 
    spack('D',n,size,packet);
    switch(rpack(&len,&num,recpkt))     /* What was the reply? */
    {
          case 'N':                       /* NAK, just stay in this state, */
              num = (--num<0 ? 63:num);   /* unless it's NAK for next packet */
              if (n != num)               /* which is just like an ACK for */
                    return(state);          /* this packet so fall thru to... */
 
          case 'Y':                       /* ACK */
              if (n != num) return(state); /* If wrong ACK, persist */
              numtry = 0;                 /* Reset try counter    */
              n = (n+1)%64;               /* Bump packet count    */
              if (len != 0) switch (*recpkt) {   /* ACK has data */
                case 'Z':                         /* cancel all   */
                case 'z':
                    filecount = 0;                 /* no more to go */
                case 'X':                         /* cancel file  */
                case 'x':
                    return('Z');
                default:                          /* invalid      */
                    if (!senda) {               /* Attrib ACK can have data */
                       recpkt[20] = 0;                 /*  truncate    */
                       error("%sLocal Kermit sent ACK with data: <%s> - goodbye!",prompt,recpkt);
                       return('A');
                       } /* end if */
                 } /* end inner switch */
              if ((size = bufill(packet)) != EOF) /* data from file */
                    return('D');            /* Got data, stay in state D */
  /* EOF can mean either really end-of-file or an error         */
              if ( (num = filerr()) != 0 ) {    /* actual error */
                    error("Problem while reading file, OS code %xx",num);
                    return('A');
                    } /* end if */
              return('Z');                /* EOF                  */
 
          case 'E':                       /* Error packet received */
              prerrpkt(recpkt);           /* Print it out and */
              return('A');                /* abort */
 
          case FALSE: return(state);      /* Receive failure, stay in D */
 
          default:
              error(badpack,prompt,type);
              return('A');        /* Anything else, "abort" */
          } /* end outer switch */
}                       /* End sdata()                          */
 
/*
 *     s e o f
 *
 *     Send End-of-File
 *
 */
 
char seof()
{
    int num, len;                       /* Packet number, length */
    if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */
 
    spack('Z',n,0,packet);              /* Send a 'Z' packet */
    switch(rpack(&len,&num,recpkt))     /* What was the reply? */
    {
          case 'N':                       /* NAK, just stay in this state, */
              num = (--num<0 ? 63:num);   /* unless it's NAK for next packet, */
              if (n != num)               /* which is just like an ACK for */
                    return(state);          /* this packet so fall thru to... */
 
          case 'Y':                       /* ACK */
              if (n != num) return(state); /* If wrong ACK, hold out */
              numtry = 0;                 /* Reset try counter */
              n = (n+1)%64;               /* and bump packet count */
              if (debug) fprintf(dfp,"\nClosing input file <%s>, ",filnam);
              fclose(fp);                 /* Close the input file */
              fp = NULL;            /* Set flag indicating no file open */
 
              if (debug) fprintf(dfp,"looking for next file...");
              if (gnxtfl() == FALSE) {     /* No more files go? */
                    if (debug) fprintf(dfp,"\nNo more files to send.");
                    return('B');            /* if not, break, EOT, all done */
              }
              if (debug) fprintf(dfp,"New file is %s\n",filnam);
              senda = TRUE;               /* send attrib pkt if negotiated */
              return('F');                /* More files, switch state to F */
 
          case 'E':                       /* Error packet received */
              prerrpkt(recpkt);           /* Print it out and */
              return('A');                /* abort */
 
          case FALSE: return(state);      /* Receive failure, stay in Z */
 
          default:
              error(badpack,prompt,type);
              return('A');        /* Something else, "abort" */
    }
}                       /* End seof()                           */
 
/*
 *     s f i l e
 *
 *     Send file header
 *
 */
 
char sfile()
{
    int num, len, lenlen;               /* Packet number, length */
    unsigned filesize;
    char filnam1[50],                   /* Converted file name */
          *newfilnam,                     /* Pointer to file name to send */
          *cp;                            /* char pointer */
 
     /*  MUST use attribute packets with foreign file types!!  */ 
 
/*  if ((fileimage == FOREIGN) && ((senda == FALSE) || (sattrib == FALSE))) {
       error(noattrib, prompt);
       return('A');
       }   */
 
    if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
 
    if (fp == NULL) {                   /* If not already open, */
          if (debug) fprintf(dfp,"\nOpening %s for sending.",filnam);
        if ((fileimage == BINARY) || (fileimage == FOREIGN))
          fp = fopen(filnam,"rb");
        else
          fp = fopen(filnam,"r");         /* open the file to be sent */
          if (fp == NULL)                 /* If bad file pointer, give up */
          {
              error("%sCannot open file <%s>",prompt,filnam);
              return('A');
          }
    }
 
    strcpy(filnam1, filnam);            /* Copy file name */
    newfilnam = cp = filnam1;
    while (*cp != '\0')                 /* Strip off all leading directory */
          if (*cp++ == '>')               /* names (ie. up to the last >). */
              newfilnam = cp;
 
    if (filnamcnv)                      /* Convert lower case to upper  */
          for (cp = newfilnam; *cp != '\0'; cp++)
              if (*cp >= 'a' && *cp <= 'z')
                    *cp ^= 040;
 
    len = cp - newfilnam;               /* Compute length of new filename */
 
    if (debug) fprintf(dfp,"\nSending %s as %s",filnam,newfilnam);
 
   if (iflg >= 99)
      spack('X',n,len,newfilnam);   /* Send an X packet if a 'remote' cmd */
      else
         spack('F',n,len,newfilnam);  /* Send an F packet for file xfer */
    switch(rpack(&len,&num,recpkt))     /* What was the reply? */
    {
          case 'N':                       /* NAK, just stay in this state, */
              num = (--num<0 ? 63:num);   /* unless it's NAK for next packet */
          case 'Y':                       /* ACK */
              if (n != num)
                    return(state);          /* If wrong ACK, stay in F state */
              numtry = 0;                 /* Reset try counter */
              n = (n+1)%64;               /* Bump packet count */
 
       /*  if using attributes switch to 'Q' state; else 'D' state */

          /*  get the attribute from foreign files  */
          
           if (fileimage == FOREIGN)  
              fgets(attrib, 80, fp);

           if ((sattrib) && (senda)) {   
                /* use attribute packets */
          if ( (fileimage == FOREIGN) && ((strncmp(",I",attrib,2)!=0)) ) {
                size = strlen(attrib)-1;               /* drop the newline */
                } else {      /* not 'foreign' so build some attribs */
                  lenlen = 0;
                  while (lenlen < 45) attrib[lenlen++] = 0x0000;
                  /*   compute size in Kilobytes  */
                  if (fileimage == BINARY) 
                     filesize = fsize(filnam,0);
                       else filesize = 0;
                  sprintf(attrib, "%u", filesize);
                  lenlen = strlen(attrib);
         /*   print to string, include computer attrib as well  */
                  sprintf(attrib, ".\042E3!%c%u", tochar(lenlen), filesize);
                  size = strlen(attrib);
                  } /* end else */
              return('Q');
              } else {  /* not using attributes! */
                if ((size = bufill(packet)) != EOF) /* data from file */
                    return('D');            /* Got data, stay in state D */
  /* EOF can mean either really end-of-file or an error         */
                if ( (num = filerr()) != 0 ) {    /* actual error */
                    error("Problem while reading file, OS code %xx",num);
                    return('A');
                    }
                return('Z');                /* EOF (empty file)     */
                } /* end outer else */
 
          case 'E':                       /* Error packet received */
              prerrpkt(recpkt);           /* Print it out and */
              return('A');                /* abort */
 
          case FALSE: return(state);      /* Receive failure, stay in F state */
 
          default:
              error(badpack,prompt,type);
              return('A');        /* Something else, just "abort" */
    }
}                       /* End sfile()                  */
 
 
/*
 *     s a t t r u
 *
 *     Send file attributes
 *     A separate state is not required to receive file attributes !
 *
 */
 
char sattru()
{
    int num, len, lenlen;        /* Packet number, length */
 
    spack('A',n,size,attrib);             /* Send an A packet for file xfer */
    switch(rpack(&len,&num,recpkt))      /* What was the reply? */
    {
          case 'N':                       /* NAK, just stay in this state, */
              num = (--num<0 ? 63:num);   /* unless it's NAK for next packet */
          case 'Y':                       /* ACK */
              if (n != num)
                    return(state);          /* If wrong ACK, stay in Q state */
              numtry = 0;                 /* Reset try counter */
              n = (n+1)%64;               /* Bump packet count */
              if ((size = bufill(packet)) != EOF) /* data from file */
                    return('D');            /* Got data, stay in state D */
  /* EOF can mean either really end-of-file or an error         */
              if ( (num = filerr()) != 0 ) {    /* actual error */
                    error("Problem while reading file, OS code %xx",num);
                    return('A');
                    }                    
              return('Z');                /* EOF (empty file)     */
 
          case 'E':                       /* Error packet received */
              prerrpkt(recpkt);           /* Print it out and */
              return('A');                /* abort */
 
          case FALSE: return(state);      /* Receive failure, stay in Q state */
 
          default:
              error(badpack,prompt,type);
              return('A');        /* Something else, just "abort" */
    }
}                       /* End sattru()                     */
 
 
/*
 *     s i n i t
 *
 *     Send initialization parameters and receive other side's back
 *
 */
 
char sinit()
{
    int num, len;                       /* Packet number, length */
 
    flushinput();                       /* Flush pending input */
    bctu = 1;                           /* assume type-1 block check */
    if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
    len = spar(packet);                 /* Fill up init info packet */
    spack('S',n,len,packet);              /* Send an S packet */
    switch(rpack(&len,&num,recpkt))     /* What was the reply? */
    {
          case 'N':
              num = (--num<0 ? 63:num);   /* unless it's NAK for next packet */
              if (n != num)               /* which is just like an ACK for */
                    return(state);          /* this packet so fall thru to... */
 
          case 'Y':                       /* ACK */
              if (n != num)               /* If wrong ACK, stay in S state */
                    return(state);          /* and try again */
              rpar(recpkt,len);           /* Get other side's init info */
              numtry = 0;                 /* Reset try counter */
              n = (n+1)%64;               /* Bump packet count */
              bctu = bctr;                /* use agreed upon block check */
              return('F');                /* OK, switch state to F */
 
          case 'E':                       /* Error packet received */
              prerrpkt(recpkt);           /* Print it out and */
              return('A');                /* abort */
 
          case 'I':                       /* Init-parameters      */
              rpar(packet,len);
              len = spar(packet);
              spack('Y',n,len,packet); /* ack with our parameters */
              n = (n+1)%64;               /* Bump packet number, mod 64 */
              bctu = bctr;                /* use agreed upon block check */
              return(state);              /*  & continue          */
 
          case FALSE: return(state);      /* Receive failure, try again */
 
          default:
              error(badpack,prompt,type);
              return('A');           /* Anything else, just "abort" */
    }
}                       /* End sinit()                          */
 
/*
 *     s p a c k
 *
 *     Send a packet
 *     Modified for extended packets [FRANK DREANO]
 */
 
spack(stype,num,len,d)
char stype, *d;
int num, len;
{
    int i, j;                             /* Character loop counter */
    register char *bufp;
    char chksum, buffer[MAXPACKSIZ + 6], *lp;    /* Checksum, packet buffer */
 
    if (debug > 1) {                     /* Display outgoing packet */
          fprintf(dfp,"\nSending packet;  type: %c;",stype);
          fprintf(dfp," num: %d;",num);
          fprintf(dfp," len:  %d;",len);
          if (len != 0) {
         j = 0;
              while (j < len) {
                 fprintf(dfp,"\n  data: <");
                 i=0;
                 while ((i < 60 ) && (j < len)) {
                       putc(d[j++],dfp);
                       i++;
                       } /* end while */
                 putc('>',dfp);
}   }   }
    bufp = buffer;
    *bufp++ = SOH;                      /* Packet marker, ASCII 1 (SOH) */
    lp = bufp++;                        /* store LEN pointer for later */
    *bufp++ = tochar(num);              /* Packet number */
    *bufp++ = stype;                     /* Packet type */
    j = len + bctu;      /* packet length plus block check characters */
      if (j+2 > 94) {
/*    if (j > 95) {                         long packets */
       *lp = tochar(0);                  /* init LEN count */
       *bufp++ = tochar(j / 95);     /* high part */
       *bufp++ = tochar(j % 95);     /* lo part */
       *bufp = '\0';                   /* header checksum */
       *bufp++  = tochar(chk1(lp));
       } else *lp = tochar(j+2);    /* give normal length */
 
    while (len-- > 0) *bufp++ = (*d++);
      *bufp = '\0';
 
    switch (bctu) {
       case 1:
           *bufp++ = tochar(chk1(lp));
           break;
       case 2:
           j = chk2(lp);
           *bufp++ = (unsigned) tochar((j >> 6) & 077);
           *bufp++ = (unsigned) tochar(j & 077);
           break;
       case 3:
           j = chk3(lp);
           *bufp++ = tochar(( (unsigned) (j & 0170000)) >> 12);
           *bufp++ = tochar((j >> 6) & 077);
           *bufp++ = tochar(j & 077);
           break;
       }
    *bufp++ = eol;
/*  *bufp = CR;                      CR for network */
    write(1, buffer, bufp-buffer+1);
    if (debug) {
          fprintf(dfp," Packet %d sent;\n",num);
    }
    return;
}                       /* End of spack()                       */
 
/*
 *     s p a r
 *
 *     Fill the data array with my send-init parameters
 *     Returns length of parameter block (6, 7, 9 or 13)
 *     Modified for extended packets [FRANK DREANO]
 */
 
spar(data)
char    *data;
{
    char        len;
 
    data[0] = tochar((spsiz > 94) ? 94 : spsiz);
    data[1] = tochar(MYTIME);
    data[2] = tochar(MYPAD);
    data[3] = ctl(0);
    data[4] = tochar(MYEOL);
    data[5] = MYQUOTE;
    len = 6;
    if (image == 2) {                   /* 8th-bit prefixing    */
          if (qu8 == 0)
/*            data[6] = 'Y';   	this means I don't need to quote !!!  */
		      data[6] = '&';
          else
              data[6] = qu8;              /*  feed back 8-quote   */
          len = 7;
          }
          else
             data[6] = 'N';
    data[7] = bctr + '0';           /*  set checksum type */
    len = 8;
    if (rptflg) {
          data[8] = '~';        /* only ~ for repeating */
          len = 9;
          } /* end if */
 
/* extended packet modifications  [FRANK DREANO]         */
       data[9] = tochar(0x08);       /* I can accept attribute packets */
    if (slongp == TRUE) {
       data[9] = tochar(0x0a); /* attribs & extended packets can be used */
       data[10] = tochar(0x00);                /* NO sliding windows! */
       data[11] = tochar(MAXPACKSIZ / 95);   /* set up for 2000 bytes */
       data[12] = tochar(MAXPACKSIZ % 95);
       len = 13;
       if (debug)
          fprintf(dfp,"\nExtended packets requested (2000) bytes.");
       } /* end if */
 
    if (debug) fprintf(dfp,
"\nParms sent out: Fileimage: %d, image: %d, q_char: %c, rptflg: %s, bchk: %d.",
fileimage,image,qu8,logicval[-rptflg],bctr);              
/*    
"\nParms sent out: 8th-bit tseting is %d, char is %c, reptflag %s, chktype %d.",
image,qu8,logicval[-rptflg],bctr); */
    return(len);
 
}                       /* End of spar()                        */
 
/*
 *     t i m o c a n
 *
 *     Cancel a scheduled timeout
 *
 */
 
timocan()
{
    timoset(0);
    timflag = 0xff;
    return;
}                       /* End of timocan()             */
 
/*
 *     t i m e o x
 *
 *     Indicate timeout condition
 *
 */
 
timoex()
{
    timflag = 0;                /* clear flag           */
    if (debug) {
          fprintf(dfp,"Timeout ...");
    }
    return;
}                       /* End of timoex()              */
 
 
/*
 *        f s i z e
 *
 *        This routine gets the APPROXIMATE size of a file in kilobytes
 *        so that an 'attribute' packet may be sent during transfers.
 *        It uses very esoteric code and MOD400 macro calls so if it
 *        causes trouble, skip sending attribute packets.  
 *        If the 'func' arg is other than '1' the size is only computed
 *        for fixed-length record files as variable-length record file 
 *        size estimates are highly inaccurate.  If the 'func' arg is '1'
 *        AND the file 'fname' contains variable length records a 0 is
 *        returned if the DATA_CODE is unknown and a 1 if it is BINARY. 
 *
 *                                                   [FRANK DREANO]
 */
 
unsigned
fsize(fname, func) char *fname; int func;
{
#define $GIFIL 0x1060   /* --- get file information       --- */
 
      struct mcl_psb {
          int *reg_b4;
          int *reg_b3;
          int *reg_b2;
          int *reg_b1;
          int reg_r7;
          int reg_r6;
          int reg_r5;
          int reg_r4;
          int reg_r3;
          int reg_r2; } reg;
 
       union cvt_adr {int address[3]; int *adrint; char *adrchar;} adrtag;
 
struct gifab {
     int gfa_lrsz;            /* logical record size                  */
     int gfa_bksz;            /* block size (bytes/CI for disk files) */
     int gfa_find;            /* field indicators (# of CIs in file)  */
     int gfa_dsw1;            /* device specific word 1               */
     int gfa_dsw2;            /* device specific word 2               */
     int gfa_isw1;            /* init device specific word 1          */
     int gfa_isw2;            /* init device specific word 2          */
     int gfa_rfu [9];         /* reserved - must be zero              */
} fab;
# define gfa_cisz gfa_bksz
 
struct gipsb {
     int gipsb_lfn;
     int *gipsb_pthp;
     int gipsb_dtyp;
     int gipsb_lrn;
     char gipsb_ftyp;
     char gipsb_rtyp;
     struct gifab *gipsb_fabp;
     unsigned int gipsb_sdid;
     int gipsb_resv;
     int *gipsb_kdp;
     int gipsb_rdsz;
     int gipsb_nrf;
} psb;
 
       int i;
       int hunds, tens, units;
       int path_name[28];
       char rec_type;              /* Fixed or variable records */
/*     float front; */
       unsigned lrsz, cisz, cinum, bytesize;    /* multiplicative operands */
 
              /* load up required parameters in arg block */
 
       lrsz = cisz = cinum = bytesize = 0;
/*     front = 0;  */  i = 0;
       while (i < 28) path_name[i++] = 0x2020;  /* file name inited to blank */
       path_name[28] = 0x2020;                  /* terminate name array     */
       strcpy(path_name, fname);
       strcat(path_name, " ");      /* $GIFIL macro needs terminating blank */
       psb.gipsb_lfn = 0x2020;                   /* blank out LFN field      */
       psb.gipsb_pthp = &path_name[0];           /* load pointer to pathname */
       psb.gipsb_fabp = &fab;                    /* load ptr to file attribs */
       psb.gipsb_kdp = 0x000;                    /* load NULL ptr, field N/A */
 
                /* set-up arg-block for the mcl call */
 
       adrtag.adrint = &psb;          /* get char pointer to argument block */
       reg.reg_b4 = adrtag.adrint;    /* 'dirty' conversion of pointer      */
       adrtag.adrint = &reg.reg_b4;   /* get address of B4 register         */
       i = mcl($GIFIL,adrtag.adrint);
       if (i != 0) {
           printf("\n\tERRORCODE: %x\n", i);
           return(0);
           } /* end if */
 
       rec_type = psb.gipsb_rtyp;
 /*  if arg = 3 get lrsz for >SYSLIB2>EC to determine operating system  */ 
       if (func == 3) {
          lrsz_6 = fab.gfa_lrsz; 
          if (debug) fprintf(dfp, "BU lrsz size = %d\n", lrsz_6);
          return(0);
          }
       lrsz = fab.gfa_lrsz;
       cisz = fab.gfa_cisz;  /* put Fixed-relative CI size in var. */
       cinum = fab.gfa_find;
 
   /* determine if a sequential file has DATA_CODE = BINARY attribute */       
   
/*     if (debug) 
          fprintf(dfp,
         "\nFSIZE(): File: %s, rec_type: %c, function: %d, data_code: %x\n", 
              fname, rec_type, func, (psb.gipsb_resv & 0x1000));  */
 
       if ((rec_type != 'F') && (func == 1)) 
          return(psb.gipsb_resv & 0x1000);
       
   /* recompute the CI size to exclude CI & logical record header info */
 
       if (rec_type != 'F')          /* dont try var-length SEQ files */
          return(0);
       cisz = cisz - (((cisz / lrsz) * 4) + 8);
 
   /* compute file size in kilobytes WITHOUT using floating point ops. */
 
       hunds = cisz/100; tens = (cisz - (hunds * 100)) / 10;
       units = cisz - (hunds * 100) - (tens * 10);
       hunds = hunds * cinum; tens = tens * cinum; units = units * cinum;
       bytesize = (hunds + (tens/ 10) + (units / 100)) / 10;
 
/*     front = cisz; front = front / 1024; front = front * cinum;
       bytesize = front; */
       if (debug ) {
          fprintf(dfp, "\n\tThe logical record size is: %u.", lrsz);
          fprintf(dfp, "\n\tThe number of data bytes per CI is: %u.", cisz);
          fprintf(dfp, "\n\tThe highest numbered file CI is: %u.", cinum);
          fprintf(dfp,
              "\n\tThe approximate size in kilobytes is: %u.\n", bytesize);
          } /* end if */
       return(bytesize);         /* return size in bytes */
 
 
}  /* end fsize */
 
 
/*
 *     Kermit checksum routines:
 *
 *     The following three routines are in keeping with 'classic'
 *     Kermit and are presented worst to best below [FRANK DREANO]
 *
 */
 
/*
 *      c h k 1 -- compute type-1 Kermit error-checking;
 *                 a 6-bit checksum.
 *
 */
 
chk1(pkt) char *pkt; {
        unsigned int chk;
        chk = chk2(pkt);
        chk = (((chk & 0300) >> 6) + chk) & 077;
        return(chk);
}       /* end of chk1 */
 
/*
 *      c h k 2 -- compute the numeric sum of all bytes in the packet;
 *                 a 12-bit checksum.
 *
 */
 
 unsigned
 chk2(pkt) unsigned char *pkt; {
        long chk;
        for (chk = 0; *pkt != '\0'; pkt++)
           chk += *pkt;
        return(chk & 07777);
}       /* end of chk2 */
 
/*
 *      c h k 3 -- compute type-3 Kermit checksum;
 *                 a 16-bit cyclic redundancy check.
 *
 */
 
 chk3(s) char *s; {
        unsigned int c, q;
        unsigned long crc = 0;
 
        while ((c = *s++) != '\0') {
           c &= 0177;                   /* strip high bit if any */
           q = (crc ^ c) & 017;         /* low order nibble */
           crc = (crc >> 4) ^ (q * 010201);
           q = (crc ^ (c >> 4)) & 017;  /* hi order nibble */
           crc = (crc >> 4) ^ (q * 010201);
           } /* end while */
        return(crc);
} /* end chk3 */
 
/*
 *     Kermit printing routines:
 *
 *     help - displays command syntax specific to DHS version of Kermit
 *     usage - print command line options showing proper syntax
 *     printmsg - like printf with logo prepended
 *     error - like printmsg if local Kermit; sends error packet if remote
 *     prerrpkt - print contents of error packet received from remote
 *
 */
 
/*
 *     h e l p
 *
 *     The next two routines are user help displays for DHS Kermit
 *
 */
 
help()
{
    printf("\nSummary of DPS-6 Superkermit:\n");
    help1();
    printf("\t\t\t\t hit CR for more ");
    timoset(30);
    while (timflag != 0)
          if (cread() != 0)
              break;
    printf("\nBasic syntax of the \"superkerm\" command is:\n");
    usage();                    /* exits                */
}                       /* End of help()                */
help1()
{
 printf("This is a remote receive/send/server Kermit; normally called with\n");
 printf("  command line arguments, if not, server mode is assumed.\n");
 printf("CRC error checking is always requested, 7-bit ASCII transfers invoked\n");
 printf("  by \"a\"-flag, otherwise 8-bit prefixed transfer is the default;\n");
 printf("  mapping between LFs and CR/LF pairs is only done for ASCII transfers.\n");
 printf("8-bit image mode is invoked by \"i\"-flag; there is NO Connect facility.\n");
 printf("Extended packet (up to 2000 bytes) transfers are always available.\n");
 printf("Incoming text files will be concatenated to via the \"c\"-flag.\n");
 printf("Server mode supports many advanced server commands...see the files\n");
 printf("   >SYSLIB1>SUPERKER.DOC and >SYSLIB1>SUPERKER.BWR for details.\n");
 printf("If your transfer breaks down, go into connect-mode and enter\n");
 printf("  ESCAPE-C, which will cause Superkermit to quit gracefully;\n");
 printf("  alternatively enter ESCAPE-H, which will elicit a reassurance.\n");
 printf("If debug is requested by \"-D\" flag(s) on second parameter, then\n");
 printf("  debug information is written into a file whose name is \n");
 printf("  the rest of the second parameter (after last \"D\"); up to three\n");
 printf("  \"D\" flags may be entered (but only one \"-\"):\n");
 printf("Debug = 1 gives basic trace of automaton states + error-messages,\n");
 printf("      = 2 logs packets as sent/received,\n");
 printf("      = 3 also logs all chars as read from line, in hex.\n");
    return;
}                               /* End of help1()                       */
 
/*
 *     u s a g e
 *
 *     Tell the user how to invoke Kermit in any mode and quit
 *
 */
 
usage()
{
 cooktty();
printf
 ("Usage: superkerm  s[abfic] [-Ddebug-file] file(s) ...    (send mode)\n");
 printf
 ("or:    superkerm  r[abfic] [-Ddebug-file]                (receive mode)\n");
 printf
 ("or:    superkerm  v[abfic] [-Ddebug-file]                (server mode)\n");
 printf("  where a  =  ASCII 7-bit file xfer (default),\n");
 printf("        b  =  BINARY file xfer (usually DPS-6 bound-units),\n");
 printf("        f  =  FOREIGN (MSDOS/UNIX) file xfer: *.exe, *.com, etc,\n");
 printf("        i  =  force 8-bit binary-image xfer (no parity allowed!),\n");
 printf("        c  =  concatenate to ASCII files if they already exist,\n\n");
 printf("        Wild card xfers (all files ASCII, BINARY or FOREIGN) are legal.\n");
 printf("        Under the 4.0 operating system Superkermit will work with the\n");
 printf("        VIP3 Terminal Emulator configured for 7-bit 'other host' Kermit\n");
 printf("        (NOT Honeywell's Kermit); it can use the ASYNCH1 AP port.\n");
 printf("        debug-file is preceded by \"-\" and up to 3 \"D\"-flags.\n");
 printf("or:    superkerm  h                                  (help display).\n");
 printf(crlf);
 closeall();
 exit(0);
}                       /* End of usage()                       */
 
/*
 *     p r i n t m s g
 *
 *     Print message on standard output if not remote
 *
 */
 
/*VARARGS1*/
printmsg(fmt, a1, a2, a3, a4, a5)
char *fmt;
{
          printf("Superkermit: ");
          printf(fmt,a1,a2,a3,a4,a5);
          printf("\n\r");
          return;
}                       /* End of printmsg()                    */
 
/*
 *     e r r o r
 *
 *     Print error message
 *     If remote, send an error packet with the message
 *
 */
 
/*VARARGS1*/
error(fmt, a1, a2, a3, a4, a5)
char *fmt;
{
    char msg[100];
    int len;
 
    sprintf(msg,fmt,a1,a2,a3,a4,a5); /* Make it a string */
    len = strlen(msg);
    spack('E',n,len,msg);           /* Send the error packet */
    if (debug) fprintf(dfp,"%s\n",msg);
    return;
}                       /* End of error()               */
 
/*
 *     p r e r r p k t
 *
 *     Print contents of error packet received from remote Kermit
 *
 */
 
prerrpkt(msg)
char *msg;
{
    if (debug) {
       fprintf(dfp,
	   "\nSuperkermit Aborting with following message from local Kermit:");
       msg[50] = 0;
       fprintf(dfp,"\n  \"%s\"",msg);
    }
    return;
}                       /* End prerrpkt()               */
 
/*********************  END of FILE  hd6pri.c  **************************/
