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