home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1689 / vmsreaddir.c < prev   
Encoding:
C/C++ Source or Header  |  1990-12-28  |  4.9 KB  |  242 lines

  1. /*
  2. **  VMS readdir() routines.
  3. **  Written by Rich $alz, <rsalz@bbn.com> in August, 1990.
  4. **  This code has no copyright.
  5. */
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <errno.h>
  9. #include <descrip.h>
  10. #include <rmsdef.h>
  11. #include "dirent.h"
  12.  
  13.     /* Uncomment the next line to get a test routine. */
  14. /*#define TEST*/
  15.  
  16.     /* Number of elements in vms_versions array */
  17. #define VERSIZE(e)    (sizeof e->vms_versions / sizeof e->vms_versions[0])
  18.  
  19.     /* Linked in later. */
  20. extern char    *malloc();
  21. extern char    *strrchr();
  22. extern char    *strcpy();
  23.  
  24.  
  25. /*
  26. **  Open a directory, return a handle for later use.
  27. */
  28. DIR *
  29. opendir(name)
  30.     char    *name;
  31. {
  32.     DIR        *dd;
  33.  
  34.     /* Get memory for the handle, and the pattern. */
  35.     if ((dd = (DIR *)malloc(sizeof *dd)) == NULL) {
  36.     errno = ENOMEM;
  37.     return NULL;
  38.     }
  39.     dd->pattern = malloc((unsigned int)(strlen(name) + sizeof "*.*" + 1));
  40.     if (dd->pattern == NULL) {
  41.     free((char *)dd);
  42.     errno = ENOMEM;
  43.     return NULL;
  44.     }
  45.  
  46.     /* Fill in the fields; mainly playing with the descriptor. */
  47.     (void)sprintf(dd->pattern, "%s*.*", name);
  48.     dd->context = 0;
  49.     dd->vms_wantversions = 0;
  50.     dd->pat.dsc$a_pointer = dd->pattern;
  51.     dd->pat.dsc$w_length = strlen(dd->pattern);
  52.     dd->pat.dsc$b_dtype = DSC$K_DTYPE_T;
  53.     dd->pat.dsc$b_class = DSC$K_CLASS_S;
  54.  
  55.     return dd;
  56. }
  57.  
  58.  
  59. /*
  60. **  Set the flag to indicate we want versions or not.
  61. */
  62. void
  63. vmsreaddirversions(dd, flag)
  64.     DIR        *dd;
  65.     int        flag;
  66. {
  67.     dd->vms_wantversions = flag;
  68. }
  69.  
  70.  
  71. /*
  72. **  Free up an opened directory.
  73. */
  74. void
  75. closedir(dd)
  76.     DIR        *dd;
  77. {
  78.     free(dd->pattern);
  79.     free((char *)dd);
  80. }
  81.  
  82.  
  83. /*
  84. **  Collect all the version numbers for the current file.
  85. */
  86. static void
  87. collectversions(dd)
  88.     DIR                *dd;
  89. {
  90.     struct dsc$descriptor_s    pat;
  91.     struct dsc$descriptor_s    res;
  92.     struct dirent        *e;
  93.     char            *p;
  94.     char            buff[sizeof dd->entry.d_name];
  95.     int                i;
  96.     char            *text;
  97.     long            context;
  98.  
  99.     /* Convenient shorthand. */
  100.     e = &dd->entry;
  101.  
  102.     /* Add the version wildcard, ignoring the "*.*" put on before */
  103.     i = strlen(dd->pattern);
  104.     text = malloc((unsigned int)(i + strlen(e->d_name)+ 2 + 1));
  105.     if (text == NULL)
  106.     return;
  107.     (void)strcpy(text, dd->pattern);
  108.     (void)sprintf(&text[i - 3], "%s;*", e->d_name);
  109.  
  110.     /* Set up the pattern descriptor. */
  111.     pat.dsc$a_pointer = text;
  112.     pat.dsc$w_length = strlen(text);
  113.     pat.dsc$b_dtype = DSC$K_DTYPE_T;
  114.     pat.dsc$b_class = DSC$K_CLASS_S;
  115.  
  116.     /* Set up result descriptor. */
  117.     res.dsc$a_pointer = buff;
  118.     res.dsc$w_length = sizeof buff - 2;
  119.     res.dsc$b_dtype = DSC$K_DTYPE_T;
  120.     res.dsc$b_class = DSC$K_CLASS_S;
  121.  
  122.     /* Read files, collecting versions. */
  123.     for (context = 0; e->vms_verscount < VERSIZE(e); e->vms_verscount++) {
  124.     if (lib$find_file(&pat, &res, &context) == RMS$_NMF || context == 0)
  125.         break;
  126.     buff[sizeof buff - 1] = '\0';
  127.     if (p = strchr(buff, ';'))
  128.         e->vms_versions[e->vms_verscount] = atoi(p + 1);
  129.     else
  130.         e->vms_versions[e->vms_verscount] = -1;
  131.     }
  132.  
  133.     free(text);
  134. }
  135.  
  136.  
  137. /*
  138. **  Read the next entry from the directory.
  139. */
  140. struct dirent *
  141. readdir(dd)
  142.     DIR                *dd;
  143. {
  144.     struct dsc$descriptor_s    res;
  145.     char            *p;
  146.     char            buff[sizeof dd->entry.d_name];
  147.     int                i;
  148.  
  149.     /* Set up result descriptor, and get next file. */
  150.     res.dsc$a_pointer = buff;
  151.     res.dsc$w_length = sizeof buff - 2;
  152.     res.dsc$b_dtype = DSC$K_DTYPE_T;
  153.     res.dsc$b_class = DSC$K_CLASS_S;
  154.     if (lib$find_file(&dd->pat, &res, &dd->context) == RMS$_NMF
  155.      || dd->context == 0L)
  156.     /* None left... */
  157.     return NULL;
  158.  
  159.     /* Force the buffer to end with a NUL. */
  160.     buff[sizeof buff - 1] = '\0';
  161.     for (p = buff; !isspace(*p); p++)
  162.     ;
  163.     *p = '\0';
  164.  
  165.     /* Skip any directory component and just copy the name. */
  166.     if (p = strchr(buff, ']'))
  167.     (void)strcpy(dd->entry.d_name, p + 1);
  168.     else
  169.     (void)strcpy(dd->entry.d_name, buff);
  170.  
  171.     /* Clobber the version. */
  172.     if (p = strchr(dd->entry.d_name, ';'))
  173.     *p = '\0';
  174.  
  175.     dd->entry.vms_verscount = 0;
  176.     if (dd->vms_wantversions)
  177.     collectversions(dd);
  178.     return &dd->entry;
  179. }
  180.  
  181.  
  182. /*
  183. **  Return something that can be used in a seekdir later.
  184. */
  185. long
  186. telldir(dd)
  187.     DIR        *dd;
  188. {
  189.     return dd->context;
  190. }
  191.  
  192.  
  193. /*
  194. **  Return to a spot where we used to be.
  195. */
  196. void
  197. seekdir(dd, pos)
  198.     DIR        *dd;
  199.     long    pos;
  200. {
  201.     dd->context = pos;
  202. }
  203.  
  204.  
  205. #ifdef    TEST
  206. main()
  207. {
  208.     char        buff[256];
  209.     DIR            *dd;
  210.     struct dirent    *dp;
  211.     int            i;
  212.     int            j;
  213.  
  214.     for ( ; ; ) {
  215.     printf("\n\nEnter dir:  ");
  216.     (void)fflush(stdout);
  217.     (void)gets(buff);
  218.     if (buff[0] == '\0')
  219.         break;
  220.     if ((dd = opendir(buff)) == NULL) {
  221.         perror(buff);
  222.         continue;
  223.     }
  224.  
  225.     /* Print the directory contents twice, the second time print
  226.      * the versions. */
  227.     for (i = 0; i < 2; i++) {
  228.         while (dp = readdir(dd)) {
  229.         printf("%s%s", i ? "\t" : "    ", dp->d_name);
  230.         for (j = 0; j < dp->vms_verscount; j++)
  231.             printf("  %d", dp->vms_versions[j]);
  232.         printf("\n");
  233.         }
  234.         rewinddir(dd);
  235.         vmsreaddirversions(dd, 1);
  236.     }
  237.     closedir(dd);
  238.     }
  239.     exit(0);
  240. }
  241. #endif    /* TEST */
  242.