From 05b8eff319536ade894d07705bc74abaf425788e Mon Sep 17 00:00:00 2001
From: Roy Marples <roy@marples.name>
Date: Fri, 5 Oct 2007 10:16:14 +0000
Subject: Punt rc_ls_dir

---
 src/env-update.c   |  87 ++++++++++++++++++++++++----------------------
 src/librc-daemon.c |  79 +++++++++++++++++++++++++-----------------
 src/librc-depend.c |  34 +++++++++---------
 src/librc-misc.c   |  41 ----------------------
 src/librc.c        |  62 ++++++++++++++++++++++++++++-----
 src/librc.h        |   1 -
 src/rc-depend.c    |   2 +-
 src/rc-plugin.c    |  28 ++++++++-------
 src/rc.c           | 100 ++++++++++++++++++++++++++---------------------------
 src/rc.h           |  11 ------
 src/rc.map         |   1 -
 11 files changed, 229 insertions(+), 217 deletions(-)

diff --git a/src/env-update.c b/src/env-update.c
index c9fbf1a8..2f97719f 100644
--- a/src/env-update.c
+++ b/src/env-update.c
@@ -12,6 +12,7 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
@@ -90,8 +91,8 @@ static const char * const longopts_help[] = {
 
 int env_update (int argc, char **argv)
 {
-	char **files = rc_ls_dir (ENVDIR, 0);
-	char *file;
+	DIR *dp;
+	struct dirent *d;
 	char **envs = NULL;
 	char *env;
 	int i = 0;
@@ -108,6 +109,9 @@ int env_update (int argc, char **argv)
 	bool ldconfig = true;
 	bool fork_ldconfig = false;
 	int nents = 0;
+	char *path;
+	char **entries = NULL;
+	struct stat buf;
 
 	applet = argv[0];
 
@@ -126,45 +130,50 @@ int env_update (int argc, char **argv)
 		}
 	}
 
-	if (! files)
-		eerrorx ("%s: no files in " ENVDIR " to process", applet);
+	if (! (dp = opendir (ENVDIR)))
+		eerrorx ("%s: opendir `" ENVDIR "': %s", applet, strerror (errno));
 
-	STRLIST_FOREACH (files, file, i) {
-		char *path = rc_strcatpaths (ENVDIR, file, (char *) NULL);
-		char **entries = NULL;
-		struct stat buf;
+	while ((d = readdir (dp))) {
+		if (d->d_name[0] == '.')
+			continue;
 
-		j = strlen (file);
-		if (stat (file, &buf) == 0 && S_ISDIR (buf.st_mode) == 0 &&
+		j = strlen (d->d_name);
+		if (stat (d->d_name, &buf) == 0 && S_ISDIR (buf.st_mode) == 0 &&
 			j > 2 &&
-			*file >= '0' &&
-			*file <= '9' &&
-			*(file + 1) >= '0' &&
-			*(file + 1) <= '9' &&
-			*(file + j - 1) != '~' &&
-			(j < 4 || strcmp (file + j - 4, ".bak") != 0) &&
-			(j < 5 || strcmp (file + j - 5, ".core") != 0))
+			d->d_name[0] >= '0' &&
+			d->d_name[0] <= '9' &&
+			d->d_name[1] >= '0' &&
+			d->d_name[1] <= '9' &&
+			d->d_name[j - 1] != '~' &&
+			(j < 4 || strcmp (d->d_name + j - 4, ".bak") != 0) &&
+			(j < 5 || strcmp (d->d_name + j - 5, ".core") != 0))
+		{
+			path = rc_strcatpaths (ENVDIR, d->d_name, (char *) NULL);
 			entries = rc_config_load (path);
-		free (path);
-
-		STRLIST_FOREACH (entries, entry, j) {
-			char *tmpent = rc_xstrdup (entry);
-			char *value = tmpent;
-			char *var = strsep (&value, "=");
-
-			if (strcmp (var, "COLON_SEPARATED") == 0)
-				while ((var = strsep (&value, " ")))
-					rc_strlist_addu (&mycolons, var);
-			else if (strcmp (var, "SPACE_SEPARATED") == 0)
-				while ((var = strsep (&value, " ")))
-					rc_strlist_addu (&myspaces, var);
-			else 
-				rc_strlist_add (&config, entry);
-			free (tmpent);
+			free (path);
+
+			STRLIST_FOREACH (entries, entry, j) {
+				char *tmpent = rc_xstrdup (entry);
+				char *value = tmpent;
+				char *var = strsep (&value, "=");
+
+				if (strcmp (var, "COLON_SEPARATED") == 0)
+					while ((var = strsep (&value, " ")))
+						rc_strlist_addu (&mycolons, var);
+				else if (strcmp (var, "SPACE_SEPARATED") == 0)
+					while ((var = strsep (&value, " ")))
+						rc_strlist_addu (&myspaces, var);
+				else 
+					rc_strlist_add (&config, entry);
+				free (tmpent);
+			}
+			rc_strlist_free (entries);
 		}
-
-		rc_strlist_free (entries);
 	}
+	closedir (dp);
+
+	if (! config)
+		eerrorx ("%s: nothing to process", applet);
 
 	STRLIST_FOREACH (config, entry, i) {
 		char *tmpent = rc_xstrdup (entry);
@@ -241,7 +250,6 @@ int env_update (int argc, char **argv)
 	rc_strlist_free (mycolons);
 	rc_strlist_free (myspaces);
 	rc_strlist_free (config);
-	rc_strlist_free (files);
 
 	if ((fp = fopen (PROFILE_ENV, "w")) == NULL)
 		eerrorx ("%s: fopen `%s': %s", applet, PROFILE_ENV, strerror (errno));
@@ -288,11 +296,8 @@ int env_update (int argc, char **argv)
 		return (EXIT_SUCCESS);
 	}
 
-	while ((file = strsep (&ldent, ":"))) {
-		if (strlen (file) == 0)
-			continue;
-
-		if (rc_strlist_addu (&ldents, file))
+	while ((env = strsep (&ldent, ":"))) {
+		if (*env && rc_strlist_addu (&ldents, env))
 			nents++;
 	}
 
diff --git a/src/librc-daemon.c b/src/librc-daemon.c
index 90d28c6f..ebad6a54 100644
--- a/src/librc-daemon.c
+++ b/src/librc-daemon.c
@@ -289,9 +289,7 @@ bool rc_service_daemon_set (const char *service, const char *exec,
 {
 	char *svc;
 	char *dirpath;
-	char **files = NULL;
-	char *file;
-	char *ffile = NULL;
+	char *file = NULL;
 	int i;
 	char *mexec;
 	char *mname;
@@ -299,6 +297,8 @@ bool rc_service_daemon_set (const char *service, const char *exec,
 	int nfiles = 0;
 	char *oldfile = NULL;
 	bool retval = false;
+	DIR *dp;
+	struct dirent *d;
 
 	if (! exec && ! name && ! pidfile) {
 		errno = EINVAL;
@@ -331,25 +331,30 @@ bool rc_service_daemon_set (const char *service, const char *exec,
 		mpidfile = rc_xstrdup ("pidfile=");
 
 	/* Regardless, erase any existing daemon info */
-	files = rc_ls_dir (dirpath, 0);
-	STRLIST_FOREACH (files, file, i) {
-		ffile = rc_strcatpaths (dirpath, file, (char *) NULL);
-		nfiles++;
-
-		if (! oldfile) {
-			if (_match_daemon (dirpath, file, mexec, mname, mpidfile)) {
-				unlink (ffile);
-				oldfile = ffile;
-				nfiles--;
+	if ((dp = opendir (dirpath))) {
+		while ((d = readdir (dp))) {
+			if (d->d_name[0] == '.')
+				continue;
+			file = rc_strcatpaths (dirpath, d->d_name, (char *) NULL);
+			nfiles++;
+
+			if (! oldfile) {
+				if (_match_daemon (dirpath, d->d_name,
+								   mexec, mname, mpidfile))
+				{
+					unlink (file);
+					oldfile = file;
+					nfiles--;
+				}
+			} else {
+				rename (file, oldfile);
+				free (oldfile);
+				oldfile = file;
 			}
-		} else {
-			rename (ffile, oldfile);
-			free (oldfile);
-			oldfile = ffile;
 		}
+		free (file);
+		closedir (dp);
 	}
-	free (ffile); 
-	rc_strlist_free (files);
 
 	/* Now store our daemon info */
 	if (started) {
@@ -387,6 +392,8 @@ bool rc_service_started_daemon (const char *service, const char *exec,
 	char *mexec;
 	bool retval = false;
 	char *svc;
+	DIR *dp;
+	struct dirent *d;
 
 	if (! service || ! exec)
 		return (false);
@@ -407,13 +414,16 @@ bool rc_service_started_daemon (const char *service, const char *exec,
 		retval = _match_daemon (dirpath, file, mexec, NULL, NULL);
 		free (file);
 	} else {
-		char **files = rc_ls_dir (dirpath, 0);
-		STRLIST_FOREACH (files, file, i) {
-			retval = _match_daemon (dirpath, file, mexec, NULL, NULL);
-			if (retval)
-				break;
+		if ((dp = opendir (dirpath))) {
+			while ((d = readdir (dp))) {
+				if (d->d_name[0] == ',')
+					continue;
+				retval = _match_daemon (dirpath, d->d_name, mexec, NULL, NULL);
+				if (retval)
+					break;
+			}
+			closedir (dp);
 		}
-		rc_strlist_free (files);
 	}
 
 	free (dirpath);
@@ -425,10 +435,9 @@ librc_hidden_def(rc_service_started_daemon)
 bool rc_service_daemons_crashed (const char *service)
 {
 	char *dirpath;
-	char **files;
-	char *file;
+	DIR *dp;
+	struct dirent *d;
 	char *path;
-	int i;
 	FILE *fp;
 	char buffer[RC_LINEBUFFER];
 	char *exec = NULL;
@@ -449,10 +458,16 @@ bool rc_service_daemons_crashed (const char *service)
 							  (char *) NULL);
 	free (svc);
 
+	if (! (dp = opendir (dirpath)))
+		return (false);
+
 	memset (buffer, 0, sizeof (buffer));
-	files = rc_ls_dir (dirpath, 0);
-	STRLIST_FOREACH (files, file, i) {
-		path = rc_strcatpaths (dirpath, file, (char *) NULL);
+
+	while ((d = readdir (dp))) {
+		if (d->d_name[0] == '.')
+			continue;
+
+		path = rc_strcatpaths (dirpath, d->d_name, (char *) NULL);
 		fp = fopen (path, "r");
 		free (path);
 		if (! fp)
@@ -530,7 +545,7 @@ bool rc_service_daemons_crashed (const char *service)
 	free (exec);
 	free (name);
 	free (dirpath);
-	rc_strlist_free (files);
+	closedir (dp);
 
 	return (retval);
 }
diff --git a/src/librc-depend.c b/src/librc-depend.c
index c701c214..4794c856 100644
--- a/src/librc-depend.c
+++ b/src/librc-depend.c
@@ -497,13 +497,13 @@ char **rc_deptree_order_services (rc_depinfo_t *deptree, const char *runlevel,
 		strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
 		strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
 	{
-		list = rc_ls_dir (RC_SVCDIR_STARTING, RC_LS_INITD);
+		list = rc_services_in_state (RC_SERVICE_STARTED);
 
-		tmp = rc_ls_dir (RC_SVCDIR_INACTIVE, RC_LS_INITD);
+		tmp = rc_services_in_state (RC_SERVICE_INACTIVE);
 		rc_strlist_join (&list, tmp);
 		rc_strlist_free (tmp);
 
-		tmp = rc_ls_dir (RC_SVCDIR_INACTIVE, RC_LS_INITD);
+		tmp = rc_services_in_state (RC_SERVICE_STARTING);
 		rc_strlist_join (&list, tmp);
 		rc_strlist_free (tmp);
 		reverse = true;
@@ -511,18 +511,15 @@ char **rc_deptree_order_services (rc_depinfo_t *deptree, const char *runlevel,
 		list = rc_services_in_runlevel (runlevel);
 
 		/* Add coldplugged services */
-		tmp = rc_ls_dir (RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
+		tmp = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
 		rc_strlist_join (&list, tmp);
 		rc_strlist_free (tmp);
 
 		/* If we're not the boot runlevel then add that too */
 		if (strcmp (runlevel, bootlevel) != 0) {
-			char *path = rc_strcatpaths (RC_RUNLEVELDIR, bootlevel,
-										 (char *) NULL);
-			tmp = rc_ls_dir (path, RC_LS_INITD);
+			tmp = rc_services_in_runlevel (bootlevel);
 			rc_strlist_join (&list, tmp);
 			rc_strlist_free (tmp);
-			free (path);
 		}
 	}
 
@@ -547,10 +544,10 @@ static bool is_newer_than (const char *file, const char *target)
 {
 	struct stat buf;
 	time_t mtime;
-	char **targets;
-	char *t;
-	int i;
 	bool newer = true;
+	DIR *dp;
+	struct dirent *d;
+	char *path;
 
 	if (stat (file, &buf) != 0 || buf.st_size == 0)
 		return (false);
@@ -564,16 +561,21 @@ static bool is_newer_than (const char *file, const char *target)
 	if (mtime < buf.st_mtime)
 		return (false);
 
-	targets = rc_ls_dir (target, 0);
-	STRLIST_FOREACH (targets, t, i)
-	{
-		char *path = rc_strcatpaths (target, t, (char *) NULL);
+	if (! (dp = opendir (target)))
+		return (true);
+
+	while ((d = readdir (dp))) {
+		if (d->d_name[0] == '.')
+			continue;
+
+		path = rc_strcatpaths (target, d->d_name, (char *) NULL);
 		newer = is_newer_than (file, path);
 		free (path);
 		if (! newer)
 			break;
 	}
-	rc_strlist_free (targets);
+	closedir (dp);
+
 	return (newer);
 }
 
diff --git a/src/librc-misc.c b/src/librc-misc.c
index f255f706..11cbadc6 100644
--- a/src/librc-misc.c
+++ b/src/librc-misc.c
@@ -94,47 +94,6 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...)
 }
 librc_hidden_def(rc_strcatpaths)
 
-char **rc_ls_dir (const char *dir, int options)
-{
-	DIR *dp;
-	struct dirent *d;
-	char **list = NULL;
-
-	if ((dp = opendir (dir)) == NULL) 
-		return (NULL);
-
-	errno = 0;
-	while (((d = readdir (dp)) != NULL) && errno == 0) {
-		if (d->d_name[0] != '.') {
-			if (options & RC_LS_INITD) {
-				int l = strlen (d->d_name);
-				char *init = rc_strcatpaths (RC_INITDIR, d->d_name,
-											 (char *) NULL);
-				bool ok = rc_exists (init);
-				free (init);
-				if (! ok)
-					continue;
-
-				/* .sh files are not init scripts */
-				if (l > 2 && d->d_name[l - 3] == '.' &&
-					d->d_name[l - 2] == 's' &&
-					d->d_name[l - 1] == 'h')
-					continue;
-			}
-			if (options & RC_LS_DIR) {
-				struct stat buf;
-
-				if (stat (d->d_name, &buf) == 0 && ! S_ISDIR (buf.st_mode))
-					continue;
-			}
-			rc_strlist_addsort (&list, d->d_name);
-		}
-	}
-	closedir (dp);
-
-	return (list);
-}
-librc_hidden_def(rc_ls_dir)
 
 bool rc_rm_dir (const char *pathname, bool top)
 {
diff --git a/src/librc.c b/src/librc.c
index 0aecc4c7..1ff76928 100644
--- a/src/librc.c
+++ b/src/librc.c
@@ -42,6 +42,50 @@ static const rc_service_state_name_t rc_service_state_names[] = {
 	{ 0, NULL}
 };
 
+
+#define LS_INITD	0x01
+#define LS_DIR   0x02
+static char **ls_dir (const char *dir, int options)
+{
+	DIR *dp;
+	struct dirent *d;
+	char **list = NULL;
+
+	if ((dp = opendir (dir)) == NULL) 
+		return (NULL);
+
+	errno = 0;
+	while (((d = readdir (dp)) != NULL) && errno == 0) {
+		if (d->d_name[0] != '.') {
+			if (options & LS_INITD) {
+				int l = strlen (d->d_name);
+				char *init = rc_strcatpaths (RC_INITDIR, d->d_name,
+											 (char *) NULL);
+				bool ok = rc_exists (init);
+				free (init);
+				if (! ok)
+					continue;
+
+				/* .sh files are not init scripts */
+				if (l > 2 && d->d_name[l - 3] == '.' &&
+					d->d_name[l - 2] == 's' &&
+					d->d_name[l - 1] == 'h')
+					continue;
+			}
+			if (options & LS_DIR) {
+				struct stat buf;
+
+				if (stat (d->d_name, &buf) == 0 && ! S_ISDIR (buf.st_mode))
+					continue;
+			}
+			rc_strlist_addsort (&list, d->d_name);
+		}
+	}
+	closedir (dp);
+
+	return (list);
+}
+
 static const char *rc_parse_service_state (rc_service_state_t state)
 {
 	int i;
@@ -68,7 +112,7 @@ librc_hidden_def(rc_runlevel_stopping)
 
 char **rc_runlevel_list (void)
 {
-	return (rc_ls_dir (RC_RUNLEVELDIR, RC_LS_DIR));
+	return (ls_dir (RC_RUNLEVELDIR, LS_DIR));
 }
 librc_hidden_def(rc_runlevel_list)
 
@@ -376,7 +420,7 @@ bool rc_service_mark (const char *service, const rc_service_state_t state)
 	/* These are final states, so remove us from scheduled */
 	if (state == RC_SERVICE_STARTED || state == RC_SERVICE_STOPPED) {
 		char *sdir = rc_strcatpaths (RC_SVCDIR, "scheduled", (char *) NULL);
-		char **dirs = rc_ls_dir (sdir, 0);
+		char **dirs = ls_dir (sdir, 0);
 		char *dir;
 		int serrno;
 
@@ -657,7 +701,7 @@ char **rc_services_in_runlevel (const char *runlevel)
 	char **list = NULL;
 
 	if (! runlevel)
-		return (rc_ls_dir (RC_INITDIR, RC_LS_INITD));
+		return (ls_dir (RC_INITDIR, LS_INITD));
 
 	/* These special levels never contain any services */
 	if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 ||
@@ -665,7 +709,7 @@ char **rc_services_in_runlevel (const char *runlevel)
 		return (NULL);
 
 	dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
-	list = rc_ls_dir (dir, RC_LS_INITD);
+	list = ls_dir (dir, LS_INITD);
 	free (dir);
 	return (list);
 }
@@ -678,13 +722,13 @@ char **rc_services_in_state (rc_service_state_t state)
 	char **list = NULL;
 
 	if (state == RC_SERVICE_SCHEDULED) {
-		char **dirs = rc_ls_dir (dir, 0);
+		char **dirs = ls_dir (dir, 0);
 		char *d;
 		int i;
 
 		STRLIST_FOREACH (dirs, d, i) {
 			char *p = rc_strcatpaths (dir, d, (char *) NULL);
-			char **entries = rc_ls_dir (p, RC_LS_INITD);
+			char **entries = ls_dir (p, LS_INITD);
 			char *e;
 			int j;
 
@@ -698,7 +742,7 @@ char **rc_services_in_state (rc_service_state_t state)
 		if (dirs)
 			free (dirs);
 	} else {
-		list = rc_ls_dir (dir, RC_LS_INITD);
+		list = ls_dir (dir, LS_INITD);
 	}
 
 	free (dir);
@@ -758,7 +802,7 @@ librc_hidden_def(rc_service_delete)
 
 char **rc_services_scheduled_by (const char *service)
 {
-	char **dirs = rc_ls_dir (RC_SVCDIR "/scheduled", 0);
+	char **dirs = ls_dir (RC_SVCDIR "/scheduled", 0);
 	char **list = NULL;
 	char *dir;
 	int i;
@@ -784,7 +828,7 @@ char **rc_services_scheduled (const char *service)
 	char **list = NULL;
 
 	free (svc);
-	list = rc_ls_dir (dir, RC_LS_INITD);
+	list = ls_dir (dir, LS_INITD);
 	free (dir);
 	return (list);
 }
diff --git a/src/librc.h b/src/librc.h
index 1a65c3bc..3d0ce3ef 100644
--- a/src/librc.h
+++ b/src/librc.h
@@ -65,7 +65,6 @@ librc_hidden_proto(rc_env_config)
 librc_hidden_proto(rc_env_filter)
 librc_hidden_proto(rc_exists)
 librc_hidden_proto(rc_find_pids)
-librc_hidden_proto(rc_ls_dir)
 librc_hidden_proto(rc_rm_dir)
 librc_hidden_proto(rc_runlevel_exists)
 librc_hidden_proto(rc_runlevel_get)
diff --git a/src/rc-depend.c b/src/rc-depend.c
index 80ee9ceb..ad95d6a4 100644
--- a/src/rc-depend.c
+++ b/src/rc-depend.c
@@ -29,7 +29,7 @@ rc_depinfo_t *_rc_deptree_load (void) {
 
 		ebegin ("Caching service dependencies");
 		retval = rc_deptree_update ();
-		eend (retval, "Failed to update the dependency tree");
+		eend (retval ? 0 : -1, "Failed to update the dependency tree");
 	}
 
 	return (rc_deptree_load ());
diff --git a/src/rc-plugin.c b/src/rc-plugin.c
index 76b8e08e..b367228f 100644
--- a/src/rc-plugin.c
+++ b/src/rc-plugin.c
@@ -5,6 +5,7 @@
    Released under the GPLv2
    */
 
+#include <dirent.h>
 #include <dlfcn.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -49,10 +50,12 @@ dlfunc_t dlfunc (void * __restrict handle, const char * __restrict symbol)
 
 void rc_plugin_load (void)
 {
-	char **files;
-	char *file;
-	int i;
+	DIR *dp;
+	struct dirent *d;
 	plugin_t *plugin = plugins;
+	char *p;
+	void *h;
+	int (*fptr) (rc_hook_t, const char *);
 
 	/* Don't load plugins if we're in one */
 	if (rc_in_plugin)
@@ -61,15 +64,15 @@ void rc_plugin_load (void)
 	/* Ensure some sanity here */
 	rc_plugin_unload ();
 
-	if (! rc_exists (RC_PLUGINDIR))
+	if (! (dp = opendir (RC_PLUGINDIR)))
 		return;
 
-	files = rc_ls_dir (RC_PLUGINDIR, 0);
-	STRLIST_FOREACH (files, file, i) {
-		char *p = rc_strcatpaths (RC_PLUGINDIR, file, NULL);
-		void *h = dlopen (p, RTLD_LAZY);
-		int (*fptr) (rc_hook_t, const char *); 
+	while ((d = readdir (dp))) {
+		if (d->d_name[0] == '.')
+			continue;
 
+		p = rc_strcatpaths (RC_PLUGINDIR, d->d_name, NULL);
+		h = dlopen (p, RTLD_LAZY);
 		free (p);
 		if (! h) {
 			eerror ("dlopen: %s", dlerror ());
@@ -78,7 +81,7 @@ void rc_plugin_load (void)
 
 		fptr = (int (*)(rc_hook_t, const char*)) dlfunc (h, RC_PLUGIN_HOOK);
 		if (! fptr) {
-			eerror ("%s: cannot find symbol `%s'", file, RC_PLUGIN_HOOK);
+			eerror ("%s: cannot find symbol `%s'", d->d_name, RC_PLUGIN_HOOK);
 			dlclose (h);
 		} else {
 			if (plugin) {
@@ -88,13 +91,12 @@ void rc_plugin_load (void)
 				plugin = plugins = rc_xmalloc (sizeof (plugin_t));
 
 			memset (plugin, 0, sizeof (plugin_t));
-			plugin->name = rc_xstrdup (file);
+			plugin->name = rc_xstrdup (d->d_name);
 			plugin->handle = h;
 			plugin->hook = fptr;
 		}
 	}
-
-	rc_strlist_free (files);
+	closedir (dp);
 }
 
 void rc_plugin_run (rc_hook_t hook, const char *value)
diff --git a/src/rc.c b/src/rc.c
index ae814877..7117a1ee 100644
--- a/src/rc.c
+++ b/src/rc.c
@@ -20,6 +20,7 @@
 #include <sys/utsname.h>
 #include <sys/wait.h>
 #include <errno.h>
+#include <dirent.h>
 #include <ctype.h>
 #include <getopt.h>
 #include <libgen.h>
@@ -331,7 +332,7 @@ static int do_mark_service (int argc, char **argv)
 				eerror ("%s: failed to signal parent %d: %s",
 						applet, pid, strerror (errno));
 
-		/* Remove the exclsive time test. This ensures that it's not
+		/* Remove the exclusive time test. This ensures that it's not
 		   in control as well */
 		l = strlen (RC_SVCDIR "exclusive") +
 			strlen (svcname) +
@@ -420,7 +421,7 @@ static char read_key (bool block)
 	struct termios termios;
 	char c = 0;
 	int fd = fileno (stdin);
-	
+
 	if (! isatty (fd))
 		return (false);
 
@@ -736,6 +737,8 @@ int main (int argc, char **argv)
 	char ksoftbuffer [PATH_MAX];
 	char pidstr[6];
 	int opt;
+	DIR *dp;
+	struct dirent *d;
 
 	atexit (cleanup);
 	if (argv[0])
@@ -1032,18 +1035,14 @@ int main (int argc, char **argv)
 	   its coldplugging thing. runscript knows when we're not ready so it
 	   stores a list of coldplugged services in DEVBOOT for us to pick up
 	   here when we are ready for them */
-	start_services = rc_ls_dir (DEVBOOT, RC_LS_INITD);
-	if (start_services) {
+	if ((dp = opendir (DEVBOOT))) {
+		while ((d = readdir (dp))) {
+			if (rc_service_exists (d->d_name) &&
+				rc_service_plugable (d->d_name))
+				rc_service_mark (d->d_name, RC_SERVICE_COLDPLUGGED);
+		}
+		closedir (dp);
 		rc_rm_dir (DEVBOOT, true);
-
-		STRLIST_FOREACH (start_services, service, i)
-			if (rc_service_plugable (service))
-				rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
-		/* We need to dump this list now.
-		   This may seem redunant, but only Linux needs this and saves on
-		   code bloat. */
-		rc_strlist_free (start_services);
-		start_services = NULL;
 	}
 #else
 	/* BSD's on the other hand populate /dev automagically and use devd.
@@ -1057,50 +1056,52 @@ int main (int argc, char **argv)
 	{
 #if defined(__DragonFly__) || defined(__FreeBSD__)
 		/* The net interfaces are easy - they're all in net /dev/net :) */
-		start_services = rc_ls_dir ("/dev/net", 0);
-		STRLIST_FOREACH (start_services, service, i) {
-			j = (strlen ("net.") + strlen (service) + 1);
-			tmp = rc_xmalloc (sizeof (char *) * j);
-			snprintf (tmp, j, "net.%s", service);
-			if (rc_service_exists (tmp) && rc_service_plugable (tmp))
-				rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
-			CHAR_FREE (tmp);
+		if ((dp = opendir ("/dev/net"))) {
+			while ((d = readdir (dp))) {
+				i = (strlen ("net.") + strlen (d->d_name) + 1);
+				tmp = rc_xmalloc (sizeof (char *) * i);
+				snprintf (tmp, i, "net.%s", d->d_name);
+				if (rc_service_exists (d->d_name) &&
+					rc_service_plugable (d->d_name))
+					rc_service_mark (d->d_name, RC_SERVICE_COLDPLUGGED);
+				CHAR_FREE (tmp);
+			}
+			closedir (dp);
 		}
-		rc_strlist_free (start_services);
 #endif
 
 		/* The mice are a little more tricky.
 		   If we coldplug anything else, we'll probably do it here. */
-		start_services = rc_ls_dir ("/dev", 0);
-		STRLIST_FOREACH (start_services, service, i) {
-			if (strncmp (service, "psm", 3) == 0 ||
-				strncmp (service, "ums", 3) == 0)
-			{
-				char *p = service + 3;
-				if (p && isdigit (*p)) {
-					j = (strlen ("moused.") + strlen (service) + 1);
-					tmp = rc_xmalloc (sizeof (char *) * j);
-					snprintf (tmp, j, "moused.%s", service);
-					if (rc_service_exists (tmp) && rc_service_plugable (tmp))
-						rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
-					CHAR_FREE (tmp);
+		if ((dp == opendir ("/dev"))) {
+			while ((d = readdir (dp))) {
+				if (strncmp (d->d_name, "psm", 3) == 0 ||
+					strncmp (d->d_name, "ums", 3) == 0)
+				{
+					char *p = d->d_name + 3;
+					if (p && isdigit (*p)) {
+						i = (strlen ("moused.") + strlen (d->d_name) + 1);
+						tmp = rc_xmalloc (sizeof (char *) * i);
+						snprintf (tmp, i, "moused.%s", d->d_name);
+						if (rc_service_exists (tmp) && rc_service_plugable (tmp))
+							rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
+						CHAR_FREE (tmp);
+					}
 				}
 			}
+			closedir (dp);
 		}
-		rc_strlist_free (start_services);
-		start_services = NULL;
 	}
 #endif
 
 	/* Build a list of all services to stop and then work out the
 	   correct order for stopping them */
-	stop_services = rc_ls_dir (RC_SVCDIR_STARTING, RC_LS_INITD);
-	
-	tmplist = rc_ls_dir (RC_SVCDIR_INACTIVE, RC_LS_INITD);
+	stop_services = rc_services_in_state (RC_SERVICE_STARTING);
+
+	tmplist = rc_services_in_state (RC_SERVICE_INACTIVE);
 	rc_strlist_join (&stop_services, tmplist);
 	rc_strlist_free (tmplist);
 
-	tmplist = rc_ls_dir (RC_SVCDIR_STARTED, RC_LS_INITD);
+	tmplist = rc_services_in_state (RC_SERVICE_STARTED);
 	rc_strlist_join (&stop_services, tmplist);
 	rc_strlist_free (tmplist);
 
@@ -1110,7 +1111,7 @@ int main (int argc, char **argv)
 	rc_strlist_add (&types, "iafter");
 
 	deporder = rc_deptree_depends (deptree, types, stop_services,
-							   runlevel, depoptions | RC_DEP_STOP);
+								   runlevel, depoptions | RC_DEP_STOP);
 
 	rc_strlist_free (stop_services);
 	rc_strlist_free (types);
@@ -1120,7 +1121,7 @@ int main (int argc, char **argv)
 	rc_strlist_reverse (stop_services);
 
 	/* Load our list of coldplugged services */
-	coldplugged_services = rc_ls_dir (RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
+	coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
 
 	/* Load our start services now.
 	   We have different rules dependent on runlevel. */
@@ -1133,15 +1134,12 @@ int main (int argc, char **argv)
 			}
 			printf ("\n");
 		}
-		tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel,
-							  (char *) NULL);
-		tmplist = rc_ls_dir (tmp, RC_LS_INITD);
+		tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
 		rc_strlist_join (&start_services, tmplist);
 		rc_strlist_free (tmplist);
-		CHAR_FREE (tmp);
 	} else {
 		/* Store our list of coldplugged services */
-		tmplist = rc_ls_dir (RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
+		tmplist = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
 		rc_strlist_join (&coldplugged_services, tmplist);
 		rc_strlist_free (tmplist);
 		if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
@@ -1155,7 +1153,7 @@ int main (int argc, char **argv)
 			tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
 			rc_strlist_join (&start_services, tmplist);
 			rc_strlist_free (tmplist);
-			
+
 			STRLIST_FOREACH (coldplugged_services, service, i)
 				rc_strlist_add (&start_services, service);
 
@@ -1229,7 +1227,7 @@ int main (int argc, char **argv)
 		   going to be started depends on us */
 		rc_strlist_add (&stopdeps, service);
 		deporder = rc_deptree_depends (deptree, types, stopdeps,
-								   runlevel, RC_DEP_STRICT);
+									   runlevel, RC_DEP_STRICT);
 		rc_strlist_free (stopdeps);
 		stopdeps = NULL;
 		found = false;
@@ -1299,7 +1297,7 @@ int main (int argc, char **argv)
 	rc_strlist_add (&types, "iuse");
 	rc_strlist_add (&types, "iafter");
 	deporder = rc_deptree_depends (deptree, types, start_services,
-							   runlevel, depoptions | RC_DEP_START);
+								   runlevel, depoptions | RC_DEP_START);
 	rc_strlist_free (types);
 	types = NULL;
 	rc_strlist_free (start_services);
diff --git a/src/rc.h b/src/rc.h
index 65421dec..82b24ce2 100644
--- a/src/rc.h
+++ b/src/rc.h
@@ -438,17 +438,6 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...) SENTINEL;
  * @return true if it matches true, yes or 1, false if otherwise. */
 bool rc_env_bool (const char *variable);
 
-/*! @name rc_ls_dir options */
-/*! Ensure that an init.d service exists for each file returned */
-#define RC_LS_INITD	0x01
-#define RC_LS_DIR   0x02
-
-/*! Return a NULL terminted sorted list of the contents of the directory
- * @param dir to list
- * @param options any options to apply
- * @return NULL terminated list */
-char **rc_ls_dir (const char *dir, int options);
-
 /*! Remove a directory
  * @param pathname to remove
  * @param top remove the top level directory too
diff --git a/src/rc.map b/src/rc.map
index fa738c37..71b7ce09 100644
--- a/src/rc.map
+++ b/src/rc.map
@@ -14,7 +14,6 @@ global:
 	rc_env_filter;
 	rc_environ_fd;
 	rc_find_pids;
-	rc_ls_dir;
 	rc_rm_dir;
 	rc_runlevel_exists;
 	rc_runlevel_get;
-- 
cgit v1.2.3