1/* $XConsortium: miscfuncs.c,v 1.7 94/12/01 17:15:05 kaleb Exp $ */ 2/* $XFree86: xc/programs/xmh/miscfuncs.c,v 3.6 2001/10/28 03:34:39 tsi Exp $ */ 3 4#include "xmh.h" 5 6#include <X11/Xos.h> 7 8#ifndef X_NOT_POSIX 9#include <dirent.h> 10#else 11#include <sys/dir.h> 12#ifndef dirent 13#define dirent direct 14#endif 15#endif 16 17#include <stdlib.h> 18 19 20 21/* 22** This code is by Rich Salz (rsalz@bbn.com), and ported to SVR4 23** by David Elliott (dce@smsc.sony.com). No copyrights were found 24** in the original. Subsequently modified by Bob Scheifler. 25*/ 26 27/* A convenient shorthand. */ 28typedef struct dirent ENTRY; 29 30/* Initial guess at directory size. */ 31#define INITIAL_SIZE 20 32 33static int StrCmp(char **a, char **b) 34{ 35 return strcmp(*a, *b); 36} 37 38int 39ScanDir( 40 const char *Name, 41 char ***List, 42 int (*Selector)(char *)) 43{ 44 register char **names; 45 register ENTRY *E; 46 register DIR *Dp = NULL; 47 register size_t i = 0; 48 register size_t size; 49 50 /* Get initial list space and open directory. */ 51 size = INITIAL_SIZE; 52 if (!(names = malloc(size * sizeof(char *))) || 53 !(Dp = opendir(Name))) 54 goto failure; 55 56 /* Read entries in the directory. */ 57 while ((E = readdir(Dp))) { 58 if (!Selector || (*Selector)(E->d_name)) { 59 /* User wants them all, or he wants this one. */ 60 if (++i >= size) { 61 char **newnames = NULL; 62 size <<= 1; 63 newnames = realloc(names, size * sizeof(char*)); 64 if (!newnames) { 65 i--; 66 goto failure; 67 } 68 names = newnames; 69 } 70 71 /* Copy the entry. */ 72 names[i - 1] = strdup(E->d_name); 73 if (names[i - 1] == NULL) { 74 goto failure; 75 } 76 } 77 } 78 79 /* Close things off. */ 80 names[i] = (char *)0; 81 *List = names; 82 closedir(Dp); 83 84 /* Sort? */ 85 if (i) 86 qsort((char *)names, i, sizeof(char *), 87 (int (*)(const void *, const void *))StrCmp); 88 89 return(i); 90 91 failure: 92 for (size_t n = 0; n < i; n++) { 93 free(names[i]); 94 } 95 free(names); 96 if (Dp != NULL) 97 closedir(Dp); 98 return(-1); 99} 100