/*
**  SCANDIR
**  Scan a directory, collecting all (selected) items into a an array.
*/
#ifdef MWC
#include <types.h>
#include "ndir.h"
#else
#include <sys/types.h>
#include <sys/dir.h>
#endif

#ifdef  RCSID
static char RCS[] = "$Header: scandir.c,v 1.1 87/12/29 21:35:56 rsalz Exp $";
#endif  /* RCSID */

/* Initial guess at directory size. */
#define INITIAL_SIZE    20

/* A convenient shorthand. */
typedef struct direct    ENTRY;

/* Linked in later. */
extern char     *malloc();
extern char     *realloc();
extern char     *strcpy();


int
scandir(Name, List, Selector, Sorter)
    char          *Name;
    ENTRY       ***List;
    int          (*Selector)();
    int          (*Sorter)();
{
    register ENTRY   **names;
    register ENTRY    *E;
    register DIR      *Dp;
    register int       i;
    register int       size;

    /* Get initial list space and open directory. */
    size = INITIAL_SIZE;
    if ((names = (ENTRY **)malloc(size * sizeof names[0])) == NULL || (Dp = opendir(Name)) == NULL)
        return(-1);

    /* Read entries in the directory. */
    for (i = 0; E = readdir(Dp); )
    {
        if (Selector == NULL || (*Selector)(E))
	{
            /* User wants them all, or he wants this one. */
            if (++i >= size)
	    {
                size <<= 1;
                names = (ENTRY **)realloc((char *)names, size * sizeof names[0]);
                if (names == NULL)
		{
                    closedir(Dp);
                    return(-1);
                }
            }
            /* Copy the entry. */
            if ((names[i - 1] = (ENTRY *)malloc(DIRSIZ(E))) == NULL)
	    {
                closedir(Dp);
                return(-1);
            }
            names[i - 1]->d_ino = E->d_ino;
            names[i - 1]->d_reclen = E->d_reclen;
            names[i - 1]->d_namlen = E->d_namlen;
            (void)strcpy(names[i - 1]->d_name, E->d_name);
        }
    }
    /* Close things off. */
    names[i] = NULL;
    *List = names;
    closedir(Dp);

    /* Sort? */
    if (i && Sorter)
        qsort((char *)names, i, sizeof names[0], Sorter);

    return(i);
}
