home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ncr9800 / ckvfio.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  20KB  |  577 lines

  1. /* C K V F I O      object module transfer      */
  2.  
  3. /**********************************************************************
  4. *                                                                     *
  5. * IVS / MCS-Kermit REL 2                                              *
  6. * source code                                                         *
  7. *                                                                     *
  8. * Change History:                                                     *
  9. *                                                                     *
  10. *                1. Modify C-Kermit(4E) source code to                *
  11. *                   produce new module for MCS/IVS-Kermit             *
  12. *                   ORIGINAL RELEASE                                  *
  13. *                   June 22, 1990                                     *
  14. *                                                                     *
  15. *                                                                     *
  16. ***********************************************************************/
  17.  
  18. /*
  19.    update May 10, 1990
  20.    PEG
  21.    Modified error handling
  22.    to reflect changes to
  23.    other modules to use
  24.    errhdlr()
  25.  
  26.    update May 23, 1990
  27.    OBJECT FILE message flawed
  28.    PEG
  29.  
  30.   VKOFIO - Object file I/O for VKERMIT.
  31.   This module interfaces to and does buffering for
  32.   VRX/E object files.
  33.  
  34.   In order for object file transfer to work, the file type must be
  35.   set to binary for both sides of the kermit file transfer. No translation
  36.   of CR or LF can be allowed.
  37.  
  38.   Vkermit can only receive and create object files which have been
  39.   sent previously by vkermit. It cannot handle object files transferred
  40.   to the remote system by some other means. Nor is the format of a vkermit
  41.   sent object file suitable for ANY use other than being transferred back
  42.   to a VRX system by vkermit.
  43.  
  44.   FCL is necessary to properly open the object file. The default file
  45.   reference name is OBJFILE.
  46.   The VRX file type must be set to object and the record size must be set
  47.   to 1/490.
  48.  
  49.   The following routines are to be called by the ckufio module
  50.   when it detects that a VRX object file is being transported.
  51.     voopeni - to open an object file for input (download)
  52.               Called by zopeni.
  53.     voopeno - to open an object file for output (upload)
  54.               Called by zopeno.
  55.     vogetc - to get the next character from a VRX object file.
  56.              Called by zchin.
  57.     voputc - to put the next character to a vrx object.
  58.              Called by zchout.
  59.     voclose - to close a VRX object file. Called by zclose.
  60.  
  61.   This module contains data structures to buffer the characters
  62.   and keep track of the object file(s) currently open.
  63.   In this implementation, there is only one VRX object file open
  64.   at a time.
  65.  
  66.   Since VRX object files are variable length, a two byte VLI is
  67.   prepended to each data record. This module creates the VLI for
  68.   downloading and interprets the VLI for uploading. The rest of
  69.   kermit does not even know these VLIs are there and treats them
  70.   as data. Since binary file type transfer is being used, the non-ASCII
  71.   nature of these VLIs is unimportant.
  72.  
  73.   Using VLIs as part of the data stream is the only way to recreate
  74.   the object file on VRX. Object files must be written with variable
  75.   length records. When an object file is written, the VLI is stripped
  76.   off of the buffer and the rest of the buffer is written as the record.
  77.   The implicit length of the string determines the record size and VRX
  78.   file management takes care of the internals necessary for variable
  79.   length records.
  80.  
  81.   Although buffering is done by this module, the actual I/O's
  82.   are done by a separate module written in NCRL which uses
  83.   NCRL IO.
  84.  */
  85. #include <stdio.h>
  86. #include "ckcker.h"              /* March 2, 1990 */
  87. #include <errno.h>
  88.  
  89. /*
  90.  * Constants used by this module
  91.  */
  92.  
  93. /*
  94.    *  Errors returned by NCRL I/O service routines
  95.    */
  96. #define NIOOK    0
  97. #define NIOBAD   1
  98. #define NIOEOF   2
  99.  
  100. /*
  101.    *  Sizes of various structures and strings
  102.    */
  103. #define LEGRECSIZ 200        /* The size of the NCRL legible type */
  104. /* Actual size is probably less - e.g.
  105.                                 134 bytes on 4-85, but the size is
  106.                                 not guaranteed to remain constant from
  107.                                 release to release. */
  108. #define MAXOBJDAT 490        /* Max size of object record data  */
  109. #define REFSIZ 31            /* Standard size for VRX file reference */
  110. #define OBJREFSIZ 7          /* Size of default reference name */
  111. #define VLISIZE 2            /* The size of the added VLIs */
  112. #define MAXOBJREC MAXOBJDAT+VLISIZE  /* The maximum size of the
  113.                                         buffer used for objects
  114.                                         including the vli * /
  115.  
  116. /* dummy type for access() */
  117.  
  118. #define file_EXIST 0
  119.  
  120. /*
  121.  * Types declared for this module
  122.  */
  123.  
  124. /* legible - This is an NCRL type used for I/O.  */
  125. typedef char     legible[LEGRECSIZ];
  126.  
  127. /* objrec - This type allows access of the buffer
  128.    as a string and also direct reference of the VLI and data
  129.    portions of the buffer. The NCRL IO routines actually
  130.    fill in the VLI and data, but this module must have access
  131.    of the number of bytes in order to determine when a new
  132.    record must be read or written.
  133.   */
  134. typedef union objrec {
  135.      char     buffer[MAXOBJREC];
  136.      struct {
  137.           short     vli;       /* does not include size of the vli itself */
  138.           /* must be on a two byte boundary          */
  139.           char     data[MAXOBJREC - VLISIZE];
  140.      } vlianddata;
  141. };
  142.  
  143. /*
  144.    * This series of types is declared so that variable length strings
  145.      can be passed to an NCRL routine. A NCRL string consists of
  146.      a four byte length indicator and a pointer to the text of the
  147.      string. The C strings passed as parameters must be translated
  148.      into this form in order for NCRL IO to work properly.
  149.  
  150.    NCRLptr - a definition of NCRL's 3 byte pointers.
  151.    ptr_param - a definition of the 4 byte pointer format of NCRL
  152.      pointers used when passing pointers as parameters (the first
  153.      byte is ignored as serves only to align the pointer).
  154.    c2vrx_ptr - a union constructs that allows casting of integers
  155.      into the four byte pointer format.
  156.    ncrl_string - a definition of NCRL variable strings as a four
  157.      byte length and a four byte pointer.
  158.   */
  159. struct NCRLptr {
  160.      char     byte1;
  161.      char     byte2;
  162.      char     byte3;
  163. };
  164.  
  165. struct ptr_param {
  166.      char     zero_fill;
  167.      struct NCRLptr ptr;
  168. };
  169.  
  170. union c2vrx_ptr {
  171.      int     *int_ptr;
  172.      struct ptr_param ncr_ptr;
  173. };
  174.  
  175. struct ncrl_string {
  176.      int     len;
  177.      union c2vrx_ptr ptr;
  178. };
  179.  
  180. /*
  181.  * Global variables -
  182.  *  These variables are directly referenced only be this module but
  183.  *  must retain their values until changed (if at all) by this module.
  184.  */
  185.  
  186. /* objref - The default reference name. A different reference name
  187.    can be passed in as part of the name parameter of the open routines.
  188.    An FCL file reference must be used on the invocation of vkermit in
  189.    order to open the file correctly.
  190.   */
  191. char     objref[OBJREFSIZ+1] = "OBJFILE";  /* The default reference name */
  192. union objrec buf;                      /* The buffer used for object IO */
  193. struct ncrl_string buffer_string;      /* The NCRL string used to pass the
  194.                                        buffer to the NCRL IO routines
  195.                                        (see discussion under types).  */
  196. int     nBufSiz, nBufNdx;        /* Current buffer size (including VLI)
  197.                                 and current char in buffer being accessed */
  198. legible objf;                /* The object file definition structure
  199.                              The legible construct is filled in by the
  200.                              NCRL OPEN and is then used to refer to the
  201.                              file for all subsequent IO operations.  */
  202. /* There is only ONE object file open at a time */
  203.  
  204. /*
  205.  * Declaration of all procedures in the NCRL IO service module.
  206.  * This module must be compiled with COPT='-Xv' to avoid
  207.  * adding an additional return parameter to these void declared
  208.  * procedures.
  209.  */
  210. extern void OBJOPENI();
  211. extern void OBJOPENO();
  212. extern void OBJCLOSE();
  213. extern void OBJRECIN();      /* Reads an entire object record, prepending data
  214.                              with a VLI. */
  215. extern void OBJRECOUT();     /* Writes one variable record */
  216.  
  217. extern int     errhdlr();
  218. extern int     access();
  219. int            ERRCELL;     /* set in VKNCRLIO by bad vrxoutcome    */
  220.  
  221. /* forward procedure declaration */
  222. setupvbuf();
  223.  
  224. voopeni(n, in_name)
  225. int     n;      /* file number*/
  226. char     *in_name;
  227. /*
  228.  voopeni - prepare for open of VRX object file by NCRL I/O
  229.  refandname may be of the form "fileref(NAME=filename)" or may
  230.  just contain the file name. If the complex form is present,
  231.  it must be broken into its components for usage by NCRL I/O.
  232.  The n parameter is the file number and is ignored since only one
  233.  object file is opened at a time.
  234.  
  235.  Return values:
  236.    0 if open successful
  237.    -1 if unsuccessful
  238. */
  239. {
  240.      char     result;
  241.      struct ncrl_string ncrl_name, ncrl_refname;
  242.      char     name[REFSIZ+1];
  243.      char     refname[REFSIZ+1];
  244.      char     refandname[REFSIZ+4];
  245.      char     *temp;
  246.      int     i;
  247.  
  248.      /* before we go through several levels of code, parsing
  249.      the final file name, etc, etc. Let's save some processing
  250.      time and some nasty errors by verifying the file is
  251.      present. In order for this to work the FCL reference
  252.      OBJFILE must exist. Otherwise we maybe back at square one.
  253.  
  254.      PEG March 7, 1990
  255.                                                                 */
  256.  
  257.      if (in_name != NULL)
  258.         strcpy(refandname,in_name);
  259.      else
  260.         return(-1);
  261.  
  262.      if ((i = access(refandname, file_EXIST)) != 0)
  263.           return(-1);
  264.  
  265.      if (in_name != NULL)
  266.         strcpy(refandname,in_name);
  267.      else
  268.         return(-1);
  269.  
  270.      /* determine type of format of refandname and parse it */
  271.      if ((temp = strrchr(refandname, ')')) != NULL) {
  272.                                                            /* complex form */
  273.                                             /* eliminate final parenthesis */
  274.           temp[0] = '\0';
  275.           if ((temp = strrchr(refandname, '=')) != NULL) {
  276.                                    /* now temp points just before file name */
  277.                temp++;
  278.                strcpy(name, temp);
  279.                                          /* continue to parse for refname */
  280.                if ((temp = strchr(refandname, '(')) != NULL) {
  281.                     /* eliminate first parenthesis - what is left is refname */
  282.                     temp[0] = '\0';
  283.                     strcpy(refname, refandname);
  284.                } else {
  285.                                                               /* error! */
  286.                     errhdlr("voopeni");
  287.                     fprintf(stderr,"voopeni: name format1 error: %s",
  288.                               refandname);
  289.                     return(-1);
  290.                }
  291.           } else {
  292.                                                               /* error ! */
  293.                errhdlr("voopeni");
  294.                fprintf(stderr, "name format2 error: %s",
  295.                     refandname);
  296.                return(-1);
  297.           }
  298.      } else {
  299.           /* must be in simple format -
  300.        use parameter as filename and use default refname
  301.     */
  302.           strcpy(name, refandname);
  303.           strcpy(refname, objref);
  304.      }
  305.      ncrl_name.len = strlen(name);
  306.      ncrl_name.ptr.int_ptr = (int *) name;
  307.      ncrl_refname.len = strlen(refname);
  308.      ncrl_refname.ptr.int_ptr = (int *) refname;
  309.      OBJOPENI(&ncrl_name, &ncrl_refname, objf, &result);
  310.  
  311.      if (result != NIOOK) {
  312.           /*
  313.                               When a lousy outcome is returned from
  314.                               VKNCRLIO we output an error message
  315.                               PEG March 6, 1990
  316.                            */
  317.  
  318.       errhdlr("voopeni");
  319.           fprintf(stderr, "objfile (i)open failure outcome: %d\n", ERRCELL);
  320.           return(-1);
  321.  
  322.      }
  323.  
  324.      setupvbuf();
  325.      return(0);
  326. }
  327.  
  328.  
  329. voopeno(n, in_name)
  330. int     n;      /* file number*/
  331. char     *in_name;
  332. /*
  333.  voopeno - prepare for open of VRX object file by NCRL I/O
  334.  refandname may be of the form "fileref(NAME=filename)" or may
  335.  just contain the file name. If the complex form is present,
  336.  it must be broken into its components for usage by NCRL I/O.
  337.  The n parameter is the file number and is ignored since file numbers
  338.  are not used when files are opend by NCRL IO.
  339.  
  340.  Return values:
  341.    0 if open successful
  342.    -1 if unsuccessful
  343. */
  344. {
  345.      char     result;
  346.      struct ncrl_string ncrl_name, ncrl_refname;
  347.      char     name[REFSIZ+1];
  348.      char     refname[REFSIZ+1];
  349.      char     refandname[REFSIZ+1];
  350.      char     *temp;
  351.  
  352.      if (in_name  != NULL)
  353.         strcpy(refandname,in_name);
  354.      else
  355.         return(-1);
  356.  
  357.      /* determine type of format of refandname and parse it */
  358.      if ((temp = strrchr(refandname, ')')) != NULL) {
  359.           /* complex form */
  360.           /* eliminate final parenthesis */
  361.           temp[0] = '\0';
  362.           if ((temp = strrchr(refandname, '=')) != NULL) {
  363.                /* now temp points just before file name */
  364.                temp++;
  365.                strcpy(name, temp);
  366.                /* continue to parse for refname */
  367.                if ((temp = strchr(refandname, '(')) != NULL) {
  368.                     /* eliminate first parenthesis - what is left is refname */
  369.                     temp[0] = '\0';
  370.                     strcpy(refname, refandname);
  371.                } else {
  372.                                                          /* error! */
  373.                     errhdlr("voopeno");
  374.                     fprintf(stderr, "name format1 error: %s\n",
  375.                          refandname);
  376.                     return(-1);
  377.                }
  378.           } else {
  379.                                                             /* error ! */
  380.                errhdlr("voopeno");
  381.                fprintf(stderr, "name format2 error: %s\n",
  382.                     refandname);
  383.                return(-1);
  384.           }
  385.      } else {
  386.           /* must be in simple format -
  387.          use parameter as filename and use default refname
  388.                                                                 */
  389.           strcpy(name, refandname);
  390.           strcpy(refname, objref);
  391.      }
  392.      ncrl_name.len = strlen(name);
  393.      ncrl_name.ptr.int_ptr = (int *) name;
  394.      ncrl_refname.len = strlen(refname);
  395.      ncrl_refname.ptr.int_ptr = (int *) refname;
  396.  
  397.      OBJOPENO(&ncrl_name, &ncrl_refname, objf, &result);
  398.  
  399.      if (result != NIOOK) {
  400.           /*
  401.                               When a lousy outcome is returned from
  402.                               VKNCRLIO we output an error message
  403.                               PEG March 6, 1990
  404.                            */
  405.  
  406.           errhdlr("voopeno");
  407.           fprintf(stderr,"object (o)file failure outcome: %d\n",ERRCELL);
  408.           return(-1);
  409.      }
  410.  
  411.      setupvbuf();
  412.      return(0);
  413. }
  414.  
  415.  
  416. setupvbuf()
  417. {
  418.      /* SETUPVBUF -
  419.  *  Initialize buffer variables in preparation for IO
  420.  */
  421.      buffer_string.len = MAXOBJREC;
  422.      buffer_string.ptr.int_ptr = (int *) & buf;
  423.      nBufSiz = nBufNdx = 0;
  424. }
  425.  
  426.  
  427. /* VOGETC -
  428.  *  Return the next characters from the object file.
  429.  *  In most cases, this just returns the next character in the object
  430.  *  record buffer. When the last character in the buffer has been
  431.  *  used, objrecin is called to read in another record. Note that
  432.  *  the VLI itself is returned to the caller as part of the data.
  433.  *  The calling kermit routine does not need to know this.
  434.  *  The VLI must be made part of the data in order to reconstruct
  435.  *  an object file when the file is later received by vkermit (see voputc).
  436.  *
  437.  *  Return values:
  438.  *    -1 if error or EOF
  439.  *    otherwise the character read
  440.  */
  441. vogetc(n)
  442. int     n;
  443. {
  444.      char     result;
  445.  
  446.      if (nBufNdx < nBufSiz) {
  447.           nBufNdx++;
  448.           return(buf.buffer[nBufNdx-1]);
  449.      } else {
  450.           /* get new buffer */
  451.           OBJRECIN(objf, &buffer_string, &nBufSiz, &result);
  452.  
  453.           if (result != NIOOK) {
  454.                if (result != NIOEOF) {
  455.                     /*
  456.                               When a lousy outcome is returned from
  457.                               VKNCRLIO we output an error message
  458.                               PEG March 6, 1990
  459.                            */
  460.  
  461.                     errhdlr("vogetc");
  462.                     fprintf(stderr,"READ FAILURE OUTCOME: %d\n",ERRCELL);
  463.                     return(-1);
  464.  
  465.                } else /* end of file */
  466.                     return(-1);               /* DRE 030990 */
  467.  
  468.           } else {  /* good i-o */
  469.  
  470.                if (buf.vlianddata.vli > MAXOBJDAT) {  /* March 2, 1990  */
  471.  
  472.                     char errbuf[40];
  473.  
  474.                     sprintf(errbuf,"vogetc: obj vli exceeds max: %#X",
  475.                             buf.vlianddata.vli);
  476.                     errhdlr(errbuf);
  477.                     fprintf(stderr,"current vli maximum: %#X\n", MAXOBJDAT);
  478.                     return(-1);
  479.                }
  480.  
  481.                nBufNdx = 1;
  482.                nBufSiz += VLISIZE;
  483.                return(buf.buffer[0]);
  484.           }
  485.      }
  486. }
  487.  
  488.  
  489. /* VOPUTC -
  490.  *  Put a single character into the destination object file.
  491.  *  The first two characters are used to calculate the size of
  492.  *  the record next to be written. When that many characters have
  493.  *  been transferred into the buffer, the buffer is written using
  494.  *  OBJRECOUT. A ncrl_string type must be used to create a string
  495.  *  with a known (to NCRL) length.
  496.  *
  497.  *  Return values:
  498.  *    0 if successful
  499.  *   -1 if failure
  500.  */
  501. voputc(c, n)
  502. char     c;
  503. int     n;
  504. {
  505.      char     result;
  506.  
  507.      /* check if we just got a full vli */
  508.      if (nBufNdx == 1) {
  509.           /*calculate size of record to write */
  510.           /* Note that the buffer size includes the size of the VLI
  511.              but the VLI itself does not include the size of the VLI */
  512.           buf.buffer[1] = c;
  513.  
  514.           if (buf.vlianddata.vli > MAXOBJDAT) {  /* March 2, 1990  */
  515.  
  516.                     char errbuf[40];
  517.  
  518.                     sprintf(errbuf,"voputc: obj vli exceeds max: %#X",
  519.                             buf.vlianddata.vli);
  520.                     errhdlr(errbuf);
  521.                     fprintf(stderr,"current vli maximum: %#X\n", MAXOBJDAT);
  522.                     return(-1);
  523.  
  524.           }
  525.  
  526.           nBufSiz = buf.vlianddata.vli + VLISIZE;
  527.      }
  528.      buf.buffer[nBufNdx] = c;   /* when nBufNdx = 1 c is written twice */
  529.      nBufNdx++;
  530.      if (nBufNdx >= nBufSiz) {
  531.           /* clear the current buffer by writing it out */
  532.           /* unless it is the first time */
  533.  
  534.           if (nBufSiz > 0) {                          /* March 2, 1990 */
  535.                OBJRECOUT(objf, &buffer_string, &result);
  536.  
  537.                if (result != NIOOK) {
  538.  
  539.                     /*
  540.                               When a lousy outcome is returned from
  541.                               VKNCRLIO we output an error message
  542.                               PEG March 6, 1990
  543.                            */
  544.                     errhdlr("voputc");
  545.                     fprintf(stderr,"write failure outcome: %d\n",ERRCELL);
  546.                     return(-1);
  547.  
  548.                }
  549.  
  550.                nBufNdx = 0;
  551.                /* Note actual size of buffer is not calculated until
  552.                   second byte arrives. */
  553.           }
  554.      }
  555.      return(0);
  556. }
  557.  
  558.  
  559. voclose(n)
  560. int     n;
  561. {
  562.      char     result;
  563.  
  564.      OBJCLOSE(objf, result);
  565.      if (result == NIOBAD) {    /*
  566.                               When a lousy outcome is returned from
  567.                               VKNCRLIO we output an error message
  568.                               PEG March 6, 1990
  569.                                   */
  570.  
  571.           errhdlr("voclose");
  572.           fprintf(stderr,"error closing file outcome: %d\n",ERRCELL);
  573.           return(-1);
  574.      }
  575.      else return(0);
  576. }
  577.