home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume3 / pcmail / part03 / dir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-03  |  6.8 KB  |  250 lines

  1. /*++
  2. /* NAME
  3. /*      opendir,readdir,closedir 3
  4. /* SUMMARY
  5. /*      directory search functions
  6. /* PROJECT
  7. /*      dos/unix compatibility
  8. /* PACKAGE
  9. /*      library routines
  10. /* SYNOPSIS
  11. /*      int opendir(path)
  12. /*      char *path;
  13. /*
  14. /*      char *readdir(id)
  15. /*      int dir;
  16. /*
  17. /*      closedir(id)
  18. /*      int id;
  19. /* DESCRIPTION
  20. /*      This package provides a system-independent interface to the file system
  21. /*      that allows a program to simultaneously scan one or more directories.
  22. /*
  23. /*    The MS-DOS version accepts both forward and backward slash as
  24. /*    field delimiter in path names.
  25. /*
  26. /*      opendir() accepts a valid path and returns an id which should be used 
  27. /*      in subsequent calls of readdir()....closedir().
  28. /*
  29. /*      readdir() returns a pointer to a character string with the next file in
  30. /*      the directory associated with id, or a null pointer. 
  31. /*
  32. /*      closedir() terminates the directory search and deallocates
  33. /*      memory used to keep track of `certain important data'.
  34. /* FUNCTIONS AND MACROS
  35. /*      myalloc()
  36. /* DIAGNOSTICS
  37. /*      opendir() returns -1 if all slots are in use.
  38. /*      Specifying a wrong id is considered a fatal error condition.
  39. /*      Memory allocation errors cause the program to terminate.
  40. /* BUGS
  41. /*      readdir() returns a pointer to memory
  42. /*      whose contents is overwritten with each call.
  43. /*
  44. /*    Despite whatthe names suggest, these functions are not compatible
  45. /*    with the BSD directory access routines.
  46. /*
  47. /*    Does not work with unix file systems that have variable-length
  48. /*    directory entries (BSD).
  49. /* AUTHOR(S)
  50. /*      Wietse Venema
  51. /*      Eindhoven University of Technology
  52. /*      Department of Mathematics and Computer Science
  53. /*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  54. /* CREATION DATE
  55. /*      Mon Nov 17 19:38:19 GMT+1:00 1986
  56. /* LAST MODIFICATION
  57. /*    Mon Apr  4 23:38:43 MET 1988
  58. /* VERSION/RELEASE
  59. /*    1.3
  60. /*--*/
  61.  
  62. #include "defs.h"
  63. #include "dir.h"
  64.  
  65. #ifdef    unix
  66. #   include <sys/types.h>
  67. #   include <sys/dir.h>
  68. #endif
  69.  
  70. #ifdef    MSDOS
  71. #   include <dos.h>
  72. #   include <ctype.h>
  73.  
  74. hidden void badslot();            /* forward declarations */
  75. hidden void lowcpy();
  76.  
  77. /* 
  78. * The Disk Transfer Area as used by MS-DOS when it finds a file name 
  79. * during a wild-card scan.
  80. */
  81.  
  82. #define MAXNAME         13      /* max size of MS-DOS file name + null byte */
  83.  
  84. typedef struct Dta {
  85.     char reserved[21];          /* start of dta buffer */ 
  86.     char found;                 /* attribute found */
  87.     short time;                 /* file's time */
  88.     short date;                 /* file's date */
  89.     int losize;                 /* low order file size */
  90.     int hisize;                 /* high-order file size */
  91.     char name[MAXNAME];         /* name of file terminated by zero byte */
  92. } Dta;
  93.  
  94. /* macros for easy access to registers with MS-DOS system calls */
  95.  
  96. #define AH              regs.h.ah               /* ah register */
  97. #define BX              regs.x.bx               /* bx register */
  98. #define CX              regs.x.cx               /* cx register */
  99. #define DX              regs.x.dx               /* dx register */
  100. #define CF              regs.x.cflag            /* cflag register */
  101. #define INT             intdos(®s,®s)     /* dos system call */
  102. #define WORD            (unsigned)              /* cast */
  103.  
  104. #define SET_DTA(d)      { AH = 0x1a; DX = WORD d; INT; }
  105. #define GET_DTA(d)      { AH = 0x2f; INT; d = BX; }
  106. #define GET_1ST(f,n)    { AH = 0x4e; CX = 0x10; DX = WORD n; INT; f = CF; }
  107. #define GET_NXT(f)      { AH = 0x4f; CX = 0x10; INT; f = CF; }
  108.  
  109. /* information about directory accesses is kept in a table with initially */
  110. /* empty slots */
  111.  
  112. #define MAXSLOT 20              /* nbr of directories that can be processed */
  113.  
  114. typedef struct Slot {
  115.     unsigned int dsave;         /* temp storage for disk transfer address */
  116.     unsigned int cstat;         /* MS-DOS system call return status */
  117.     Dta dta;                    /* disk transfer area */
  118. } Slot;
  119.  
  120. hidden Slot *dirslots[20];      /* slots with pointers */
  121.  
  122. #endif    /* MSDOS */
  123.  
  124. /* opendir - set up for directory search */
  125.  
  126. #ifdef    MSDOS
  127.  
  128. public int opendir(name)
  129. char *name;
  130. {
  131.     register int id;
  132.     register Slot *q;
  133.     char buf[BUFSIZ];
  134.     union REGS regs;                    /* cpu registers in system call */
  135.     char lch;
  136.  
  137.     for (id = 0; id < MAXSLOT && dirslots[id]; id++)
  138.     ;                               /* search first free slot */
  139.     if (id < MAXSLOT) {                 /* found a free slot */
  140.     dirslots[id] = q = (Slot *) myalloc(sizeof(Slot));
  141.     GET_DTA(q->dsave);              /* save dta address */
  142.     SET_DTA(&q->dta);               /* set to current dta */
  143.     strcpy(buf,name);               /* construct search path */
  144.     if (*name && index("\\/:",name[strlen(name)-1]) == 0)
  145.         strcat(buf,"/");
  146.     strcat(buf,"*.*");              /* append wildest possible file name */
  147.     GET_1ST(q->cstat,buf);          /* start search (read one name ahead) */
  148.     SET_DTA(q->dsave);              /* restore dta address */
  149.     return(id);                     /* return offset in slots table */
  150.     } else {
  151.     return(-1);                     /* no free slot available */
  152.     }
  153. }
  154.  
  155. #endif    /* MSDOS */
  156.  
  157. /* readdir - return next file in directory or null string */
  158.  
  159. #ifdef    unix
  160.  
  161. public char *readdir(id)
  162. int id;
  163. {
  164.     static struct direct ent[2];
  165.  
  166.     for (;;) {
  167.     if (read(id,(char *) ent,sizeof(*ent)) != sizeof(*ent))
  168.         return(0);
  169.     if (ent[0].d_ino != 0)
  170.         return(ent[0].d_name);
  171.     }
  172. }
  173.  
  174. #endif    /* unix */
  175.  
  176. #ifdef    MSDOS
  177.  
  178. public char *readdir(id)
  179. int id;
  180. {
  181.     register Slot *q;
  182.     union REGS regs;
  183.     static char buf[MAXNAME];
  184.  
  185.     if (id < 0 || id >= MAXSLOT || (q = dirslots[id]) == 0) {
  186.     badslot("readdir",id);        /* serves you well! */
  187.     /* NOTREACHED */
  188.     } else if (q->cstat) {
  189.     return(0);            /* no name found */
  190.     } else {
  191.     lowcpy(buf,q->dta.name);        /* keep name (lower case) */
  192.     GET_DTA(q->dsave);              /* save dta address */
  193.     SET_DTA(&q->dta);               /* setup to search */
  194.     GET_NXT(q->cstat);              /* for the next entry */
  195.     SET_DTA(q->dsave);              /* in the directory */
  196.     return buf;                     /* return name */
  197.     }
  198. }
  199.  
  200. #endif    /* MSDOS */
  201.  
  202. /* closedir - release directory access slot */
  203.  
  204. #ifdef    MSDOS
  205.  
  206. public int closedir(id)
  207. int id;
  208. {
  209.     register Slot **p;
  210.  
  211.     if (id < 0 || id >= MAXSLOT || *(p = dirslots+id) == 0) {
  212.     badslot("closedir",id);
  213.     /* NOTREACHED */
  214.     } else {
  215.     free((char *)*p);               /* deallocate slot */
  216.     *p = 0;                         /* mark as unused */
  217.     return(0);
  218.     }
  219. }
  220.  
  221. #endif    /* MSDOS */
  222.  
  223. #ifdef    MSDOS
  224.  
  225. /* badslot - the program is obviously corrupted. stop it. */
  226.  
  227. hidden void badslot(name,id)
  228. char *name;
  229. int id;
  230. {
  231.     fatal("%s: bad slot: %d\n",name,id);
  232. }
  233.  
  234. /* lowcpy - copy string and map to lower case */
  235.  
  236. hidden void lowcpy(out,in)
  237. char *out;
  238. char *in;
  239. {
  240.     register char *d = out;
  241.     register char c;
  242.     register char *s = in;
  243.  
  244.     while (c = *s++)
  245.     *d++ = isupper(c) ? tolower(c) : c;
  246.     *d = '\0';
  247. }
  248.  
  249. #endif    /* MSDOS */
  250.