home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip22.zip / tandem / tandem.c < prev    next >
C/C++ Source or Header  |  1997-10-12  |  20KB  |  803 lines

  1. /*
  2.  
  3.  Copyright (C) 1990-1996 Mark Adler, Richard B. Wales, Jean-loup Gailly,
  4.  Kai Uwe Rommel, Onno van der Linden,zGeorge Petrov and Igor Mandrichenko.
  5.  Permission is granted to any individual or institution to use, copy, or
  6.  redistribute this software so long as all of the original files are included,
  7.  that it is not sold for profit, and that this copyright notice is retained.
  8.  
  9. */
  10.  
  11. /*
  12.  * routines common to TANDEM
  13.  */
  14.  
  15. #include "zip.h"
  16.  
  17. #include <time.h>
  18.  
  19. #define MATCH shmatch
  20.  
  21.  
  22. #define DISK_DEVICE        3
  23.  
  24.  
  25. /* Library functions not in (most) header files */
  26.  
  27. #ifndef UTIL    /* the companion #endif is a bit of ways down ... */
  28.  
  29. int isatty (fnum)
  30. int fnum;
  31. {
  32.   return -1;
  33. }
  34.  
  35.  
  36. extern char *label;
  37. local ulg label_time = 0;
  38. local ulg label_mode = 0;
  39. local time_t label_utim = 0;
  40.  
  41. #include <tal.h>
  42. #include <cextdecs(FILE_GETINFOLISTBYNAME_, \
  43.                    FILENAME_SCAN_,          \
  44.                    INTERPRETTIMESTAMP       \
  45.                   )>
  46. #include <cextdecs(FILENAME_FINDSTART_, \
  47.                    FILENAME_FINDNEXT_,  \
  48.                    FILENAME_FINDFINISH_ \
  49.                   )>
  50. #include <cextdecs(SETMODE)>
  51.  
  52. /* TANDEM version of chmod() function */
  53.  
  54. int chmod(file, unix_sec)
  55. const char *file;
  56. mode_t unix_sec;
  57. {
  58. FILE *stream;
  59.  
  60. struct nsk_sec_type
  61. {
  62.   unsigned progid : 1;
  63.   unsigned clear  : 1;
  64.   unsigned null   : 2;
  65.   unsigned read   : 3;
  66.   unsigned write  : 3;
  67.   unsigned execute: 3;
  68.   unsigned purge  : 3;
  69. };
  70.  
  71. union nsk_sec_ov
  72. {
  73.   struct nsk_sec_type bit_ov;
  74.   short int_ov;
  75. };
  76.  
  77. union nsk_sec_ov nsk_sec;
  78.  
  79. short fnum, fdes, err, nsk_sec_int;
  80.  
  81.   nsk_sec.bit_ov.progid = 0;
  82.   nsk_sec.bit_ov.clear  = 0;
  83.   nsk_sec.bit_ov.null   = 0;
  84.  
  85.   /*  4="N", 5="C", 6="U", 7="-"   */
  86.  
  87.   err = unix_sec & S_IROTH;
  88.  
  89.   if (unix_sec & S_IROTH) nsk_sec.bit_ov.read = 4;
  90.   else if (unix_sec & S_IRGRP) nsk_sec.bit_ov.read = 5;
  91.   else if (unix_sec & S_IRUSR) nsk_sec.bit_ov.read = 6;
  92.   else nsk_sec.bit_ov.read = 7;
  93.  
  94.   if (unix_sec & S_IWOTH) nsk_sec.bit_ov.write = 4;
  95.   else if (unix_sec & S_IWGRP) nsk_sec.bit_ov.write = 5;
  96.   else if (unix_sec & S_IWUSR) nsk_sec.bit_ov.write = 6;
  97.   else nsk_sec.bit_ov.write = 7;
  98.  
  99.   if (unix_sec & S_IXOTH) nsk_sec.bit_ov.execute = 4;
  100.   else if (unix_sec & S_IXGRP) nsk_sec.bit_ov.execute = 5;
  101.   else if (unix_sec & S_IXUSR) nsk_sec.bit_ov.execute = 6;
  102.   else nsk_sec.bit_ov.execute = 7;
  103.  
  104.   nsk_sec.bit_ov.purge = nsk_sec.bit_ov.write;
  105.  
  106.   nsk_sec_int = nsk_sec.int_ov;
  107.  
  108.   fdes = open(file, (O_EXCLUSIVE | O_RDONLY));
  109.   fnum = fdtogfn (fdes);
  110.   err = SETMODE (fnum, SET_FILE_SECURITY, nsk_sec_int);
  111.   err = close(fdes);
  112.  
  113. }
  114.  
  115.  
  116.  
  117. /* TANDEM version of stat() funcion */
  118.  
  119. time_t gmt_to_time_t (long long *);
  120.  
  121. time_t gmt_to_time_t (gmt)
  122.   long long *gmt;
  123. {
  124.   struct tm temp_tm;
  125.   short  date_time[8];
  126.   long   julian_dayno;
  127.  
  128.   julian_dayno = INTERPRETTIMESTAMP (*gmt, date_time);
  129.  
  130.   temp_tm.tm_sec   = date_time[5];
  131.   temp_tm.tm_min   = date_time[4];
  132.   temp_tm.tm_hour  = date_time[3];
  133.   temp_tm.tm_mday  = date_time[2];
  134.   temp_tm.tm_mon   = date_time[1] - 1;     /* C's so sad */
  135.   temp_tm.tm_year  = date_time[0] - 1900;  /* it's almost funny */
  136.   temp_tm.tm_isdst = -1;  /* don't know */
  137.  
  138.   return (mktime(&temp_tm));
  139. }
  140.  
  141. void zexit(status)
  142. int status;
  143. {
  144.   terminate_program (0,0,status,,,);   /* Exit(>0) creates saveabend files */
  145. }
  146.  
  147.  
  148. #ifdef fopen
  149.   #undef fopen
  150. #endif
  151.  
  152. FILE *zipopen(fname, opt)
  153. const char *fname;
  154. const char *opt;
  155. {
  156.   int fdesc;
  157.  
  158.   if (strcmp(opt,FOPW) == 0)
  159.     if ((fdesc = creat(fname,,100,500)) != -1)
  160.       close(fdesc);
  161.  
  162.   return fopen(fname,opt);
  163. }
  164. #define fopen zipopen
  165.  
  166. #ifdef putc
  167.   #undef putc
  168. #endif
  169.  
  170. int zputc(ch, fptr)
  171. int ch;
  172. FILE *fptr;
  173. {
  174.   int err;
  175.   err = putc(ch,fptr);
  176.   fflush(fptr);
  177.   return err;
  178. }
  179. #define putc zputc
  180.  
  181. int utime OF((char *, ztimbuf *));
  182.  
  183. int utime(file, time)
  184. char *file;
  185. ztimbuf *time;
  186. {
  187.   return 0;
  188. }
  189.  
  190.  
  191. short parsename(
  192. const char *,
  193. char *,
  194. char *
  195. );
  196.  
  197. short parsename(srce, fname, ext)
  198. const char *srce;
  199. char *fname;
  200. char *ext;
  201. {
  202.   /* As a way of supporting DOS extensions from Tandem we look for a space
  203.      separated extension string after the Guardian filename
  204.      e.g. ZIP ZIPFILE "$DATA4.TESTING.INVOICE TXT"
  205.   */
  206.  
  207.   char *fstart;
  208.   char *fptr;
  209.   short extension = 0;
  210.  
  211.   *fname = *ext = '\0';  /* set to null string */
  212.  
  213.   fstart = (char *) srce;
  214.  
  215.   if ((fptr = strrchr(fstart, TANDEM_EXTENSION)) != NULL) {
  216.     extension = 1;
  217.  
  218.     fptr++;
  219.     strncat(ext, fptr, _min(EXTENSION_MAX, strlen(fptr)));
  220.  
  221.     fptr = strchr(fstart, TANDEM_EXTENSION);  /* End of filename */
  222.     strncat(fname, fstart, _min(FILENAME_MAX, (fptr - fstart)));
  223.   }
  224.   else {
  225.     /* just copy string */
  226.     strncat(fname, srce, _min(FILENAME_MAX, strlen(srce)));
  227.   }
  228.  
  229.   return extension;
  230. }
  231.  
  232. int stat(n, s)
  233. const char *n;
  234. struct stat *s;
  235. {
  236.   #define list_items 14
  237.   #define rlist_size 200
  238.  
  239.   short err, i, extension;
  240.   char fname[FILENAME_MAX + 1];
  241.   short fnamelen;
  242.   char ext[EXTENSION_MAX + 1];
  243.                         /* #0  #1  #2  #3 #4 #5 #6 #7 #8 #9 #10 #11 #12 #13 */
  244.   short ilist[list_items]={62,117,145,142,58,41,42,30,31,75, 78, 79, 60,119};
  245.   short ilen[list_items] ={ 2,  4,  4,  2, 1, 1, 1, 1, 1, 1,  1,  1,  1,  4};
  246.   short ioff[list_items];
  247.   short rlist[rlist_size];
  248.   short extra[2];
  249.   short *rlen=&extra[0];
  250.   short *err_item=&extra[1];
  251.   unsigned short *fowner;
  252.   unsigned short *fprogid;
  253.   char *fsec;
  254.  
  255.   short end, count, kind, level, options, searchid;
  256.   short info[5];
  257.  
  258.   /* Initialise stat structure */
  259.   s->st_dev = _S_GUARDIANOBJECT;
  260.   s->st_ino = 0;
  261.   s->st_nlink = 0;
  262.   s->st_rdev = 0;
  263.   s->st_uid = s->st_gid = 0;
  264.   s->st_size = 0;
  265.   s->st_atime = s->st_ctime = s->st_mtime = 0;
  266.   s->st_reserved[0] = 0;
  267.  
  268.   /* Check to see if name contains a (pseudo) file extension */
  269.   extension = parsename (n,fname,ext);
  270.  
  271.   fnamelen = strlen(fname);
  272.  
  273.   options = 3; /* Allow Subvols and Templates */
  274.   err = FILENAME_SCAN_( fname,
  275.                         fnamelen,
  276.                         &count,
  277.                         &kind,
  278.                         &level,
  279.                         options
  280.                       );
  281.  
  282.   if (err != 0 || kind == 2) return -1;
  283.  
  284.   if (kind == 1 || level < 2) {
  285.     /* Pattern, Subvol Name or One part Filename - lets see if it exists */
  286.     err = FILENAME_FINDSTART_ ( &searchid,
  287.                                 fname,
  288.                                 fnamelen,
  289.                                 ,
  290.                                 DISK_DEVICE
  291.                               );
  292.  
  293.     if (err != 0) {
  294.       end = FILENAME_FINDFINISH_ ( searchid );
  295.       return -1;
  296.     }
  297.  
  298.     err = FILENAME_FINDNEXT_ ( searchid,
  299.                                fname,
  300.                                FILENAME_MAX,
  301.                                &fnamelen,
  302.                                info
  303.                               );
  304.     end = FILENAME_FINDFINISH_ ( searchid );
  305.  
  306.     if (err != 0)
  307.       return -1;  /* Non existing template, subvol or file */
  308.  
  309.     if (kind == 1 || info[2] == -1) {
  310.       s->st_mode = S_IFDIR;    /* Its an existing template or directory */
  311.       return 0;
  312.     }
  313.  
  314.     /* Must be a real file so drop to code below to get info on it */
  315.   }
  316.  
  317.   err = FILE_GETINFOLISTBYNAME_( fname,
  318.                                  fnamelen,
  319.                                  ilist,
  320.                                  list_items,
  321.                                  rlist,
  322.                                  rlist_size,
  323.                                  rlen,
  324.                                  err_item
  325.                                );
  326.  
  327.   if (err != 0) return -1;
  328.  
  329.   ioff[0] = 0;
  330.  
  331.   /*  Build up table of offets into result list */
  332.   for (i=1; i < list_items; i++)
  333.     ioff[i] = ioff[i-1] + ilen[i-1];
  334.  
  335.  
  336.   /* Setup timestamps */
  337.   s->st_atime = gmt_to_time_t ((long long *)&rlist[ioff[1]]);
  338.   s->st_mtime = s->st_ctime = gmt_to_time_t ((long long *)&rlist[ioff[2]]);
  339.   s->st_reserved[0] = (int64_t) gmt_to_time_t ((long long *)&rlist[ioff[13]]);
  340.  
  341.   s->st_size = *(off_t *)&rlist[ioff[3]];
  342.  
  343.   fowner = (unsigned short *)&rlist[ioff[4]];
  344.   s->st_uid = *fowner & 0x00ff;
  345.   s->st_gid = *fowner >> 8;
  346.  
  347.   /* Note that Purge security (fsec[3]) in NSK has no relevance to stat() */
  348.   fsec = (char *)&rlist[ioff[0]];
  349.   fprogid = (unsigned short *)&rlist[ioff[12]];
  350.  
  351.   s->st_mode = S_IFREG |  /* Regular File */
  352.   /*  Parse Read Flag */
  353.                ((fsec[0] & 0x03) == 0x00 ? S_IROTH : 0) |
  354.                ((fsec[0] & 0x02) == 0x00 ? S_IRGRP : 0) |
  355.                ((fsec[0] & 0x03) != 0x03 ? S_IRUSR : 0) |
  356.   /*  Parse Write Flag */
  357.                ((fsec[1] & 0x03) == 0x00 ? S_IWOTH : 0) |
  358.                ((fsec[1] & 0x02) == 0x00 ? S_IWGRP : 0) |
  359.                ((fsec[1] & 0x03) != 0x03 ? S_IWUSR : 0) |
  360.   /*  Parse Execute Flag */
  361.                ((fsec[2] & 0x03) == 0x00 ? S_IXOTH : 0) |
  362.                ((fsec[2] & 0x02) == 0x00 ? S_IXGRP : 0) |
  363.                ((fsec[2] & 0x03) != 0x03 ? S_IXUSR : 0) |
  364.   /*  Parse Progid */
  365.                (*fprogid == 1 ? (S_ISUID | S_ISGID) : 0) ;
  366.  
  367.   return 0;
  368. }
  369.  
  370. char *ex2in(x, isdir, pdosflag)
  371. char *x;                /* external file name */
  372. int isdir;              /* input: x is a directory */
  373. int *pdosflag;          /* output: force MSDOS file attributes? */
  374. /* Convert the external file name to a zip file name, returning the malloc'ed
  375.    string or NULL if not enough memory. */
  376. {
  377.   char *n;              /* internal file name (malloc'ed) */
  378.   char *t;              /* shortened name */
  379.   int dosflag;
  380.   char *p;               /* pointer to temp area */
  381.   char fname[FILENAME_MAX + 1]= ""; /* file name */
  382.   char ext[EXTENSION_MAX + 1] = ""; /* extension name */
  383.   short extension;    /* does the filename contain an extension */
  384.  
  385.   dosflag = dosify;  /* default for non-DOS non-OS/2 */
  386.  
  387.   /* Find starting point in name before doing malloc */
  388.   t = x;
  389.  
  390.   /* Make changes, if any, to the copied name (leave original intact) */
  391.  
  392.   if (!pathput)
  393.     t = last(t, TANDEM_DELIMITER);
  394.  
  395.   /* Malloc space for internal name and copy it */
  396.   if ((n = malloc(strlen(t) + 4)) == NULL) /* + 4 for safety */
  397.     return NULL;
  398.  
  399.   extension = parsename(t,fname,ext);
  400.   t = fname;
  401.  
  402.   *n= '\0';
  403.  
  404.   while (*t != '\0') {  /* File part could be sys,vol,subvol or file */
  405.     if (*t == TANDEM_NODE) {    /* System Name */
  406.       strcat(n, INTERNAL_NODE_STR);
  407.       t++;
  408.     }
  409.     else if (*t == TANDEM_DELIMITER) {  /* Volume or Subvol */
  410.            strcat(n, INTERNAL_DELIMITER_STR);
  411.            t++;
  412.          };
  413.     p = strchr(t,TANDEM_DELIMITER);
  414.     if (p == NULL) break;
  415.     strncat(n,t,(p - t));
  416.     t = p;
  417.   }
  418.  
  419.   strcat(n,t);  /* mop up any left over characters */
  420.  
  421.   if (extension) {
  422.     strcat(n,DOS_EXTENSION_STR);
  423.     strcat(n,ext);
  424.   };
  425.  
  426.   if (isdir == 42) return n;      /* avoid warning on unused variable */
  427.  
  428.   if (dosify)
  429.     msname(n);
  430.  
  431.   /* Returned malloc'ed name */
  432.   if (pdosflag)
  433.     *pdosflag = dosflag;
  434.  
  435.   return n;
  436. }
  437.  
  438.  
  439. char *in2ex(n)
  440. char *n;                /* internal file name */
  441. /* Convert the zip file name to an external file name, returning the malloc'ed
  442.    string or NULL if not enough memory. */
  443. {
  444.   char *x;              /* external file name */
  445.   char *t;              /* pointer to internal */
  446.   char *p;              /* pointer to internal */
  447.   char *e;              /* pointer to internal */
  448.  
  449.   int len;
  450.  
  451.   if ((x = malloc(strlen(n) + 4)) == NULL)  /* + 4 for safety */
  452.     return NULL;
  453.  
  454.   t = n;
  455.  
  456.   *x= '\0';
  457.  
  458.   if (!pathput)
  459.     t = last(t, INTERNAL_DELIMITER);
  460.  
  461.   while (*t != '\0') {  /* File part could be sys,vol,subvol or file */
  462.     if (*t == INTERNAL_DELIMITER) {    /* System, Volume or Subvol Name */
  463.       t++;
  464.       if (*t == INTERNAL_DELIMITER) {  /* System */
  465.         strcat(x, TANDEM_NODE_STR);
  466.         t++;
  467.       }
  468.       else
  469.         strcat(x, TANDEM_DELIMITER_STR);
  470.     }
  471.     p = strchr(t,INTERNAL_DELIMITER);
  472.     if (p == NULL) break;
  473.     if ((e = strchr(t,DOS_EXTENSION)) == NULL)
  474.       e = p;
  475.     else
  476.       e = (e < p ? e : p);
  477.     len = _min (MAXFILEPARTLEN, (e - t));
  478.     strncat(x,t,(e - t));
  479.     t = p;
  480.   }
  481.  
  482.   if ((e = strchr(t,DOS_EXTENSION)) == NULL)
  483.     strcat(x,t);
  484.   else
  485.     strncat(x,t,(e - t));
  486.  
  487.   return x;
  488. }
  489.  
  490. void stamp(f, d)
  491. char *f;                /* name of file to change */
  492. ulg d;                  /* dos-style time to change it to */
  493. /* Set last updated and accessed time of file f to the DOS time d. */
  494. {
  495.   ztimbuf u;            /* argument for utime() */
  496.  
  497.   /* Convert DOS time to time_t format in u.actime and u.modtime */
  498.   u.actime = u.modtime = dos2unixtime(d);
  499.  
  500.   utime(f, &u);
  501. }
  502.  
  503. ulg filetime(f, a, n, t)
  504. char *f;                /* name of file to get info on */
  505. ulg *a;                 /* return value: file attributes */
  506. long *n;                /* return value: file size */
  507. iztimes *t;             /* return value: access and modification time */
  508. {
  509.   struct stat s;
  510.   char fname[FILENAME_MAX + 1];
  511.  
  512.   if (strcmp(f, "-") == 0) {    /* if compressing stdin */
  513.     if (n != NULL) {
  514.       *n = -1L;
  515.     }
  516.   }
  517.  
  518.   strcpy(fname, f);
  519.  
  520.   if (stat(fname, &s) != 0) return 0;
  521.  
  522.   if (a!= NULL) {
  523.     *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWUSR);
  524.     if ((s.st_mode & S_IFMT) == S_IFDIR) {
  525.       *a |= MSDOS_DIR_ATTR;
  526.     }
  527.   }
  528.  
  529.   if (n!= NULL)
  530.     *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
  531.  
  532.   if (t != NULL) {
  533.     t->atime = s.st_atime;
  534.     t->mtime = s.st_mtime;
  535.     t->ctime = (time_t) s.st_reserved[0];
  536.   }
  537.  
  538.   return unix2dostime(&s.st_mtime);
  539. }
  540.  
  541. int set_extra_field(z, z_utim)
  542. struct zlist far *z;
  543. iztimes *z_utim;
  544. /* create extra field and change z->att if desired */
  545. {
  546.   return ZE_OK;
  547. }
  548.  
  549. int deletedir(d)
  550. char *d;                /* directory to delete */
  551. /* Delete the directory *d if it is empty, do nothing otherwise.
  552.    Return the result of rmdir(), delete(), or system().
  553.    For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
  554.  */
  555. {
  556.     return rmdir(d);
  557. }
  558.  
  559. /*  COMMENTED OUT - SEE LATER DECLARATION
  560.   void version_local()
  561.   {
  562.       printf("Compiled with %s under %s.\n", "T9255C", "TANDEM NSK"
  563.       );
  564.   }
  565. */
  566.  
  567. #endif /* !UTIL */
  568.  
  569.  
  570. /*
  571.  * TANDEM
  572.  */
  573.  
  574. DIR *opendir(const char *dirname)
  575. {
  576.    short i, resolve;
  577.    char sname[FILENAME_MAX + 1];
  578.    short snamelen;
  579.    char fname[FILENAME_MAX + 1];
  580.    short fnamelen;
  581.    char *p;
  582.    short searchid,err,end;
  583.    struct dirent *entry;
  584.    DIR *dirp;
  585.    char ext[EXTENSION_MAX + 1];
  586.    short extension;
  587.  
  588.    extension = parsename(dirname, sname, ext);
  589.    snamelen = strlen(sname);
  590.  
  591.    /*  First we work out how detailed the template is...
  592.     *  e.g. If the template is DAVES*.* we want the search result
  593.     *       in the same format
  594.     */
  595.  
  596.    p = sname;
  597.    i = 0;
  598.    while ((p = strchr(p, TANDEM_DELIMITER)) != NULL){
  599.      i++;
  600.      p++;
  601.    };
  602.    resolve = 2 - i;
  603.  
  604.    /*  Attempt to start a filename template */
  605.    err = FILENAME_FINDSTART_ ( &searchid,
  606.                                sname,
  607.                                snamelen,
  608.                                resolve,
  609.                                DISK_DEVICE
  610.                              );
  611.    if (err != 0) {
  612.      end = FILENAME_FINDFINISH_(searchid);
  613.      return NULL;
  614.    }
  615.  
  616.    /* Create DIR structure */
  617.    if ((dirp = malloc(sizeof(DIR))) == NULL ) {
  618.      end = FILENAME_FINDFINISH_(searchid);
  619.      return NULL;
  620.    }
  621.    dirp->D_list = dirp->D_curpos = NULL;
  622.    strcpy(dirp->D_path, dirname);
  623.  
  624.    while ((err = FILENAME_FINDNEXT_(searchid,
  625.                                     fname,
  626.                                     FILENAME_MAX,
  627.                                     &fnamelen
  628.                                    )
  629.            ) == 0 ){
  630.      /*  Create space for entry */
  631.      if ((entry = malloc (sizeof(struct dirent))) == NULL) {
  632.        end = FILENAME_FINDFINISH_(searchid);
  633.        return NULL;
  634.      }
  635.  
  636.      /*  Link to last entry */
  637.      if (dirp->D_curpos == NULL)
  638.        dirp->D_list = dirp->D_curpos = entry;  /* First name */
  639.      else {
  640.        dirp->D_curpos->d_next = entry;         /* Link */
  641.        dirp->D_curpos = entry;
  642.      };
  643.      /* Add directory entry */
  644.      *dirp->D_curpos->d_name = '\0';
  645.      strncat(dirp->D_curpos->d_name,fname,fnamelen);
  646.      if (extension) {
  647.        strcat(dirp->D_curpos->d_name,TANDEM_EXTENSION_STR);
  648.        strcat(dirp->D_curpos->d_name,ext);
  649.      };
  650.      dirp->D_curpos->d_next = NULL;
  651.    };
  652.  
  653.    end = FILENAME_FINDFINISH_(searchid);
  654.  
  655.    if (err = 1) {  /*  Should return EOF at end of search */
  656.      dirp->D_curpos = dirp->D_list;        /* Set current pos to start */
  657.      return dirp;
  658.    }
  659.    else
  660.      return NULL;
  661. }
  662.  
  663. struct dirent *readdir(DIR *dirp)
  664. {
  665.    struct dirent *cur;
  666.  
  667.    cur = dirp->D_curpos;
  668.    dirp->D_curpos = dirp->D_curpos->d_next;
  669.    return cur;
  670. }
  671.  
  672. void rewinddir(DIR *dirp)
  673. {
  674.    dirp->D_curpos = dirp->D_list;
  675. }
  676.  
  677. int closedir(DIR *dirp)
  678. {
  679.    struct dirent *node;
  680.  
  681.    while (dirp->D_list != NULL) {
  682.       node = dirp->D_list;
  683.       dirp->D_list = dirp->D_list->d_next;
  684.       free( node );
  685.    }
  686.    free( dirp );
  687.    return 0;
  688. }
  689.  
  690. local char *readd(d)
  691. DIR *d;                 /* directory stream to read from */
  692. /* Return a pointer to the next name in the directory stream d, or NULL if
  693.    no more entries or an error occurs. */
  694. {
  695.   struct dirent *e;
  696.  
  697.   e = readdir(d);
  698.   return e == NULL ? (char *) NULL : e->d_name;
  699. }
  700.  
  701. int procname(n)
  702. char *n;                /* name to process */
  703. /* Process a name or sh expression to operate on (or exclude).  Return
  704.    an error code in the ZE_ class. */
  705. {
  706.   char *a;              /* path and name for recursion */
  707.   DIR *d;               /* directory stream from opendir() */
  708.   char *e;              /* pointer to name from readd() */
  709.   int m;                /* matched flag */
  710.   char *p;              /* path for recursion */
  711.   struct stat s;        /* result of stat() */
  712.   struct zlist far *z;  /* steps through zfiles list */
  713.  
  714.   if (strcmp(n, "-") == 0)   /* if compressing stdin */
  715.     return newname(n, 0);
  716.   else if (stat(n, &s))
  717.   {
  718.     /* Not a file or directory--search for shell expression in zip file */
  719.     p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
  720.     m = 1;
  721.     for (z = zfiles; z != NULL; z = z->nxt) {
  722.       if (MATCH(p, z->zname))
  723.       {
  724.         z->mark = pcount ? filter(z->zname) : 1;
  725.         if (verbose)
  726.             fprintf(mesg, "zip diagnostic: %scluding %s\n",
  727.                z->mark ? "in" : "ex", z->name);
  728.         m = 0;
  729.       }
  730.     }
  731.     free((zvoid *)p);
  732.     return m ? ZE_MISS : ZE_OK;
  733.   }
  734.  
  735.   /* Live name--use if file, recurse if directory */
  736.   if ((s.st_mode & S_IFDIR) == 0)
  737.   {
  738.     /* add or remove name of file */
  739.     if ((m = newname(n, 0)) != ZE_OK)
  740.       return m;
  741.   } else {
  742.     if ((p = malloc(strlen(n)+4)) == NULL)
  743.       return ZE_MEM;
  744.  
  745.     strcpy(p, n);
  746.  
  747.     /* No concept of directories on Tandem - so do not store them ...*/
  748.     /* code removed from which attempted to save dir name if dirnames set */
  749.  
  750.     /*  Test for recurse being set removed, since Tandem has no dir concept */
  751.     /*  recurse into template */
  752.     if ((d = opendir(n)) != NULL)
  753.     {
  754.       while ((e = readd(d)) != NULL) {
  755.         if ((m = procname(e)) != ZE_OK)   /* recurse on name */
  756.         {
  757.           if (m == ZE_MISS)
  758.             zipwarn("name not matched: ", e);
  759.           else
  760.             ziperr(m, e);
  761.         }
  762.       }
  763.       closedir(d);
  764.     }
  765.     free((zvoid *)p);
  766.   } /* (s.st_mode & S_IFDIR) == 0) */
  767.   return ZE_OK;
  768. }
  769.  
  770. /******************************/
  771. /*  Function version_local()  */
  772. /******************************/
  773.  
  774. void version_local()
  775. {
  776.     static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
  777. #if 0
  778.     char buf[40];
  779. #endif
  780.  
  781.     printf(CompiledWith,
  782.  
  783. #ifdef __GNUC__
  784.       "gcc ", __VERSION__,
  785. #else
  786. #  if 0
  787.       "cc ", (sprintf(buf, " version %d", _RELEASE), buf),
  788. #  else
  789.       "unknown compiler", "",
  790. #  endif
  791. #endif
  792.  
  793.       "Tandem/NSK", "",
  794.  
  795. #ifdef __DATE__
  796.       " on ", __DATE__
  797. #else
  798.       "", ""
  799. #endif
  800.       );
  801.  
  802. } /* end function version_local() */
  803.