home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ncr9800 / ckvfi2.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  62KB  |  2,034 lines

  1. char     *ckzv = "VRX/VE file support, 4E(038) 30 May 90";
  2.  
  3. /* C K U F I 2  --  Kermit file system support for VRX/VE systems */
  4.  
  5. /**********************************************************************
  6. *                                                                     *
  7. * IVS / MCS-Kermit REL 2                                              *
  8. * source code                                                         *
  9. *                                                                     *
  10. * Change History:                                                     *
  11. *                                                                     *
  12. *                1. Modify C-Kermit(4E) source code to                *
  13. *                   produce new module for MCS/IVS-Kermit             *
  14. *                   ORIGINAL RELEASE                                  *
  15. *                   June 22, 1990                                     *
  16. *                                                                     *
  17. *                                                                     *
  18. ***********************************************************************/
  19.  
  20.  
  21. /*
  22.  Author: Frank da Cruz (SY.FDC@CU20B),
  23.  Columbia University Center for Computing Activities, January 1985.
  24.  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
  25.  Permission is granted to any individual or institution to use, copy, or
  26.  redistribute this software so long as it is not sold for profit, provided this
  27.  copyright notice is retained.
  28. */
  29.  
  30. /* ******************************************************************
  31.          DO NOT COMPILE THIS MODULE WITH
  32.          #include <mcs.h>
  33.          THIS INCLUDE CAUSES A PERFORMANCE DEGRADATION
  34.          PEG  May 04, 1990
  35. ********************************************************************* */
  36.  
  37. /*
  38. *********************************************************************
  39.  
  40.      May 9, 1990
  41.  
  42.      The following features were removed from the user
  43.      display and disabled from use.
  44.  
  45.      add-linenum id-fields line-numbers renumber
  46.  
  47.      May 21, 1990
  48.  
  49.      We added reset logic for errno == EMINR. This
  50.      (?)error appends spaces characters to line
  51.      end. Earlier releases we treated this as
  52.      corruption. This release (V-KERMIT 2.01)
  53.      we are treating it as normal for the VRX / VE
  54.      file systems. I did not test for errno (EMINR)
  55.      directly, I reset it when say an fputs terminates
  56.      normally, and errno != EMINR.
  57.  
  58. *********************************************************************/
  59.  
  60. /* Includes */
  61. #include "ckcker.h"   /* Kermit definitions */
  62. #include "ckcdeb.h"   /* Typedefs, debug formats, etc */
  63. #include "vrx.h"      /* VRX SPUR File definitions */
  64. #include <ctype.h>    /* Character types */
  65. #include <stdio.h>    /* Standard i/o */
  66. #include <string.h>   /* String routines */
  67. #include <errno.h>
  68. #include <time.h>
  69.  
  70. char     *ckzsys = " NCR VRX/VE";
  71.  
  72. /*
  73.   Functions (n is one of the predefined file numbers from ckermi.h):
  74.  
  75.    zopeni(n,name)   -- Opens an existing file for input.
  76.    zopeno(n,name)   -- Opens a new file for output.
  77.    zclose(n)        -- Closes a file.
  78.    zchin(n,&c)      -- Gets the next character from an input file.
  79.    zsout(n,s)       -- Write a null-terminated string to output file, buffered.
  80.    zsoutl(n,s)      -- Like zsout, but appends a line terminator.
  81.    zsoutx(n,s,x)    -- Write x characters to output file, unbuffered.
  82.    zchout(n,c)      -- Add a character to an output file, unbuffered.
  83.    zchki(name)      -- Check if named file exists and is readable, return size.
  84.    zchko(name)      -- Check if named file can be created.
  85.    znewn(name,s)    -- Make a new unique file name based on the given name.
  86.    zdelet(name)     -- Delete the named file.
  87.    zxpand(string)   -- Expands the given wildcard string into a list of files.
  88.    znext(string)    -- Returns the next file from the list in "string".
  89.    zxcmd(cmd)       -- Execute the command in a lower fork.
  90.    zclosf()         -- Close input file associated with zxcmd()'s lower fork.
  91.    zrtol(n1,n2)     -- Convert remote filename into local form.
  92.    zltor(n1,n2)     -- Convert local filename into remote form.
  93.    zchdir(dirnam)   -- Change working directory.
  94.    zhome()          -- Return pointer to home directory name string.
  95.    zkself()         -- Kill self, log out own job.
  96.  */
  97.  
  98. /* Some systems define these symbols in include files, others don't... */
  99.  
  100. #ifndef MAXNAMLEN
  101. #define MAXNAMLEN 14              /* If still not defined... */
  102. #endif
  103.  
  104. #define MAXWLD 500
  105.  
  106. #define SRCLNLEN 82     /* source or control string max
  107.                            line length March 8, 1990      */
  108.  
  109. #define OPEN 1          /* resetopen processing           */
  110. #define CLOSE 0
  111.  
  112. /* Declarations */
  113.  
  114. extern long    time();
  115. extern int     debug();
  116. extern int     fncnv, send_id, recv_id, send_num, recv_num, recv_renum,
  117.                keep;
  118. extern int     server, recv_addnum, send_addnum, send_renum, deblog, binary;
  119. extern char    *sys_errlist[];
  120. extern int     sys_nerr;
  121. extern void    perror();
  122. /*  ^   extern int errno already declared in errno.h.
  123.     |   why they didnot declare these three are anyone's
  124.     |   guess.  March 7, 1990                           */
  125.  
  126. /* forward declarations */
  127. void    errhdlr(), resetopen();
  128. int     lenchk();
  129.  
  130. FILE *fp[ZNFILS] = { /* File pointers */
  131.      NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  132.  
  133.  
  134. static int     list_count;               /* # matches file names == 1 */
  135. static int     pid = 0;                  /* pid of child fork */
  136. static int     fcount;                   /* Number of files in wild group */
  137. static char    nambuf[MAXNAMLEN+2];     /* Buffer for a filename */
  138. char           *malloc(), *strcpy();           /* System functions */
  139.  
  140. static char     *mtchs[MAXWLD],          /* Matches found for filename */
  141.                **mtchptr;                /* Pointer to current match */
  142.  
  143. static char     file_type[9];            /* type of current file */
  144. static int     char_count;               /* number of characters written */
  145.  
  146. static int     spur_type;
  147.  
  148. /* 1=NCRL 2=BASIC 3=FORTB 4=FORTI 5=FORTF 6=FORTV 7=NEAT/3          */
  149. /* 8=NEAT/VS 9=NEAT/C 10=COBOL 11=COBOL/6 12=COBOL/7 13=COBOL/8     */
  150. /* 14=HEADCS 15=PROC,16=PROCN,17=COBOL1,18=COBOL1/6 19=COBOL1/7     */
  151. /* 20=COBOL1/8 21=COBOL4                                            */
  152.  
  153. static char    language[7];
  154. static int     suffix;
  155. static int     spur_eof = 0;
  156. static int     linenumber;
  157. static char    spur_data[400];        /* Area to hold packet data */
  158. static char    *nxtspur_data;
  159. static char    pcard[100];            /* VRX Control String header record */
  160.  
  161. static int     objopen = CLOSE;       /* incomplete object files left
  162.                                          open by aborted transfers       */
  163. static char    fn_temp[10];           /* to DELETE incomplete files
  164.                                          leftover from interuptions   */
  165.  
  166. /*  Z K S E L F  --  Kill Self: log out own job, if possible.  */
  167.  
  168. /* Note, should get current pid, but if your system doesn't have */
  169. /* getppid(), then just kill(0,9)...  */
  170.  
  171. zkself()
  172. {                    /* For "bye", but no guarantee! */
  173.      return(0);
  174. }
  175.  
  176.  
  177. /*  Z O P E N I  --  Open an existing file for input. */
  178.  
  179. zopeni(n, name)
  180. int     n;
  181. char     *name;
  182. {
  183.      char     buff[100];
  184.  
  185.      if (deblog) {
  186.           debug(F111, " zopeni", name, n);
  187.           debug(F101, "  fp", "", (int) fp[n]);
  188.      }
  189.  
  190.      if (n == ZIFILE)
  191.           resetopen();
  192.  
  193.      if (access(name, 0) != 0) {
  194.           errhdlr("zopeni");
  195.           fprintf(stderr,"file does not exist: %s\n",name);
  196.           return(-1);
  197.      }
  198.  
  199.      if ((suffix == BINARY || suffix == L_BINARY)
  200.          && !(binary) && (n == ZIFILE)) {
  201.           errhdlr("file mismatch see STDERR");
  202.           fprintf(stderr,"FILE TYPE is set to TEXT\n");
  203.           fprintf(stderr,"BINARY file type requested\n");
  204.           fprintf(stderr,"set file type to binary 8\n");
  205.           fprintf(stderr,"file transport will proceed\n");
  206.           return(-1);
  207.      }
  208.  
  209.      if (chkfn(n) != 0)
  210.           return(0);
  211.  
  212.      if (n == ZSYSFN || n == ZSTDIO)      /* Input from a system function
  213.                                              or stdio                     */
  214.           return(0);                      /* VRX invailid */
  215.  
  216.      /*
  217.        * VKERMIT code:
  218.        * Special handling open required for object files on NCR's VRX/E
  219.        */
  220.  
  221.      if (*file_type == 'O' && n == ZIFILE) {
  222.  
  223.           /* note difference in return numbers for voopen and zopen */
  224.  
  225.           if (voopeni(n, name) == 0) {        /* OK */
  226.                fp[n] = (FILE *) 1; /* bogus fp to keep ckermit happy */
  227.                strcpy(fn_temp, name);
  228.                objopen = OPEN;
  229.                fprintf(stderr, "downloading to PC\n");
  230.                return(1);
  231.           } else {
  232.                errhdlr("zopeni vopeni bad outcome");
  233.                return(0);
  234.           }
  235.      }
  236.      /* end VKERMIT code */
  237.  
  238.       if (binary)
  239.            fp[n] = fopen(name, "rb");  /* Real binary file. */
  240.       else
  241.            fp[n] = fopen(name, "r");   /* Real file. */
  242.  
  243.      if (fp[n] == NULL) {
  244.           errhdlr("zopeni fp NULL see STDERR");
  245.           fprintf(stderr,"input file open failure: %s\n",name);
  246.           if (binary) {
  247.                 fprintf(stderr,"check V-Kermit set up...an input text file\n");
  248.                 fprintf(stderr,"can not be opened as a binary file\n");
  249.                 fprintf(stderr,"text files include source, control\n");
  250.                 fprintf(stderr,"string, and data file types...\n");
  251.           }
  252.      } else {
  253.           spur_data[0] = '\0';
  254.           nxtspur_data = &spur_data[0];
  255.           linenumber = INCREMENT;
  256.           spur_eof = 0;
  257.           strcpy(fn_temp, name);
  258.           fprintf(stderr, "downloading to PC\n");
  259.      }
  260.  
  261.      if (deblog)
  262.           debug(F111, " zopeni", name, (int) fp[n]);
  263.  
  264.      return((fp[n] != NULL) ? 1 : 0);
  265. }
  266.  
  267.  
  268. /*  Z O P E N O  --  Open a new file for output.  */
  269.  
  270. zopeno(n, name)
  271. int     n;
  272. char     *name;
  273. {
  274.  
  275.      if (deblog)
  276.           debug(F111, " zopeno", name, n);
  277.  
  278.      if (n == ZOFILE)
  279.           resetopen();
  280.  
  281.      if ((suffix == BINARY || suffix == L_BINARY)
  282.          && !(binary) && (n == ZOFILE)) {
  283.           errhdlr("file mismatch see STDERR");
  284.           fprintf(stderr,"FILE TYPE is set to TEXT\n");
  285.           fprintf(stderr,"BINARY file type requested\n");
  286.           fprintf(stderr,"set file type to binary 8\n");
  287.           fprintf(stderr,"file transport will proceed\n");
  288.           return(-1);
  289.      }
  290.  
  291.      if (chkfn(n) != 0)
  292.           return(0);
  293.  
  294.      if ((n == ZCTERM) || (n == ZSTDIO) ||
  295.          (n == ZSFILE))                   /* Terminal or standard output */
  296.                                           /* or SESIONLOG                */
  297.           return (0);                     /* Invalid for VRX             */
  298.  
  299.      /*
  300.         * VKERMIT code:
  301.         * Use special open for object files on NCR's VRX/E
  302.         */
  303.  
  304.      if (*file_type == 'O' && n == ZOFILE) {
  305.           /* note difference in return numbers in voopen and zopen */
  306.           if (voopeno(n, name) == 0) {
  307.                /* OK */ /* bogus file pointer to keep ckermit happy */
  308.                fp[n] = (FILE *) 1;
  309.                strcpy(fn_temp, name);
  310.                objopen = OPEN;
  311.                fprintf(stderr, "uploading from PC\n");
  312.                return(1);
  313.           } else {
  314.                errhdlr("voopeno can't open");
  315.                fprintf(stderr, "Error opening upload file %s\n",
  316.                        name);
  317.                return(0);
  318.           }
  319.      }
  320.      /* end VKERMIT code */
  321.  
  322.      /*
  323.            FCL references for the log files
  324.            April 5, 1990
  325.                                                   */
  326.  
  327.      switch (n) {
  328.          char     vtmp [45];
  329.  
  330.      case ZTFILE:
  331.           {
  332.                sprintf(vtmp, "LOGTRANS(NAME=%s)", name);
  333.                fp[n] = fopen(vtmp, "w");
  334.           }
  335.           break;
  336.  
  337.      case ZDFILE:
  338.           {
  339.                sprintf(vtmp, "LOGDEBUG(NAME=%s)", name);
  340.                fp[n] = fopen(vtmp, "w");
  341.           }
  342.           break;
  343.  
  344.      case ZPFILE:
  345.           {
  346.                sprintf(vtmp, "LOGPACKET(NAME=%s)", name);
  347.                fp[n] = fopen(vtmp, "w");
  348.           }
  349.           break;
  350.  
  351.      default:
  352.  
  353.           if (binary && n == ZOFILE)
  354.                fp[n] = fopen(name, "wb");
  355.           else
  356.                fp[n] = fopen(name, "w");
  357.  
  358.           if (fp[n] != NULL) {
  359.                strcpy(fn_temp, name);
  360.                fprintf(stderr, "uploading from PC\n");
  361.           }
  362.           else {
  363.                errhdlr("zopeno can't open");
  364.                fprintf(stderr, "Error opening: %s\n", name);
  365.                return (0);
  366.      }
  367.           break;
  368.  
  369.      }
  370.  
  371.      if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) {
  372.           fputc(0, fp[n]);    /* space count = 0 on pcard */
  373.  
  374.           if (ferror(fp[n]) != 0 && errno != EMAXR && errno !=
  375.               EMINR) {
  376.                errhdlr("zopeno PCARD");
  377.                fprintf(stderr, "write error: space count PCARD\n");
  378.                return(0);
  379.           } else
  380.                errno = 0;  /*    reset errno = EMAXR for pcard write
  381.                                  no big deal happens half the time
  382.                                  errno EMAXR is the message Maximum
  383.                                  record length error (line truncated)
  384.                                  April 12, 1990
  385.  
  386. */
  387.  
  388.           if (zsoutl(n, pcard) == -1)
  389.                return (0);
  390.           char_count = 0;
  391.      }
  392.  
  393.      spur_data[0] = '\0';
  394.      nxtspur_data = &spur_data[0];
  395.      linenumber = INCREMENT;
  396.      if (deblog)
  397.           debug(F101, " fp[n]", "", (int) fp[n]);
  398.  
  399.      return((fp[n] != NULL) ? 1 : 0);
  400. }
  401.  
  402.  
  403. /*  Z C L O S E  --  Close the given file.  */
  404.  
  405. /*  Returns 0 if arg out of range, 1 if successful, -1 if close failed.  */
  406.  
  407. zclose(n)
  408. int     n;
  409. {
  410.      int     x;
  411.  
  412.      if (chkfn(n) < 1)
  413.           return(0); /* Check range of n */
  414.  
  415.      /*
  416.      * VKERMIT code:
  417.      * Use special close for NCR's VRX/E object files
  418.      */
  419.  
  420.      if (*file_type == 'O' && (n == ZIFILE || n == ZOFILE)) {
  421.           if (voclose(n) == 0) {
  422.                fp[n] = NULL;             /* March 7, 1990 */
  423.                objopen = CLOSE;
  424.                return(1);
  425.           } else {
  426.                fp[n] = NULL;
  427.                objopen = CLOSE;
  428.                return(-1);
  429.           }
  430.      }
  431.      /* end VKERMIT code */
  432.  
  433.      if ((fp[n] != stdin) && (fp[n] != stdout))
  434.          x = fclose(fp[n]);
  435.  
  436.      fp[n] = NULL;
  437.  
  438.      if (x == EOF) {
  439.          errhdlr("zclose");
  440.          fprintf(stderr,"Can't close file fclose returned: EOF\n");
  441.      }
  442.  
  443.      strcpy(fn_temp, "\0");
  444.  
  445.      return((x == EOF) ? -1 : 1);
  446. }
  447.  
  448.  
  449. /*  Z C H I N  --  Get a character from the input file.  */
  450.  
  451. /*  Returns -1 if EOF, 0 otherwise with character returned in argument  */
  452. /*  removes NULL and DEL characters in Control String and Source files */
  453.  
  454. zchin(n, c)
  455. int     n;
  456. char     *c;
  457. {
  458.      int     a;
  459.      int     i = 10;
  460.  
  461.      if (*file_type == 'S' || *file_type == 'C') {
  462.           if (*nxtspur_data == '\0') {
  463.                spur_data[0] = '\0';
  464.                switch (zsreci(n)) {
  465.                case 0:
  466.                     spur_eof++;
  467.                     break;
  468.                case 1:
  469.                     break;
  470.                case -1:
  471.                     return(-1);
  472.                }
  473.                if ((spur_eof) && (strlen(spur_data) == 0))
  474.                     return(-1);
  475.                nxtspur_data = &spur_data[0];
  476.           }
  477.           a = *nxtspur_data++;
  478.  
  479.      } else if (*file_type == 'O') {
  480.  
  481.           /* VKERMIT code for VRX/E object files */
  482.  
  483.           /* vogetc returns -1 on end of file and also on
  484.              error conditions after outputing an appropriate
  485.              error message. */
  486.  
  487.           if ((a = vogetc(n)) == -1)
  488.                return(-1);
  489.  
  490.      } else {
  491.  
  492.           if (chkfn(n) < 1)   /* check file address */
  493.                return(-1);
  494.  
  495.           a = getc(fp[n]);  /* place character in a */
  496.  
  497.           if (ferror(fp[n]) != 0) {
  498.                errhdlr("zchin");
  499.                fprintf(stderr, "read error: zchin\n");
  500.                return(-1);
  501.           }
  502.  
  503.  
  504.  
  505.           if (a == EOF)    /* if EOF, return -1    */
  506.                return(-1);
  507.      }
  508.      *c = a & 0xFF;   /* strip top bit     */
  509.  
  510.      return(0);
  511. }
  512.  
  513.  
  514. /*  Z S O U T  --  Write a string to the given file, buffered.  */
  515.  
  516. zsout(n, s)
  517. int     n;
  518. char     *s;
  519. {
  520.  
  521.      if (chkfn(n) < 1)
  522.           return(-1);
  523.  
  524.      if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) {
  525.           char     *sptr;
  526.           sptr = s;
  527.           if (sptr == NULL)
  528.                return(0);
  529.           while (*sptr++ != '\0') {
  530.                if (*sptr == '\n') {
  531.                     if (putc('\377', fp[n]) == EOF) {
  532.                          errhdlr("zsout/377");
  533.                          return((ferror(fp[n]) == 0) ?
  534.                              0 : -1);
  535.                     }
  536.                     if (putc('\n', fp[n]) == EOF) {
  537.                          errhdlr("zsout NL");
  538.                          return((ferror(fp[n]) == 0) ?
  539.                              0 : -1);
  540.                     }
  541.                     if (putc('\000', fp[n]) == EOF) {
  542.                          errhdlr("zsout/000");
  543.                          return((ferror(fp[n]) == 0) ?
  544.                              0 : -1);
  545.                     }
  546.                } else if (putc(*sptr, fp[n]) == EOF) {
  547.                     errhdlr("zsout/*sptr");
  548.                     return((ferror(fp[n]) == 0) ? 0 : -1);
  549.                }
  550.           }
  551.      } else if (fputs(s, fp[n]) == NULL) {
  552.           errhdlr("zsout/fputs");
  553.           return((ferror(fp[n]) == 0) ? 0 : -1);
  554.      }
  555.      return(0);
  556. }
  557.  
  558.  
  559. /*  Z S O U T L  --  Write string to file, with line terminator, buffered  */
  560.  
  561. zsoutl(n, s)
  562. int     n;
  563. char     *s;
  564. {
  565.      char     *ptr;
  566.  
  567.      if (chkfn(n) < 1)
  568.           return(-1);
  569.  
  570.      if (lenchk(s, n)) {
  571.  
  572.           switch (spur_type) {
  573.           case 9:
  574.           case 11:
  575.                errhdlr("zsoutl: writing ln > max len");
  576.                fprintf(stderr, "writing line > %d char\n",
  577.                    SRCLNLEN + 1);
  578.                fprintf(stderr, "line length was %d\n", strlen(s));
  579.                fprintf(stderr, "%s\n", s);
  580.                return(-1);
  581.           default:
  582.                errhdlr("zsoutl: writing ln > max len");
  583.                fprintf(stderr, "writing line > %d char\n",
  584.                    SRCLNLEN);
  585.                fprintf(stderr, "line length was %d\n", strlen(s));
  586.                fprintf(stderr, "%s\n", s);
  587.                return(-1);
  588.           }
  589.      }
  590.  
  591.      if (fputs(s, fp[n]) == NULL) {
  592.           errhdlr("zsoutl/fputs");
  593.           return(-1);
  594.      }
  595.  
  596.      if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) {
  597.  
  598.           if (putc('\377', fp[n]) == EOF) {  /* end sentinal character */
  599.                errhdlr("zsoutl/377");
  600.                return((ferror(fp[n]) == 0) ? 0 : -1);
  601.           }
  602.  
  603.           if (putc('\n', fp[n]) == EOF) {
  604.                errhdlr("zsoutl/LN CS");
  605.                return((ferror(fp[n]) == 0) ? 0 : -1);
  606.           }
  607.      } else if (putc('\n', fp[n]) == EOF) {
  608.           errhdlr("zsoutl/LN");
  609.           return((ferror(fp[n]) == 0) ? 0 : -1);
  610.      }
  611.      return(0);
  612. }
  613.  
  614.  
  615. /*  Z S O U T X  --  Write x characters to file, unbuffered.  */
  616.  
  617. zsoutx(n, s, x)
  618. int     n, x;
  619. char     *s;
  620. {
  621.  
  622.      int     i;
  623.  
  624.      if (chkfn(n) < 1)
  625.           return(-1);
  626.  
  627.      if ((i = write(fp[n]->_file, s, x)) == -1) {
  628.           errhdlr("zsoutx");
  629.           return(-1);
  630.      } else {
  631.           return(i);
  632.      }
  633.  
  634. }
  635.  
  636.  
  637. /*  Z C H O U T  --  Add a character to the given file.  */
  638.  
  639. /*  Should return 0 or greater on success, -1 on failure (e.g. disk full)  */
  640.  
  641. zchout(n, c)
  642. int     n;
  643. char     c;
  644. {
  645.      int     i;
  646.  
  647.      if (chkfn(n) < 1)
  648.           return(-1);
  649.  
  650.      /* April 5, 1990
  651.  
  652.           This switch statement is courtesy of the corruption
  653.           in ZSFILE (sessionlog).
  654.  
  655.           We now check every character we write to verify
  656.           it is a printable character.
  657.  
  658.           If SET FILE TYPE TEXT is set: (int binary == 0)
  659.              we verify character for ZOFILE (output file)
  660.  
  661.           IF a LOG file we verify whether binary set or
  662.           not.
  663.  
  664.                 if a nonprintable character is encountered
  665.                 output to stderr
  666.                 return -1
  667.  
  668.        */
  669.  
  670.      switch (n) {
  671.                char     err_tmp[35];
  672.  
  673.      case ZOFILE:
  674.           if (binary)
  675.                break;
  676.           if (c == 0x1A)
  677.                return(0);
  678.           if (!(isprint(c) || isspace(c))) {
  679.                sprintf(err_tmp, "zchout nonprint char: %X",
  680.                     c);
  681.                errhdlr(err_tmp);
  682.                return(-1);
  683.           }
  684.           break;
  685.  
  686.      case ZSFILE:
  687.      case ZTFILE:
  688.      case ZDFILE:
  689.      case ZPFILE:
  690.           if (!(isprint(c) || isspace(c))) {
  691.                sprintf(err_tmp, "zchout: nonprint char: %X",
  692.                     c);
  693.                errhdlr(err_tmp);
  694.                fprintf(stderr, "error writing log file: %X\n",
  695.                     n);
  696.                return(-1);
  697.           }
  698.           break;
  699.      default:
  700.           /* we should never execute this BUT
  701.              if I do not put in in I'll be
  702.              sorry later
  703.                                                           */
  704.           errhdlr("zchout dead code");
  705.           fprintf(stderr, "Executing in dead code area: %d\n",
  706.                n);
  707.           return(-1);
  708.      }
  709.  
  710.      if (n == ZSFILE)       /* Use unbuffered for session log */
  711.           return(write(fp[n]->_file, &c, 1));
  712.  
  713.      else {    /* Buffered for everything else */
  714.  
  715.           if (*file_type == 'O' && n == ZOFILE)
  716.                return(voputc(c, n));
  717.           else if ((*file_type == 'C' || *file_type == 'S') &&
  718.               n == ZOFILE) {
  719.  
  720.                if (c == '\n') {
  721.                     if (zsreco(n) == -1)
  722.                          return (-1);
  723.                     spur_data[0] = '\0';
  724.                     nxtspur_data = &spur_data[0];
  725.  
  726.                } else {
  727.                     *nxtspur_data++ = c;
  728.                     *nxtspur_data = '\0';
  729.                }
  730.                return(0);
  731.  
  732.           } else {
  733.                if (putc(c, fp[n]) == EOF) {
  734.                                             /* If true, maybe an error */
  735.                          errhdlr("ZCHOUT");
  736.                                             /* Check to make sure */
  737.                          return((ferror(fp[n]) == 0) ?
  738.                              0 : -1);
  739.                }
  740.           }
  741.      }
  742. }
  743.  
  744.  
  745. /*  C H K F N  --  Internal function to verify file number is ok  */
  746.  
  747. /*
  748.  Returns:
  749.   -1: File number n is out of range
  750.    0: n is in range, but file is not open
  751.    1: n in range and file is open
  752. */
  753.  
  754. chkfn(n)
  755. int     n;
  756. {
  757.  
  758.      switch (n) {
  759.      case ZCTERM:
  760.      case ZSTDIO:
  761.      case ZIFILE:
  762.      case ZOFILE:
  763.      case ZDFILE:
  764.      case ZTFILE:
  765.      case ZPFILE:
  766.      case ZSFILE:
  767.      case ZSYSFN:
  768.           break;
  769.      default:
  770.           if (deblog)
  771.                debug(F101, "chkfn: file number out of range",
  772.                     "", n);
  773.           errhdlr("chkfn");
  774.           fprintf(stderr, "File number out of range - %d\n", n);
  775.           return(-1);
  776.      }
  777.  
  778.      return( (fp[n] == NULL) ? 0 : 1 );
  779. }
  780.  
  781.  
  782. /*  Z C H K I  --  Check if input file exists and is readable  */
  783.  
  784. /*
  785.   Returns:
  786.    >= 0 if the file can be read (returns the size).
  787.      -1 if file doesn't exist or can't be accessed,
  788.      -2 if file exists but is not readable (e.g. a directory file).
  789.      -3 if file exists but protected against read access.
  790. */
  791.  
  792.  
  793. long     zchki(name)
  794. char     *name;
  795. {
  796.  
  797.      FILE * fptr;
  798.      long     length;
  799.  
  800.      if (access(name, 0) != 0)
  801.           return(-1);
  802.  
  803.      if ((fptr = fopen(name, "r")) != NULL) {
  804.           fseek(fptr, 0L, 2);
  805.           length = ftell(fptr);
  806.           close(fptr);
  807.           return(length);
  808.      } else
  809.           return(-1);
  810. }
  811.  
  812.  
  813. /*  Z C H K O  --  Check if output file can be created  */
  814.  
  815. /*
  816.  Returns -1 if write permission for the file would be denied, 0 otherwise.
  817. */
  818. zchko(name)
  819. char     *name;
  820. {
  821.      return(0);
  822. }
  823.  
  824.  
  825. /*  Z D E L E T  --  Delete the named file.  */
  826.  
  827. zdelet(name)
  828. char     *name;
  829. {
  830.      unlink(name);
  831. }
  832.  
  833.  
  834. /*  Z R T O L  --  Convert remote filename into local form  */
  835.  
  836. /*
  837.  *  For VRX, this means:
  838.  *                 truncating to 8/10 characters
  839.  *                 changing lowercase to upper case
  840.  *                 changing periods (.) to underscore (_)
  841.  *  If the filename contains an extension of the form: filename.extension
  842.  *  then the parameter "type" is set the file type. If there is no extension,
  843.  *  "type" is set to type DATA.
  844.  *  possible extensions are:
  845.  *     .OBJ - object files
  846.  *     .BIN - binary data file
  847.  *     .CS  - Control String file
  848.  *     .PRO - Procedure file
  849.  *     .DAT - default data file
  850.  *     .NCR - NCRL SPUR file
  851.  *     .BAS - BASIC SPUR file
  852.  *     .FB  - Fortran/B SPUR file
  853.  *     .FI  - Fortran/I SPUR file
  854.  *     .FF  - Fortran/F SPUR file
  855.  *     .FV  - Fortran/V SPUR file
  856.  *     .N3  - NEAT/3 SPUR file
  857.  *     .NVS - NEAT/VS SPUR file
  858.  *     .NC  - NEAT/C SPUR file
  859.  *     .CO  - COBOL/0 SPUR file
  860.  *     .CO6 - COBOL/6 SPUR file
  861.  *     .CO7 - COBOL/7 SPUR file
  862.  *     .CO1 - COBOL1/0 SPUR file
  863.  *     .C16 - COBOL1/6 SPUR file
  864.  *     .C17 - COBOL1/7 SPUR file
  865.  *     .C18 - COBOL1/8 SPUR file
  866.  *     .CO4 - COBOL4 SPUR file
  867.  *     .D100 - fixed length data file with 100 byte records
  868.  *     .D1-100 - variable length data file with 1 to 100 byte records
  869.  */
  870.  
  871. #define REC_SIZE(ptr) { for(fptr = ((ptr) + 1); *fptr != '\0'; fptr++) {\
  872.     if (*fptr == '-') *fptr = '/';\
  873.     else if (*fptr < '0' || *fptr > '9') break;\
  874.    }\
  875.    if (*fptr == '\0') record_sized++;\
  876.         }
  877.  
  878. zrtol(name, name2)
  879. char     *name, *name2;
  880. {
  881.      char    *ftype, *subtype, *fptr, *namep, *strrchr();
  882.      int     suffix_len, i, n, max, record_sized = 0;
  883.      long    stamp;
  884.  
  885.      spur_type = 0;
  886.      suffix = 0;
  887.      *name2 = '\0';
  888.      if (deblog)
  889.           debug(F100, "funct: zrtol    ", "", 0);
  890.  
  891.      /* time stamp stderr output */
  892.      /* May 4, 1990              */
  893.      stamp = time((long *) 0);
  894.      fprintf(stderr, "\n%s", ctime(&stamp));
  895.  
  896.      fprintf(stderr, "name = <%s>\n", name);
  897.  
  898.      if ((ftype = strrchr(name, '.')) == NULL) {
  899.           strcpy(file_type, "DATAFILE");             /* peg 0190 */
  900.           max = 10;
  901.  
  902.      } else {
  903.           suffix_len = strlen(++ftype);
  904.           for (i = 0; i < 4; i++) {
  905.                if (i >= suffix_len)
  906.                     n = 0;
  907.                else
  908.                     n = ftype[i];
  909.                suffix = (suffix << 8) | n;
  910.           }
  911.           switch (suffix) {
  912.           case L_OBJECT:
  913.           case OBJECT:
  914.                strcpy(file_type, "OBJFILE");  /* peg 0190 */
  915.                max = 8;
  916.                *(ftype - 1) = '\0';
  917.                break;
  918.           case L_BINARY:
  919.           case BINARY:
  920.                strcpy(file_type, "DATAFILE");  /* peg 0190 */
  921.                max = 10;
  922.                *(ftype - 1) = '\0';
  923.                break;
  924.           case L_DATA:
  925.           case DATA:
  926.                strcpy(file_type, "DATAFILE");
  927.                max = 10;
  928.                *(ftype - 1) = '\0';
  929.                break;
  930.           case L_NCRL:
  931.           case NCRL:
  932.                strcpy(file_type, "SRCFILE");  /* peg 0190 */
  933.                spur_type = 1;
  934.                strcpy(language, "NCRL  ");
  935.                max = 8;
  936.                *(ftype - 1) = '\0';
  937.                break;
  938.           case L_BASIC:
  939.           case BASIC:
  940.                strcmp(file_type, "SRCFILE");  /* peg 0190 */
  941.                spur_type = 2;
  942.                strcpy(language, "BASIC ");
  943.                max = 8;
  944.                *(ftype - 1) = '\0';
  945.                break;
  946.           case L_FORTB:
  947.           case FORTB:
  948.                strcpy(file_type, "SRCFILE");  /* peg 0190 */
  949.                spur_type = 3;
  950.                strcpy(language, "FORT/B");
  951.                max = 8;
  952.                *(ftype - 1) = '\0';
  953.                break;
  954.           case L_FORTI:
  955.           case FORTI:
  956.                strcpy(file_type, "SRCFILE"); /* peg 0190 */
  957.                spur_type = 4;
  958.                strcpy(language, "FORT/I");
  959.                max = 8;
  960.                *(ftype - 1) = '\0';
  961.                break;
  962.           case L_FORTF:
  963.           case FORTF:
  964.                strcpy(file_type, "SRCFILE");    /* peg 0190 */
  965.                spur_type = 5;
  966.                strcpy(language, "FORT/F");
  967.                max = 8;
  968.                *(ftype - 1) = '\0';
  969.                break;
  970.           case L_FORTV:
  971.           case FORTV:
  972.                strcpy(file_type, "SRCFILE");   /* peg 0190 */
  973.                spur_type = 6;
  974.                strcpy(language, "FORT/V");
  975.                max = 8;
  976.                *(ftype - 1) = '\0';
  977.                break;
  978.           case L_NEAT3:
  979.           case NEAT3:
  980.                strcpy(file_type, "SRCFILE");  /* peg 0190 */
  981.                spur_type = 7;
  982.                strcpy(language, "NEAT/3");
  983.                max = 8;
  984.                *(ftype - 1) = '\0';
  985.                break;
  986.           case L_NEATVS:
  987.           case NEATVS:
  988.                strcpy(file_type, "SRCFILE");   /* peg 0190 */
  989.                spur_type = 8;
  990.                strcpy(language, "NEATVS");
  991.                max = 8;
  992.                *(ftype - 1) = '\0';
  993.                break;
  994.           case L_NEATC:
  995.           case NEATC:
  996.                strcpy(file_type, "SRCFILE");
  997.                spur_type = 9;
  998.                strcpy(language, "NEAT/C");
  999.                max = 8;
  1000.                *(ftype - 1) = '\0';
  1001.                break;
  1002.           case L_COBOL:
  1003.           case COBOL:
  1004.                strcpy(file_type, "SRCFILE");   /* peg 0190 */
  1005.                spur_type = 10;
  1006.                strcpy(language, "COBOL ");
  1007.                max = 8;
  1008.                *(ftype - 1) = '\0';
  1009.                break;
  1010.           case L_COBOL6:
  1011.           case COBOL6:
  1012.                strcpy(file_type, "SRCFILE");   /* peg 0190 */
  1013.                spur_type = 11;
  1014.                strcpy(language, "COBOL ");
  1015.                max = 8;
  1016.                *(ftype - 1) = '\0';
  1017.                break;
  1018.           case L_COBOL7:
  1019.           case COBOL7:
  1020.                strcmp(file_type, "SRCFILE");  /* peg 0190 */
  1021.                spur_type = 12;
  1022.                strcpy(language, "COBOL ");
  1023.                max = 8;
  1024.                *(ftype - 1) = '\0';
  1025.                break;
  1026.           case L_COBOL8:
  1027.           case COBOL8:
  1028.                strcpy(file_type, "SRCFILE");  /* peg 0190 */
  1029.                spur_type = 13;
  1030.                strcpy(language, "COBOL ");
  1031.                max = 8;
  1032.                *(ftype - 1) = '\0';
  1033.                break;
  1034.           case L_CS:
  1035.           case CS:
  1036.                strcpy(file_type, "CSFILE");   /* peg 0190 */
  1037.                spur_type = 14;
  1038.                strcpy(language, "HEADCS");
  1039.                max = 8;
  1040.                *(ftype - 1) = '\0';
  1041.                break;
  1042.           case L_PROC:
  1043.           case PROC:
  1044.                strcpy(file_type, "CSFILE");    /* peg 0190 */
  1045.                spur_type = 15;
  1046.                strcpy(language, "HEADCS");
  1047.                max = 8;
  1048.                *(ftype - 1) = '\0';
  1049.                break;
  1050.           case L_PROCN:
  1051.           case PROCN:
  1052.                strcmp(file_type, "CSFILE");    /* peg 0190 */
  1053.                spur_type = 16;
  1054.                strcpy(language, "HEADCS");
  1055.                max = 8;
  1056.                *(ftype - 1) = '\0';
  1057.                break;
  1058.           case L_COBOL1:
  1059.           case COBOL1:
  1060.                strcpy(file_type, "SRCFILE");   /* peg 0190 */
  1061.                spur_type = 17;
  1062.                strcpy(language, "COBOL1");
  1063.                max = 8;
  1064.                *(ftype - 1) = '\0';
  1065.                break;
  1066.           case L_COBOL16:
  1067.           case COBOL16:
  1068.                strcpy(file_type, "SRCFILE");    /* peg 0190 */
  1069.                spur_type = 18;
  1070.                strcpy(language, "COBOL1");
  1071.                max = 8;
  1072.                *(ftype - 1) = '\0';
  1073.                break;
  1074.           case L_COBOL17:
  1075.           case COBOL17:
  1076.                strcpy(file_type, "SRCFILE");   /* peg 0190 */
  1077.                spur_type = 19;
  1078.                strcpy(language, "COBOL1");
  1079.                max = 8;
  1080.                *(ftype - 1) = '\0';
  1081.                break;
  1082.           case L_COBOL18:
  1083.           case COBOL18:
  1084.                strcpy(file_type, "SRCFILE");    /* peg 0190 */
  1085.                spur_type = 20;
  1086.                strcpy(language, "COBOL1");
  1087.                max = 8;
  1088.                *(ftype - 1) = '\0';
  1089.                break;
  1090.           case L_COBOL4:
  1091.           case COBOL4:
  1092.                strcpy(file_type, "SRCFILE");   /* peg 0190 */
  1093.                spur_type = 21;
  1094.                strcpy(language, "COBOL4");
  1095.                max = 8;
  1096.                *(ftype - 1) = '\0';
  1097.                break;
  1098.           default:
  1099.                if (*ftype == 'B' || *ftype == 'b') {
  1100.                     suffix = BINARY;
  1101.                     if (*(ftype + 1) != '\0')
  1102.                          REC_SIZE(ftype);
  1103.  
  1104.                     if (record_sized) {
  1105.                          *(ftype) = '\0';
  1106.                     }
  1107.                }
  1108.  
  1109.                if ((*ftype == 'd') || (*ftype == 'D')) {
  1110.                     if (*(ftype + 1) != '\0')
  1111.                          REC_SIZE(ftype);
  1112.  
  1113.                     if (record_sized)
  1114.                          *(ftype) = '\0';
  1115.  
  1116.                }
  1117.                strcpy(file_type, "DATAFILE");
  1118.                max = 10;
  1119.                break;
  1120.           }
  1121.      }
  1122.  
  1123.      /* convert periods to underscores, lowercase to uppercase */
  1124.  
  1125.      namep = name;
  1126.  
  1127.      for (i = 0; *namep != '\0', i < max; namep++, i++) {
  1128.  
  1129.           if (*namep == '.')
  1130.                *namep = '_';
  1131.           if (*namep == '~')
  1132.                *namep = 'X';
  1133.           if (*namep == '$')
  1134.                *namep = '_';
  1135.           else if (islower(*namep) && fncnv)
  1136.                toupper(*namep);
  1137.      }
  1138.      *namep = '\0';
  1139.  
  1140.      if (record_sized) {
  1141.           /*
  1142.                            first the recordsize is truncated
  1143.                            now the displayed name contains
  1144.                            additional underscores, this fix
  1145.                            truncates everything past the
  1146.                            FINAL underscore
  1147.                            April 13, 1990
  1148.                                                                */
  1149.           char     *s_tmp;
  1150.  
  1151.           s_tmp = strrchr(name, '_');
  1152.           if (s_tmp != NULL)
  1153.                *s_tmp = '\0';
  1154.  
  1155.           sprintf(name2, "%s(NAME=%s,RECORDSIZE=%s)", file_type,
  1156.                              name, (ftype + 1));
  1157.      }  else
  1158.           sprintf(name2, "%s(NAME=%s)", file_type, name);
  1159.  
  1160.      if (*file_type == 'S' || *file_type == 'C')
  1161.           zpcrd(name);
  1162.  
  1163.      if (spur_type != 0)
  1164.           fprintf(stderr, "final name2 = <%s>  spur_type=%d\n",
  1165.                              name2, spur_type);
  1166.      else
  1167.           fprintf(stderr, "final name2 = <%s>\n", name2);
  1168.  
  1169.      if (deblog)
  1170.           debug(F110, "zrtol:", name2, 0);
  1171. }
  1172.  
  1173.  
  1174. /*  Z L T O R  --  Local TO Remote */
  1175.  
  1176. /*  Convert filename from local format to common (remote) form.  */
  1177.  
  1178. zltor(name, name2)
  1179. char     *name, *name2;
  1180. {
  1181.      char     work[100], *cp, *pp;
  1182.      int     dc = 0;
  1183.  
  1184.      if (deblog) {
  1185.           debug(F100, "funct: zltor    ", "", 0);
  1186.           debug(F110, "zltor", name, 0);
  1187.      }
  1188.      pp = work;
  1189.  
  1190.      for (cp = name; *cp != '\0'; cp++) { /* strip path name */
  1191.  
  1192.           if (*cp == '/') {
  1193.                dc = 0;
  1194.                pp = work;
  1195.           }  else if (islower(*cp))
  1196.                *pp++ = toupper(*cp); /* Uppercase letters */
  1197.  
  1198.           else if (*cp == '~')
  1199.                *pp++ = 'X'; /* Change tilde to 'X' */
  1200.  
  1201.           else if (*cp == '#')
  1202.                *pp++ = 'X'; /* Change number sign to 'X' */
  1203.  
  1204.                /*          else if (*cp == '.')
  1205.                *pp++ = '_';  */ /* & extra dots */
  1206.  
  1207.           else if (*cp == '$')
  1208.                *pp++ = '_';
  1209.  
  1210.           else
  1211.                *pp++ = *cp;
  1212.      }
  1213.      *pp = '\0';                        /* Tie it off. */
  1214.      cp = name2;                        /* If nothing before dot, */
  1215.      if (*work == '.')
  1216.           *cp++ = 'X';     /* insert 'X' */
  1217.      strcpy(cp, work);
  1218.      if (deblog)
  1219.           debug(F110, "zltor<name2>", name2, 0);
  1220. }
  1221.  
  1222.  
  1223. /*  Z C H D I R  --  Change directory  */
  1224.  
  1225. zchdir(dirnam)
  1226. char     *dirnam;
  1227. {
  1228.      /* not implemented */
  1229. }
  1230.  
  1231.  
  1232. /*  Z H O M E  --  Return pointer to user's home directory  */
  1233.  
  1234. char     *
  1235. zhome()
  1236. {
  1237.      return("home");
  1238. }
  1239.  
  1240.  
  1241. /*  Z G T D I R  --  Return pointer to user's current directory  */
  1242.  
  1243. char     *
  1244. zgtdir()
  1245. {
  1246.      return("(directory unknown)");
  1247. }
  1248.  
  1249.  
  1250. /*  Z X C M D -- Run a system command so its output can be read like a file */
  1251.  
  1252. zxcmd(comand)
  1253. char     *comand;
  1254. {
  1255.      return(0);               /* not implemented */
  1256. }
  1257.  
  1258.  
  1259. /*  Z C L O S F  - wait for the child fork to terminate and close the pipe. */
  1260.  
  1261. zclosf()
  1262. {
  1263.      int     wstat;
  1264.      if (deblog)
  1265.           debug(F100, "funct: zclosf   ", "", 0);
  1266.      fclose(fp[ZIFILE]);
  1267.      fp[ZIFILE] = fp[ZSYSFN] = NULL;
  1268.      while ((wstat = WAIT(0)) != pid && wstat != -1)
  1269.           ;
  1270.      return(1);
  1271. }
  1272.  
  1273.  
  1274. /*  Z X P A N D  --  Expand a wildcard string into an array of strings  */
  1275. /*
  1276.   Returns the number of files that match fn1, with data structures set up
  1277.   so that first file (if any) will be returned by the next znext() call.
  1278. */
  1279.  
  1280. zxpand(fn)
  1281. char     *fn;
  1282. {
  1283.      mtchs[0] = (char *) malloc(sizeof(char)*strlen(fn));
  1284.      strcpy(mtchs[0], fn);
  1285.      list_count = 1;
  1286.      return(1);
  1287. }
  1288.  
  1289.  
  1290. /*  Z N E X T  --  Get name of next file from list created by zxpand(). */
  1291. /*
  1292.  Returns >0 if there's another file, with its name copied into the arg string,
  1293.  or 0 if no more files in list.
  1294. */
  1295.  
  1296. znext(fn)
  1297. char     *fn;
  1298. {
  1299.      int     temp;
  1300.      temp = list_count;
  1301.      if (list_count)
  1302.           list_count = 0;
  1303.      strcpy(fn, mtchs[0]);
  1304.      return(temp);
  1305. }
  1306.  
  1307.  
  1308. /*  Z N E W N  --  Make a new name for the given file  */
  1309.  
  1310. znewn(fn, s)
  1311. char     *fn, **s;
  1312. {
  1313. }
  1314.  
  1315.  
  1316. /* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */
  1317.  
  1318. /*
  1319.  * The path structure is used to represent the name to match.
  1320.  * Each slash-separated segment of the name is kept in one
  1321.  * such structure, and they are linked together, to make
  1322.  * traversing the name easier.
  1323.  */
  1324.  
  1325. /*
  1326.  * splitpath:
  1327.  *  takes a string and splits the slash-separated portions into
  1328.  *  a list of path structures.  Returns the head of the list.  The
  1329.  *  structures are allocated by malloc, so they must be freed.
  1330.  *  Splitpath is used internally by the filename generator.
  1331.  *
  1332.  * Input: A string.
  1333.  * Returns: A linked list of the slash-separated segments of the input.
  1334.  */
  1335.  
  1336. struct path *
  1337. splitpath(p)
  1338. char     *p;
  1339. {
  1340. }
  1341.  
  1342.  
  1343. /*
  1344.  * fgen:
  1345.  *  This is the actual name generator.  It is passed a string,
  1346.  *  possibly containing wildcards, and an array of character pointers.
  1347.  *  It finds all the matching filenames and stores them into the array.
  1348.  *  The returned strings are allocated from a static buffer local to
  1349.  *  this module (so the caller doesn't have to worry about deallocating
  1350.  *  them); this means that successive calls to fgen will wipe out
  1351.  *  the results of previous calls.  This isn't a problem here
  1352.  *  because we process one wildcard string at a time.
  1353.  *
  1354.  * Input: a wildcard string, an array to write names to, the
  1355.  *        length of the array.
  1356.  * Returns: the number of matches.  The array is filled with filenames
  1357.  *          that matched the pattern.  If there wasn't enough room in the
  1358.  *     array, -1 is returned.
  1359.  * By: Jeff Damens, CUCCA, 1984.
  1360.  */
  1361.  
  1362. fgen(pat, resarry, len)    /* VRX version, no expansion of file names */
  1363. char     *pat, *resarry[];
  1364. int     len;
  1365. {
  1366. }
  1367.  
  1368.  
  1369. /* traverse:
  1370.  *  Walks the directory tree looking for matches to its arguments.
  1371.  *  The algorithm is, briefly:
  1372.  *   If the current pattern segment contains no wildcards, that
  1373.  *   segment is added to what we already have.  If the name so far
  1374.  *   exists, we call ourselves recursively with the next segment
  1375.  *   in the pattern string; otherwise, we just return.
  1376.  *
  1377.  *   If the current pattern segment contains wildcards, we open the name
  1378.  *   we've accumulated so far (assuming it is really a directory), then read
  1379.  *   each filename in it, and, if it matches the wildcard pattern segment, add
  1380.  *   that filename to what we have so far and call ourselves recursively on the
  1381.  *   next segment.
  1382.  *
  1383.  *   Finally, when no more pattern segments remain, we add what's accumulated
  1384.  *   so far to the result array and increment the number of matches.
  1385.  *
  1386.  * Input: a pattern path list (as generated by splitpath), a string
  1387.  *   pointer that points to what we've traversed so far (this
  1388.  *   can be initialized to "/" to start the search at the root
  1389.  *   directory, or to "./" to start the search at the current
  1390.  *   directory), and a string pointer to the end of the string
  1391.  *   in the previous argument.
  1392.  * Returns: nothing.
  1393.  */
  1394. traverse(pl, sofar, endcur)
  1395. struct path *pl;
  1396. char     *sofar, *endcur;
  1397. {
  1398. }
  1399.  
  1400.  
  1401. /*
  1402.  * addresult:
  1403.  *  Adds a result string to the result array.  Increments the number
  1404.  *  of matches found, copies the found string into our string
  1405.  *  buffer, and puts a pointer to the buffer into the caller's result
  1406.  *  array.  Our free buffer pointer is updated.  If there is no
  1407.  *  more room in the caller's array, the number of matches is set to -1.
  1408.  * Input: a result string.
  1409.  * Returns: nothing.
  1410.  */
  1411.  
  1412. addresult(str)
  1413. char     *str;
  1414. {
  1415. }
  1416.  
  1417.  
  1418. iswild(str)
  1419. char     *str;
  1420. {
  1421.      char     c;
  1422.      if (deblog)
  1423.           debug(F100, "funct: iswild   ", "", 0);
  1424.      while ((c = *str++) != '\0')
  1425.           if (c == '*' || c == '?')
  1426.                return(1);
  1427.      return(0);
  1428. }
  1429.  
  1430.  
  1431. /*
  1432.  * match:
  1433.  *  pattern matcher.  Takes a string and a pattern possibly containing
  1434.  *  the wildcard characters '*' and '?'.  Returns true if the pattern
  1435.  *  matches the string, false otherwise.
  1436.  * by: Jeff Damens, CUCCA
  1437.  *
  1438.  * Input: a string and a wildcard pattern.
  1439.  * Returns: 1 if match, 0 if no match.
  1440.  */
  1441.  
  1442. match(pattern, string)
  1443. char     *pattern, *string;
  1444. {
  1445.      char     *psave, *ssave;   /* back up pointers for failure */
  1446.      psave = ssave = NULL;
  1447.      if (deblog)
  1448.           debug(F100, "funct: matck    ", "", 0);
  1449.      while (1) {
  1450.           for (; *pattern == *string; pattern++, string++)  /* skip first */
  1451.                if (*string == '\0')
  1452.                     return(1); /* end of strings, succeed */
  1453.           if (*string != '\0' && *pattern == '?') {
  1454.                pattern++;   /* '?', let it match */
  1455.                string++;
  1456.           } else if (*pattern == '*') { /* '*' ... */
  1457.                psave = ++pattern;  /* remember where we saw it */
  1458.                ssave = string;  /* let it match 0 chars */
  1459.           } else if (ssave != NULL && *ssave != '\0') { /* if not at end  */
  1460.                /* ...have seen a star */
  1461.                string = ++ssave;  /* skip 1 char from string */
  1462.                pattern = psave;  /* and back up pattern */
  1463.           } else
  1464.                return(0);  /* otherwise just fail */
  1465.      }
  1466. }
  1467.  
  1468.  
  1469. /*  Z P C R D  --  Make a pcard for a CSFILE or a SRCFILE  */
  1470.  
  1471. zpcrd(name)
  1472. char     *name;
  1473. {
  1474.      int     i;
  1475.  
  1476.      pcard[0] = '\0';
  1477.      strcat(pcard, "000000");
  1478.      if ((spur_type == 14) || (spur_type == 15) || (spur_type ==
  1479.          16)) {
  1480.           if (!recv_num && (spur_type == 16))
  1481.                spur_type = 15;
  1482.           strcat(pcard, "P");
  1483.           strcat(pcard, name);
  1484.           for (i = 0; i < (10 - strlen(name)); i++)
  1485.                strcat(pcard, " ");
  1486.           strcat(pcard, language);
  1487.           strcat(pcard, "                ");
  1488.           switch (spur_type) {
  1489.           case 14:
  1490.                strcat(pcard, "       ");
  1491.                break;
  1492.           case 15:
  1493.                strcat(pcard, "PROC-01");
  1494.                break;
  1495.           case 16:
  1496.                strcat(pcard, "PROC-07");
  1497.                break;
  1498.           }
  1499.           strcat(pcard, "                                  ");
  1500.      } else {
  1501.           strcat(pcard, "       ");
  1502.           strcat(pcard, "P");
  1503.           strcat(pcard, name);
  1504.           for (i = 0; i < (10 - strlen(name)); i++)
  1505.                strcat(pcard, " ");
  1506.           strcat(pcard, language);
  1507.           strcat(pcard, "             ");
  1508.           switch (spur_type) {
  1509.           case 10:
  1510.                strcat(pcard, "0");
  1511.                break;
  1512.           case 11:
  1513.                strcat(pcard, "6");
  1514.                break;
  1515.           case 12:
  1516.                strcat(pcard, "7");
  1517.                break;
  1518.           default:
  1519.                strcat(pcard, " ");
  1520.                break;
  1521.           }
  1522.           strcat(pcard, "                                    ");
  1523.      }
  1524. }
  1525.  
  1526.  
  1527. /*  Z S R E C I  --  Gather SPUR records for input  */
  1528.  
  1529. zsreci(n)
  1530. int     n;
  1531. {
  1532.      char     idfield[MAX_FIELD+2];
  1533.      char     line[LINE_LEN];
  1534.      char     tail[TAIL_LEN];
  1535.      char     oldnum[10];
  1536.      int     id_start = spur_info[MAX_SPURTYPE*ID_START + spur_type -1];
  1537.      int     id_len = spur_info[MAX_SPURTYPE*ID_LEN + spur_type -1];
  1538.      int     rec_len = spur_info[MAX_SPURTYPE*REC_LEN + spur_type -1];
  1539.      int     num_field_len =
  1540.      spur_info[MAX_SPURTYPE*NUM_FIELD_LEN + spur_type -1];
  1541.      int     spaces;
  1542.      int     length;
  1543.      int     i;
  1544.  
  1545.      if (deblog)
  1546.           debug(F111, "zsreci: ", "n", n);
  1547.  
  1548.      /****************************************************************
  1549.      *  Initialize the array 'spur_data' and begin to add to this   *
  1550.      *  array the "V-Kermit-prepared" records from the file fp[n].  *
  1551.      ****************************************************************/
  1552.  
  1553.      spur_data[0] = '\0';
  1554.  
  1555.      while (strlen(spur_data) < 315) {
  1556.           if ((spaces = fgetc(fp[n])) == EOF) {
  1557.                if (deblog)
  1558.                    fprintf(stderr, "zsreci: fgetc == EOF\n");
  1559.                return((ferror(fp[n]) == 0) ? 0 : -1);
  1560.           }
  1561.  
  1562.           if (fgets(line, LINE_LEN, fp[n]) == NULL) {
  1563.                errhdlr("zsreci / NULL");
  1564.                fprintf(stderr, "zsreci: fgets == NULL\n");
  1565.                return(-1);
  1566.           }
  1567.  
  1568.           if (lenchk(line, n)) {
  1569.  
  1570.                switch (spur_type) {
  1571.                case 9:
  1572.                case 11:
  1573.                      {
  1574.                          errhdlr("zsreci");
  1575.                          fprintf(stderr, "reading line > %d char\n",
  1576.                                  SRCLNLEN+1);
  1577.                          fprintf(stderr, "line length was %d\n",
  1578.                                           strlen(line));
  1579.                          fprintf(stderr, "%s\n", line);
  1580.                          return(-1);
  1581.                     }
  1582.                default:
  1583.                      {
  1584.                          errhdlr("zsreci");
  1585.                          fprintf(stderr, "reading line > %d char\n",
  1586.                                                                 SRCLNLEN);
  1587.                          fprintf(stderr, "line length was %d\n",
  1588.                                                                 strlen(line));
  1589.                          fprintf(stderr, "%s\n", line);
  1590.                          return(-1);
  1591.                     }
  1592.                }
  1593.  
  1594.           }
  1595.  
  1596.           if (strncmp(line, "000000", 6) == 0) {
  1597.                if (deblog)
  1598.                     fprintf(stderr, "zsreci: Throwing away Pcard.\n");
  1599.                /* throw away the Pcard */
  1600.                continue;
  1601.           }
  1602.  
  1603.      /****************************************************************
  1604.      *  If we get this far, a record was successfully read from the *
  1605.      *  file pointer fp[n].                                         *
  1606.      ****************************************************************/
  1607.  
  1608.           length = rec_len - spaces;
  1609.           if (deblog) {
  1610.                debug(F111, " ", "record length", length);
  1611.                debug(F111, " ", "id start", id_start);
  1612.                debug(F111, " ", "id len", id_len);
  1613.           }
  1614.  
  1615.     /****************************************************************
  1616.      *  If the file has an id field (i.e. id_start != 0), then      *
  1617.      *  copy it into 'idfield' and let 'tail' point to the rest     *
  1618.      *  of the record after the id field.  If there is no id field, *
  1619.      *  let 'tail' point at the remaining record after the line     *
  1620.      *  number field.                                               *
  1621.      ****************************************************************/
  1622.  
  1623.           if (id_start) {
  1624.                strncpy(idfield, &line[id_start], id_len);
  1625.                strcpy(tail, &line[id_start+id_len]);
  1626.                if (deblog)
  1627.                     debug(F111, " id field", idfield, 0);
  1628.           } else {
  1629.                strcpy(tail, &line[HEAD_END]);
  1630.           }
  1631.           if (deblog)
  1632.                debug(F110, " tail", tail, 0);
  1633.  
  1634.     /****************************************************************
  1635.      *  If !send_addnum && ......                                   *
  1636.      *              send_num && !send_renum - use the first six     *
  1637.      *                                        characters of the     *
  1638.      *                                        record.               *
  1639.      *              send_num && send_renum  - replace the first six *
  1640.      *                                        characters of the     *
  1641.      *                                        record with a multi-  *
  1642.      *                                        ple of INCREMENT.     *
  1643.      *              !send_num               - do not use the first  *
  1644.      *                                        six characters of the *
  1645.      *                                        record.               *
  1646.      *     send_addnum                      - Add a multiple        *
  1647.      ****************************************************************/
  1648.  
  1649.           if (!send_addnum) {
  1650.                if (send_num) {
  1651.                     if (send_renum) {
  1652.                          sprintf(line, "%0.*d", num_field_len,
  1653.                                                            linenumber);
  1654.                          if (num_field_len == 5)
  1655.                               strcat(line, " ");
  1656.                          linenumber += INCREMENT;
  1657.                     } else {
  1658.                          line[HEAD_END] = '\0';
  1659.                     }
  1660.                } else {
  1661.                     line[0] = '\0';
  1662.                }
  1663.           } else {
  1664.                strncpy(oldnum, line, HEAD_END);
  1665.                sprintf(line, "%0.*d", num_field_len, linenumber);
  1666.                if (num_field_len == 5)
  1667.                     strcat(line, " ");
  1668.                linenumber += INCREMENT;
  1669.                strncat(line, oldnum, HEAD_END);
  1670.                length += 6;
  1671.           }
  1672.  
  1673.           if (deblog)
  1674.                debug(F110, " line number", line, 0);
  1675.  
  1676.     /****************************************************************
  1677.      *  Add the data to the line.                                   *
  1678.      ****************************************************************/
  1679.  
  1680.           strcat(line, tail);
  1681.  
  1682.     /****************************************************************
  1683.      *  If sending the id field, pad the line with spaces and add   *
  1684.      *  the id field to the end of the line.                        *
  1685.      ****************************************************************/
  1686.  
  1687.           if (send_id) {
  1688.                for (i = length - 6 + ((send_addnum || send_num)
  1689.                    *6); i < (80 - id_len); i++)
  1690.                     line[i] = ' ';
  1691.                line[80-id_len] = '\0';
  1692.                idfield[id_len] = '\n';
  1693.                idfield[id_len+1] = '\0';
  1694.                strcat(line, idfield);
  1695.           } else {
  1696.                line[length-6+((send_addnum || send_num)*6)] =
  1697.                    '\n';
  1698.                line[length-6+((send_addnum || send_num)*6)+1] =
  1699.                    0;
  1700.           }
  1701.           strcat(spur_data, line);
  1702.      }
  1703.      return(1);
  1704. }
  1705.  
  1706.  
  1707. /*  Z S R E C O -- Prepare data to output into SPUR records  */
  1708.  
  1709. zsreco(n)
  1710. int     n;
  1711. {
  1712.      int     id_start = spur_info[MAX_SPURTYPE*ID_START + spur_type - 1];
  1713.      int     id_len = spur_info[MAX_SPURTYPE*ID_LEN + spur_type - 1];
  1714.      int     num_field_len = spur_info[MAX_SPURTYPE*NUM_FIELD_LEN+spur_type-1];
  1715.      char     idfield[10];
  1716.      char     linefield[8];
  1717.      char     record[100];
  1718.      char     data[DATA_LEN];
  1719.      char     temp[DATA_LEN];
  1720.      int     number_len, i, len_char, nulls, data_len = strlen(spur_data);
  1721.  
  1722.     /****************************************************************
  1723.      * Get id field at the end of the line if there is one.         *
  1724.      * If the spur_type has an id field and there are no characters *
  1725.      * in columns (80 - id_len) to 80, the new id field will be     *
  1726.      * spaces.  If recv_id = 0, the new id field will be spaces.    *
  1727.      ****************************************************************/
  1728.  
  1729.      if (deblog) {
  1730.           debug(F111, "zsreco: ", "n", n);
  1731.           debug(F111, " ", "data length", data_len);
  1732.           debug(F111, " ", "id start", id_start);
  1733.           debug(F111, " ", "id len", id_len);
  1734.      }
  1735.  
  1736.      if (id_start) {
  1737.           if ((data_len > 72) && recv_id) {
  1738.                strncpy(idfield, &spur_data[80-id_len], id_len);
  1739.                if ((i = strlen(idfield)) < id_len) {
  1740.                     for (; i < id_len; i++)
  1741.                          idfield[i] = ' ';
  1742.                }
  1743.                idfield[id_len] = '\0';
  1744.           } else {
  1745.                for (i = 0; i < id_len; i++)
  1746.                     idfield[i] = ' ';
  1747.                idfield[id_len] = '\0';
  1748.           }
  1749.           spur_data[80-id_len] = '\0';
  1750.           if (data_len > 6)
  1751.                strncpy(data, &spur_data[NUM_LEN], 80);
  1752.           else
  1753.                data[0] = '\0';
  1754.      } else {
  1755.           idfield[0] = '\0';
  1756.           if (data_len > 6)
  1757.                strcpy(data, &spur_data[NUM_LEN]);
  1758.           else
  1759.                data[0] = '\0';
  1760.      }
  1761.      if (deblog)
  1762.           debug(F110, " id field", idfield, 0);
  1763.  
  1764.    /**********************************************************************
  1765.     * If =>  !recv_addnum && .....                                       *
  1766.     *            recv_num && !recv_renum - Keep the original first six   *
  1767.     *                                      columns from the incoming     *
  1768.     *                                      record.                       *
  1769.     *            recv_num && recv_renum  - Replace the first six columns *
  1770.     *                                      with linenumber and increment *
  1771.     *                                      by the constant INCREMENT.    *
  1772.     *            !recv_num               - Replace the first six columns *
  1773.     *                                      with spaces. (ASCII 0x20)     *
  1774.     *        recv_addnum                 - Insert new line numbers at    *
  1775.     *                                      the beginning of every new    *
  1776.     **********************************************************************/
  1777.  
  1778.      linefield[0] = '\0';
  1779.      if (recv_num && !recv_addnum) {
  1780.           if (recv_renum) {
  1781.                sprintf(linefield, "%0.*d", num_field_len, linenumber);
  1782.                if (num_field_len == 5)
  1783.                     strcat(linefield, " ");
  1784.                linenumber += INCREMENT;
  1785.           } else {
  1786.                strncpy(linefield, spur_data, NUM_LEN);
  1787.                if ((i = strlen(linefield)) < 6) {
  1788.                     for (; i < 6; i++)
  1789.                          strcat(linefield, " ");
  1790.                }
  1791.                linefield[NUM_LEN] = 0;
  1792.           }
  1793.      } else if (recv_addnum) {
  1794.           sprintf(linefield, "%0.*d", num_field_len, linenumber);
  1795.           if (num_field_len == 5)
  1796.                strcat(linefield, " ");
  1797.           linenumber += INCREMENT;
  1798.           strncpy(temp, spur_data, NUM_LEN);
  1799.           temp[NUM_LEN] = '\0';
  1800.           strcat(temp, data);
  1801.           strcpy(data, temp);
  1802.      }
  1803.      if (deblog) {
  1804.           debug(F110, " line number", linefield, 0);
  1805.           debug(F110, " data", data, 0);
  1806.      }
  1807.  
  1808.  
  1809.    /**********************************************************************
  1810.     * peel off the spaces at the end of the remaining data unless we     *
  1811.     * have a Control String or a Procedure file (spur_type=14,15,16)     *
  1812.     **********************************************************************/
  1813.  
  1814.      if ((spur_type == 14) || (spur_type == 15) || (spur_type ==
  1815.          16)) {
  1816.           i = strlen(data);
  1817.           for (; i < (80 - (6 * recv_num)); i++)
  1818.                data[i] = ' ';
  1819.           data[i] = '\0';
  1820.           len_char = 0;
  1821.      } else {
  1822.           i = strlen(data);
  1823.           while (i && (data[i-1] == ' '))
  1824.                i--;
  1825.           data[i] = '\0';
  1826.           if ((!recv_num) && ((i = strlen(data)) < 6)) {
  1827.                for (; i < 6; i++)
  1828.                     strcat(data, " ");
  1829.           }
  1830.           if (recv_num || recv_addnum)
  1831.                number_len = 6;
  1832.           else
  1833.                number_len = 0;
  1834.           len_char = 80 - id_len - strlen(data) - number_len;
  1835.           if (deblog)
  1836.                fprintf(stderr, "zsreco: len_char = %d.\n",
  1837.                    len_char);
  1838.  
  1839.    /****************************************************************
  1840.     * The following must be done since we can not output the ASCII *
  1841.     * characters 0x09 and 0x0a                                     *
  1842.     ****************************************************************/
  1843.  
  1844.           if (len_char == 9) {
  1845.  
  1846.                if (deblog)
  1847.                     fprintf(stderr, "zsreco: app 1 (0x20) on rec end.\n");
  1848.  
  1849.                strcat(data, " ");
  1850.                len_char = 8;
  1851.  
  1852.                if (deblog)
  1853.                     fprintf(stderr, "zsreco: len_char is now %d.\n",
  1854.                                                  len_char);
  1855.  
  1856.           }
  1857.           if (len_char == 10) {
  1858.                if (deblog)
  1859.                     fprintf(stderr, "zsreco: app 2 (0x20) on rec end.\n");
  1860.                strcat(data, "  ");
  1861.                len_char = 8;
  1862.                if (deblog)
  1863.                     fprintf(stderr, "zsreco: len_char is now %d.\n",
  1864.                                                  len_char);
  1865.           }
  1866.      }
  1867.  
  1868.      /* output the space character to column 1 */
  1869.      fputc(len_char, fp[n]);
  1870.      if (ferror(fp[n]) != 0) {
  1871.           errhdlr("zsrceo");
  1872.           fprintf(stderr, "write error: zsrceo len_char\n");
  1873.           return(-1);
  1874.      }
  1875.  
  1876.      /* build the record and output it */
  1877.      record[0] = '\0';
  1878.      if (recv_num || recv_addnum)
  1879.           strcat(record, linefield);
  1880.      else
  1881.           strncat(record, data, NUM_LEN);
  1882.      switch (spur_type) {
  1883.      case 9:
  1884.      case 11:
  1885.           nulls = 2;
  1886.           break;
  1887.      case 12:
  1888.           nulls = 1;
  1889.           break;
  1890.      default:
  1891.           nulls = 0;
  1892.      }
  1893.      for (i = 0; i < nulls; i++)
  1894.           strcat(record, " ");
  1895.      strcat(record, idfield);
  1896.      if (recv_num || recv_addnum)
  1897.           strcat(record, data);
  1898.      else
  1899.           strcat(record, &data[NUM_LEN]);
  1900.  
  1901.      return(zsoutl(n, record));
  1902.  
  1903. }
  1904.  
  1905.  
  1906. /* E R R H D L R - errhdlr for all unpleasant outcomes
  1907.                    PEG May 14, 1990
  1908. */
  1909.  
  1910. void errhdlr(wherefrm)
  1911. char     *wherefrm;
  1912. {
  1913.      char     s[90];
  1914.      long     errclk;
  1915.      int      geterr = errno;         /* we grab the error number
  1916.                                          due the timestamp fprintf
  1917.                                          setting errno to EMINR
  1918.                                          May 22, 1990              */
  1919.  
  1920.      /* time stamp stderr output */
  1921.      /* May 4, 1990              */
  1922.  
  1923.      errclk = time((long *) 0);
  1924.      fprintf(stderr, "\n%s", ctime(&errclk));
  1925.  
  1926. /* we do not want to print anymore EMINR messages */
  1927.  
  1928.      if ((geterr) && (geterr != EMINR)) {
  1929.           sprintf(s, "%s: %s", wherefrm, sys_errlist[geterr]);
  1930.           perror(wherefrm);
  1931.           if (!server)
  1932.                screen(SCR_EM, 0, 0l, s);
  1933.           else
  1934.                errpkt(s);
  1935.           errno = 0;
  1936.           return;
  1937.      } else {
  1938.           sprintf(s, "Error occured: %s", wherefrm);
  1939.           fprintf(stderr, "%s\n", s);
  1940.           if (!server)
  1941.                screen(SCR_EM, 0, 0l, s);
  1942.           else
  1943.                errpkt(s);
  1944.           errno = 0;
  1945.           return;
  1946.      }
  1947. } /* errhdlr end */
  1948.  
  1949.  
  1950. /* L E N C H K - lenchk: checks spur records after read or
  1951.                          before right to verify that they do not
  1952.                          exceed maximum values defined by SRCLNLEN
  1953.                                                                     */
  1954. int     lenchk(s, n)
  1955. char     *s;            /* string ptr for examing line length */
  1956. int     n;             /* file number... index into fp[]  */
  1957. {
  1958.  
  1959.      if ((n != ZIFILE && n != ZOFILE) || binary)
  1960.           return(0);
  1961.  
  1962.      if ((*file_type == 'C') || (*file_type == 'S')) {
  1963.  
  1964.           switch (spur_type) {
  1965.           case 9:
  1966.           case 11:
  1967.                 {
  1968.                     if (strlen(s) > SRCLNLEN + 1)
  1969.                          return (-1);
  1970.                     else
  1971.                          return(0);
  1972.                }
  1973.           default:
  1974.                 {
  1975.                     if (strlen(s) > SRCLNLEN)
  1976.                          return (-1);
  1977.                     else
  1978.                          return(0);
  1979.                }
  1980.           }
  1981.  
  1982.      } else
  1983.           return(0);
  1984.  
  1985. } /* end lenchk */
  1986.  
  1987.  
  1988. /* R E S E T O P E N resetopen: closes ZOFILE or ZIFILE left open
  1989.                                 from previous aborted file transfers
  1990.                                 May 30, 1990
  1991.                                                                      */
  1992.  
  1993. void resetopen()
  1994. {
  1995.   int n;
  1996.  
  1997.      if ((fp[ZOFILE] == NULL) && (fp[ZIFILE] == NULL))
  1998.          return;
  1999.  
  2000.      if (fp[ZOFILE] != NULL)
  2001.          n = ZOFILE;
  2002.      else
  2003.          n = ZIFILE;
  2004.  
  2005.      if (objopen) {              /* March 12, 1990 */
  2006.                if (voclose(n) == 0) {
  2007.                    if ((!keep) && (n == ZOFILE)) {
  2008.                          if (unlink(fn_temp) != 0) {
  2009.                               errhdlr("resetopen UNLINK");
  2010.                               fprintf(stderr, "unlink failed %s\n",
  2011.                                       fn_temp);
  2012.                          }
  2013.                     }
  2014.                }
  2015.                objopen = CLOSE;
  2016.      }
  2017.      else {
  2018.                if (fclose(fp[n]) == EOF) {
  2019.                   errhdlr("resetopen fclose error");
  2020.                   fprintf(stderr,"file name: %s\n",fn_temp);
  2021.                }
  2022.  
  2023.                if ((!keep) && (n == ZOFILE))
  2024.                     if (unlink(fn_temp) != 0) {
  2025.                          errhdlr("resetopen UNLINK");
  2026.                          fprintf(stderr, "unlink failed %s\n",
  2027.                                  fn_temp);
  2028.                     }
  2029.      }
  2030.      strcpy(fn_temp, "\0");
  2031.      fp[n] = NULL;
  2032.      return;
  2033. }
  2034.