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