1c9e2be55Smrg/* $XConsortium: miscfuncs.c,v 1.7 94/12/01 17:15:05 kaleb Exp $ */
2c9e2be55Smrg/* $XFree86: xc/programs/xmh/miscfuncs.c,v 3.6 2001/10/28 03:34:39 tsi Exp $ */
3c9e2be55Smrg
4c9e2be55Smrg#include "xmh.h"
5c9e2be55Smrg
6c9e2be55Smrg#include <X11/Xos.h>
7c9e2be55Smrg
8c9e2be55Smrg#ifndef X_NOT_POSIX
9c9e2be55Smrg#include <dirent.h>
10c9e2be55Smrg#else
11c9e2be55Smrg#include <sys/dir.h>
12c9e2be55Smrg#ifndef dirent
13c9e2be55Smrg#define dirent direct
14c9e2be55Smrg#endif
15c9e2be55Smrg#endif
16c9e2be55Smrg
17c9e2be55Smrg#include <stdlib.h>
18c9e2be55Smrg
19c9e2be55Smrg
20c9e2be55Smrg
21c9e2be55Smrg/*
22c9e2be55Smrg**  This code is by Rich Salz (rsalz@bbn.com), and ported to SVR4
23c9e2be55Smrg**  by David Elliott (dce@smsc.sony.com).  No copyrights were found
24c9e2be55Smrg**  in the original.  Subsequently modified by Bob Scheifler.
25c9e2be55Smrg*/
26c9e2be55Smrg
27c9e2be55Smrg/* A convenient shorthand. */
28c9e2be55Smrgtypedef struct dirent	 ENTRY;
29c9e2be55Smrg
30c9e2be55Smrg/* Initial guess at directory size. */
31c9e2be55Smrg#define INITIAL_SIZE	20
32c9e2be55Smrg
33c9e2be55Smrgstatic int StrCmp(char **a, char **b)
34c9e2be55Smrg{
35c9e2be55Smrg    return strcmp(*a, *b);
36c9e2be55Smrg}
37c9e2be55Smrg
38c9e2be55Smrgint
39c9e2be55SmrgScanDir(
4066d665a3Smrg    const char		  *Name,
41c9e2be55Smrg    char		***List,
42c9e2be55Smrg    int			 (*Selector)(char *))
43c9e2be55Smrg{
44c9e2be55Smrg    register char	 **names;
45c9e2be55Smrg    register ENTRY	  *E;
4666d665a3Smrg    register DIR	  *Dp = NULL;
4766d665a3Smrg    register size_t	   i = 0;
4866d665a3Smrg    register size_t	   size;
49c9e2be55Smrg
50c9e2be55Smrg    /* Get initial list space and open directory. */
51c9e2be55Smrg    size = INITIAL_SIZE;
5266d665a3Smrg    if (!(names = malloc(size * sizeof(char *))) ||
53c9e2be55Smrg	!(Dp = opendir(Name)))
5466d665a3Smrg	goto failure;
55c9e2be55Smrg
56c9e2be55Smrg    /* Read entries in the directory. */
5766d665a3Smrg    while ((E = readdir(Dp))) {
58c9e2be55Smrg	if (!Selector || (*Selector)(E->d_name)) {
59c9e2be55Smrg	    /* User wants them all, or he wants this one. */
60c9e2be55Smrg	    if (++i >= size) {
6166d665a3Smrg		char **newnames = NULL;
62c9e2be55Smrg		size <<= 1;
6366d665a3Smrg		newnames = realloc(names, size * sizeof(char*));
6466d665a3Smrg		if (!newnames) {
6566d665a3Smrg		    i--;
6666d665a3Smrg		    goto failure;
67c9e2be55Smrg		}
6866d665a3Smrg		names = newnames;
69c9e2be55Smrg	    }
70c9e2be55Smrg
71c9e2be55Smrg	    /* Copy the entry. */
7266d665a3Smrg	    names[i - 1] = strdup(E->d_name);
7366d665a3Smrg	    if (names[i - 1] == NULL) {
7466d665a3Smrg		goto failure;
75c9e2be55Smrg	    }
76c9e2be55Smrg	}
7766d665a3Smrg    }
78c9e2be55Smrg
79c9e2be55Smrg    /* Close things off. */
80c9e2be55Smrg    names[i] = (char *)0;
81c9e2be55Smrg    *List = names;
82c9e2be55Smrg    closedir(Dp);
83c9e2be55Smrg
84c9e2be55Smrg    /* Sort? */
85c9e2be55Smrg    if (i)
86e2264b6dSmrg	qsort((char *)names, i, sizeof(char *),
87e2264b6dSmrg	      (int (*)(const void *, const void *))StrCmp);
88c9e2be55Smrg
89c9e2be55Smrg    return(i);
9066d665a3Smrg
9166d665a3Smrg  failure:
9266d665a3Smrg    for (size_t n = 0; n < i; n++) {
9366d665a3Smrg	free(names[i]);
9466d665a3Smrg    }
9566d665a3Smrg    free(names);
9666d665a3Smrg    if (Dp != NULL)
9766d665a3Smrg	closedir(Dp);
9866d665a3Smrg    return(-1);
99c9e2be55Smrg}
100