/*
 * Directory-reading calls
 *
 * int OpenDir(pathname) - open a directory for reading
 * char *ReadDir() - return next name from directory or NULL
 * void CloseDir() - close directory
 */


#if !HAS_DIRENT_H && !HAS_SYS_DIR_H
*** error -- neither opendir()/readdir() nor scandir() are present?
#endif

#include	<stdio.h>
#include	<sys/types.h>
#if HAS_DIRENT_H
#  include	<dirent.h>
#else
#  if HAS_SYS_DIR_H
#    include	<sys/dir.h>
#  endif
#endif

#include	"portlib.h"


#if HAS_DIRENT_H		/* opendir() version of directory functions */

static DIR	*dir = (DIR *) NULL;

int
OpenDir (pathname)
char	*pathname;
{

#ifdef DEBUG
printf ("using opendir() to read %s\n", pathname);
#endif
	CloseDir ();		/* close previous directory if one is open */
	dir = opendir (pathname);
	if (dir != (DIR *) NULL)
		return (1);
#ifdef DEBUG
	perror ("OpenDir");
#endif
	return (0);
}


char *
ReadDir ()
{
struct dirent	*dp;

	if (dir != (DIR *) NULL)	/* directory is open */
	{
		dp = readdir (dir);
		if (dp != (struct dirent *) NULL)
			return (dp->d_name);
		CloseDir ();
	}
	return ((char *) NULL);
}


void
CloseDir ()
{
	if (dir != (DIR *) NULL)
		(void) closedir (dir);
	dir = (DIR *) NULL;
}


#else

#if HAS_SYS_DIR_H		/* scandir() version of directory functions */

/*
 * Use scandir() to simulate an opendir()/readdir()/closedir() interface.
 */

static struct direct	**dp = (struct direct **) NULL;
static int	count = 0;
static int	index = 0;

int
OpenDir (pathname)
char	*pathname;
{

#ifdef DEBUG
printf ("using scandir() to read %s\n", pathname);
#endif
	CloseDir ();		/* close previous directory if one is open */
	count = scandir (pathname, &dp, NULL, NULL);
	if (count >= 0)
	{
		return (1);
	}
#ifdef DEBUG
	perror ("OpenDir");
#endif
	count = 0;
	return (0);
}


char *
ReadDir ()
{
	if (index < count)
		return (dp[index++]->d_name);
	CloseDir ();
	return ((char *) NULL);
}


/*
 * It seems to me that the memory pointed to by dp should be freed,
 * but adding free(dp) to the function below makes no difference.
 * Perhaps it's necessary to walk through the entries and free them
 * individually.
 */

void
CloseDir ()
{
	dp = (struct direct **) NULL;
	count = 0;
	index = 0;
}

#endif /* HAS_SYS_DIR_H */

#endif /* HAS_DIRENT_H */
