summaryrefslogtreecommitdiff
path: root/src/librc
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2008-03-16 17:00:56 +0000
committerRoy Marples <roy@marples.name>2008-03-16 17:00:56 +0000
commitcb9da6a262b60255cd037f20b4cde3ab2c8a1e6a (patch)
treec5c57d5adedf009fdb02b53677e2cdf940bdb47c /src/librc
parent40e12f6ba026af9c24d5c3d8e36512719ed5faee (diff)
downloadopenrc-cb9da6a262b60255cd037f20b4cde3ab2c8a1e6a.tar.gz
openrc-cb9da6a262b60255cd037f20b4cde3ab2c8a1e6a.tar.bz2
openrc-cb9da6a262b60255cd037f20b4cde3ab2c8a1e6a.tar.xz
Remove null terminated char ** lists in favour of RC_STRINGLIST, using TAILQ from queue(3). Refactor code style around the BSD KNF.
Diffstat (limited to 'src/librc')
-rw-r--r--src/librc/.gitignore4
-rw-r--r--src/librc/Makefile2
-rw-r--r--src/librc/librc-daemon.c438
-rw-r--r--src/librc/librc-depend.c1012
-rw-r--r--src/librc/librc-depend.h61
-rw-r--r--src/librc/librc-misc.c123
-rw-r--r--src/librc/librc-strlist.c230
-rw-r--r--src/librc/librc.c843
-rw-r--r--src/librc/librc.h16
-rw-r--r--src/librc/rc.h200
-rw-r--r--src/librc/rc.map15
11 files changed, 1277 insertions, 1667 deletions
diff --git a/src/librc/.gitignore b/src/librc/.gitignore
index 5f6e3ee..eab6c70 100644
--- a/src/librc/.gitignore
+++ b/src/librc/.gitignore
@@ -3,12 +3,12 @@ librc.o
librc-daemon.o
librc-depend.o
librc-misc.o
-librc-strlist.o
+librc-stringlist.o
librc.So
librc-daemon.So
librc-depend.So
librc-misc.So
-librc-strlist.So
+librc-stringlist.So
librc.a
librc.so.1
librc.so
diff --git a/src/librc/Makefile b/src/librc/Makefile
index 78c97ce..15c396b 100644
--- a/src/librc/Makefile
+++ b/src/librc/Makefile
@@ -4,7 +4,7 @@ include ${MK}/os.mk
LIB= rc
SHLIB_MAJOR= 1
SRCS= librc.c librc-daemon.c librc-depend.c librc-misc.c \
- librc-strlist.c
+ librc-stringlist.c
INCS= rc.h
VERSION_MAP= rc.map
diff --git a/src/librc/librc-daemon.c b/src/librc/librc-daemon.c
index ca23ed2..9ae4ac2 100644
--- a/src/librc/librc-daemon.c
+++ b/src/librc/librc-daemon.c
@@ -32,33 +32,33 @@
#include "librc.h"
#if defined(__linux__)
-static bool pid_is_cmd (pid_t pid, const char *cmd)
+static bool pid_is_cmd(pid_t pid, const char *cmd)
{
char buffer[32];
FILE *fp;
int c;
- snprintf(buffer, sizeof (buffer), "/proc/%d/stat", pid);
- if ((fp = fopen (buffer, "r")) == NULL)
- return (false);
+ snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
+ if ((fp = fopen(buffer, "r")) == NULL)
+ return false;
- while ((c = getc (fp)) != EOF && c != '(')
+ while ((c = getc(fp)) != EOF && c != '(')
;
if (c != '(') {
fclose(fp);
- return (false);
+ return false;
}
- while ((c = getc (fp)) != EOF && c == *cmd)
+ while ((c = getc(fp)) != EOF && c == *cmd)
cmd++;
- fclose (fp);
+ fclose(fp);
- return ((c == ')' && *cmd == '\0') ? true : false);
+ return (c == ')' && *cmd == '\0') ? true : false;
}
-static bool pid_is_exec (pid_t pid, const char *const *argv)
+static bool pid_is_exec(pid_t pid, const char *const *argv)
{
char cmdline[32];
char buffer[PATH_MAX];
@@ -66,31 +66,30 @@ static bool pid_is_exec (pid_t pid, const char *const *argv)
int fd = -1;
int r;
+ /* Check it's the right binary */
snprintf (cmdline, sizeof (cmdline), "/proc/%u/exe", pid);
memset (buffer, 0, sizeof (buffer));
-#if 0
- if (readlink (cmdline, buffer, sizeof (buffer)) != -1) {
- if (strcmp (exec, buffer) == 0)
- return (true);
+ if (readlink(cmdline, buffer, sizeof(buffer)) != -1) {
+ if (strcmp(*argv, buffer) == 0)
+ return true;
/* We should cater for deleted binaries too */
- if (strlen (buffer) > 10) {
- p = buffer + (strlen (buffer) - 10);
- if (strcmp (p, " (deleted)") == 0) {
+ if (strlen(buffer) > 10) {
+ p = buffer + (strlen(buffer) - 10);
+ if (strcmp(p, " (deleted)") == 0) {
*p = 0;
- if (strcmp (buffer, exec) == 0)
- return (true);
+ if (strcmp(buffer, *argv) == 0)
+ return true;
}
}
}
-#endif
- snprintf (cmdline, sizeof (cmdline), "/proc/%u/cmdline", pid);
- if ((fd = open (cmdline, O_RDONLY)) < 0)
- return (false);
+ snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
+ if ((fd = open(cmdline, O_RDONLY)) < 0)
+ return false;
- r = read (fd, buffer, sizeof (buffer));
- close (fd);
+ r = read(fd, buffer, sizeof(buffer));
+ close(fd);
if (r == -1)
return 0;
@@ -98,18 +97,18 @@ static bool pid_is_exec (pid_t pid, const char *const *argv)
buffer[r] = 0;
p = buffer;
while (*argv) {
- if (strcmp (*argv, p) != 0)
- return (false);
+ if (strcmp(*argv, p) != 0)
+ return false;
argv++;
- p += strlen (p) + 1;
+ p += strlen(p) + 1;
if ((unsigned) (p - buffer) > sizeof (buffer))
- return (false);
+ return false;
}
- return (true);
+ return true;
}
-pid_t *rc_find_pids (const char *const *argv, const char *cmd,
- uid_t uid, pid_t pid)
+pid_t *rc_find_pids(const char *const *argv, const char *cmd,
+ uid_t uid, pid_t pid)
{
DIR *procdir;
struct dirent *entry;
@@ -122,8 +121,8 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
pid_t runscript_pid = 0;
char *pp;
- if ((procdir = opendir ("/proc")) == NULL)
- return (NULL);
+ if ((procdir = opendir("/proc")) == NULL)
+ return NULL;
/*
We never match RC_RUNSCRIPT_PID if present so we avoid the below
@@ -136,13 +135,13 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
nasty
*/
- if ((pp = getenv ("RC_RUNSCRIPT_PID"))) {
- if (sscanf (pp, "%d", &runscript_pid) != 1)
+ if ((pp = getenv("RC_RUNSCRIPT_PID"))) {
+ if (sscanf(pp, "%d", &runscript_pid) != 1)
runscript_pid = 0;
}
- while ((entry = readdir (procdir)) != NULL) {
- if (sscanf (entry->d_name, "%d", &p) != 1)
+ while ((entry = readdir(procdir)) != NULL) {
+ if (sscanf(entry->d_name, "%d", &p) != 1)
continue;
if (runscript_pid != 0 && runscript_pid == p)
@@ -152,23 +151,23 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
continue;
if (uid) {
- snprintf (buffer, sizeof (buffer), "/proc/%d", p);
- if (stat (buffer, &sb) != 0 || sb.st_uid != uid)
+ snprintf(buffer, sizeof(buffer), "/proc/%d", p);
+ if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
continue;
}
- if (cmd && ! pid_is_cmd (p, cmd))
+ if (cmd && ! pid_is_cmd(p, cmd))
continue;
- if (argv && ! cmd && ! pid_is_exec (p, (const char *const *)argv))
+ if (argv && ! cmd && ! pid_is_exec(p, (const char *const *)argv))
continue;
- tmp = realloc (pids, sizeof (pid_t) * (npids + 2));
+ tmp = realloc(pids, sizeof (pid_t) * (npids + 2));
if (! tmp) {
- free (pids);
- closedir (procdir);
+ free(pids);
+ closedir(procdir);
errno = ENOMEM;
- return (NULL);
+ return NULL;
}
pids = tmp;
@@ -176,9 +175,9 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
pids[npids + 1] = 0;
npids++;
}
- closedir (procdir);
+ closedir(procdir);
- return (pids);
+ return pids;
}
librc_hidden_def(rc_find_pids)
@@ -206,8 +205,8 @@ librc_hidden_def(rc_find_pids)
# define _KVM_FLAGS O_RDONLY
# endif
-pid_t *rc_find_pids (const char *const *argv, const char *cmd,
- uid_t uid, pid_t pid)
+pid_t *rc_find_pids(const char *const *argv, const char *cmd,
+ uid_t uid, pid_t pid)
{
static kvm_t *kd = NULL;
char errbuf[_POSIX2_LINE_MAX];
@@ -218,44 +217,45 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
char **pargv;
pid_t *pids = NULL;
pid_t *tmp;
+ pid_t p;
const char *const *arg;
int npids = 0;
int match;
- if ((kd = kvm_openfiles (_KVM_PATH, _KVM_PATH,
- NULL, _KVM_FLAGS, errbuf)) == NULL)
+ if ((kd = kvm_openfiles(_KVM_PATH, _KVM_PATH,
+ NULL, _KVM_FLAGS, errbuf)) == NULL)
{
- fprintf (stderr, "kvm_open: %s\n", errbuf);
- return (NULL);
+ fprintf(stderr, "kvm_open: %s\n", errbuf);
+ return NULL;
}
#ifdef _KVM_GETPROC2
- kp = kvm_getproc2 (kd, KERN_PROC_ALL, 0, sizeof(*kp), &processes);
+ kp = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(*kp), &processes);
#else
- kp = kvm_getprocs (kd, KERN_PROC_PROC, 0, &processes);
+ kp = kvm_getprocs(kd, KERN_PROC_PROC, 0, &processes);
#endif
if ((kp == NULL && processes > 0) || (kp != NULL && processes < 0)) {
- fprintf (stderr, "kvm_getprocs: %s\n", kvm_geterr (kd));
- kvm_close (kd);
- return (NULL);
+ fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd));
+ kvm_close(kd);
+ return NULL;
}
for (i = 0; i < processes; i++) {
- pid_t p = _GET_KINFO_PID (kp[i]);
+ p = _GET_KINFO_PID(kp[i]);
if (pid != 0 && pid != p)
continue;
- if (uid != 0 && uid != _GET_KINFO_UID (kp[i]))
+ if (uid != 0 && uid != _GET_KINFO_UID(kp[i]))
continue;
if (cmd) {
- if (! _GET_KINFO_COMM (kp[i]) ||
- strcmp (cmd, _GET_KINFO_COMM (kp[i])) != 0)
+ if (! _GET_KINFO_COMM(kp[i]) ||
+ strcmp(cmd, _GET_KINFO_COMM(kp[i])) != 0)
continue;
}
if (argv && *argv && ! cmd) {
- pargv = _KVM_GETARGV (kd, &kp[i], pargc);
+ pargv = _KVM_GETARGV(kd, &kp[i], pargc);
if (! pargv || ! *pargv)
continue;
@@ -263,7 +263,7 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
match = 1;
while (*arg && *pargv)
- if (strcmp (*arg++, *pargv++) != 0) {
+ if (strcmp(*arg++, *pargv++) != 0) {
match = 0;
break;
}
@@ -272,12 +272,12 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
continue;
}
- tmp = realloc (pids, sizeof (pid_t) * (npids + 2));
+ tmp = realloc(pids, sizeof(pid_t) * (npids + 2));
if (! tmp) {
- free (pids);
- kvm_close (kd);
+ free(pids);
+ kvm_close(kd);
errno = ENOMEM;
- return (NULL);
+ return NULL;
}
pids = tmp;
@@ -285,9 +285,9 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
pids[npids + 1] = 0;
npids++;
}
- kvm_close (kd);
+ kvm_close(kd);
- return (pids);
+ return pids;
}
librc_hidden_def(rc_find_pids)
@@ -295,67 +295,72 @@ librc_hidden_def(rc_find_pids)
# error "Platform not supported!"
#endif
-static bool _match_daemon (const char *path, const char *file, char **match)
+static bool _match_daemon(const char *path, const char *file,
+ RC_STRINGLIST *match)
{
char *line;
- char *ffile = rc_strcatpaths (path, file, (char *) NULL);
+ char *ffile = rc_strcatpaths(path, file, (char *) NULL);
FILE *fp;
+ RC_STRING *m;
- fp = fopen (ffile, "r");
- free (ffile);
+ fp = fopen(ffile, "r");
+ free(ffile);
if (! fp)
- return (false);
+ return false;
- while ((line = rc_getline (fp))) {
- rc_strlist_delete (&match, line);
- if (! match || !*match)
+ while ((line = rc_getline(fp))) {
+ TAILQ_FOREACH(m, match, entries)
+ if (strcmp(line, m->value) == 0) {
+ TAILQ_REMOVE(match, m, entries);
+ break;
+ }
+ if (! TAILQ_FIRST(match))
break;
}
- fclose (fp);
- if (match && *match)
- return (false);
- return (true);
+ fclose(fp);
+ if (TAILQ_FIRST(match))
+ return false;
+ return true;
}
-static char **_match_list (const char* const* argv,
- const char *name, const char *pidfile)
+static RC_STRINGLIST *_match_list(const char* const* argv,
+ const char *name, const char *pidfile)
{
- char **match = NULL;
+ RC_STRINGLIST *match = rc_stringlist_new();
int i = 0;
size_t l;
char *m;
while (argv && argv[i]) {
- l = strlen (*argv) + strlen ("argv_=") + 16;
- m = xmalloc (sizeof (char) * l);
- snprintf (m, l, "argv_0=%s", argv[i++]);
- rc_strlist_add (&match, m);
- free (m);
+ l = strlen(*argv) + strlen("argv_=") + 16;
+ m = xmalloc(sizeof(char) * l);
+ snprintf(m, l, "argv_0=%s", argv[i++]);
+ rc_stringlist_add(match, m);
+ free(m);
}
if (name) {
- l = strlen (name) + 6;
- m = xmalloc (sizeof (char) * l);
- snprintf (m, l, "name=%s", name);
- rc_strlist_add (&match, m);
- free (m);
+ l = strlen(name) + 6;
+ m = xmalloc(sizeof (char) * l);
+ snprintf(m, l, "name=%s", name);
+ rc_stringlist_add(match, m);
+ free(m);
}
if (pidfile) {
- l = strlen (pidfile) + 9;
- m = xmalloc (sizeof (char) * l);
- snprintf (m, l, "pidfile=%s", pidfile);
- rc_strlist_add (&match, m);
+ l = strlen(pidfile) + 9;
+ m = xmalloc(sizeof (char) * l);
+ snprintf(m, l, "pidfile=%s", pidfile);
+ rc_stringlist_add(match, m);
free (m);
}
- return (match);
+ return match;
}
-bool rc_service_daemon_set (const char *service, const char *const *argv,
- const char *name, const char *pidfile,
- bool started)
+bool rc_service_daemon_set(const char *service, const char *const *argv,
+ const char *name, const char *pidfile, bool started)
{
char *dirpath;
char *file = NULL;
@@ -364,123 +369,123 @@ bool rc_service_daemon_set (const char *service, const char *const *argv,
bool retval = false;
DIR *dp;
struct dirent *d;
- char **match = NULL;
+ RC_STRINGLIST *match;
int i = 0;
+ char buffer[10];
+ FILE *fp;
- if (! (argv && *argv) && ! name && ! pidfile) {
+ if (!(argv && *argv) && ! name && ! pidfile) {
errno = EINVAL;
- return (false);
+ return false;
}
- dirpath = rc_strcatpaths (RC_SVCDIR, "daemons",
- basename_c (service), (char *) NULL);
+ dirpath = rc_strcatpaths(RC_SVCDIR, "daemons",
+ basename_c(service), (char *) NULL);
- match = _match_list (argv, name, pidfile);
+ match = _match_list(argv, name, pidfile);
/* Regardless, erase any existing daemon info */
- if ((dp = opendir (dirpath))) {
- while ((d = readdir (dp))) {
+ if ((dp = opendir(dirpath))) {
+ while ((d = readdir(dp))) {
if (d->d_name[0] == '.')
continue;
- file = rc_strcatpaths (dirpath, d->d_name, (char *) NULL);
+ file = rc_strcatpaths(dirpath, d->d_name, (char *) NULL);
nfiles++;
if (! oldfile) {
- if (_match_daemon (dirpath, d->d_name, match)) {
+ if (_match_daemon(dirpath, d->d_name, match)) {
unlink (file);
oldfile = file;
nfiles--;
}
} else {
- rename (file, oldfile);
- free (oldfile);
+ rename(file, oldfile);
+ free(oldfile);
oldfile = file;
}
}
- free (file);
- closedir (dp);
+ free(file);
+ closedir(dp);
}
/* Now store our daemon info */
if (started) {
- char buffer[10];
- FILE *fp;
-
- if (mkdir (dirpath, 0755) == 0 || errno == EEXIST) {
- snprintf (buffer, sizeof (buffer), "%03d", nfiles + 1);
- file = rc_strcatpaths (dirpath, buffer, (char *) NULL);
- if ((fp = fopen (file, "w"))) {
+ if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
+ snprintf(buffer, sizeof(buffer), "%03d", nfiles + 1);
+ file = rc_strcatpaths(dirpath, buffer, (char *) NULL);
+ if ((fp = fopen(file, "w"))) {
while (argv && argv[i]) {
- fprintf (fp, "argv_%d=%s\n", i, argv[i]);
+ fprintf(fp, "argv_%d=%s\n", i, argv[i]);
i++;
}
- fprintf (fp, "name=");
+ fprintf(fp, "name=");
if (name)
- fprintf (fp, "%s", name);
- fprintf (fp, "\npidfile=");
+ fprintf(fp, "%s", name);
+ fprintf(fp, "\npidfile=");
if (pidfile)
- fprintf (fp, "%s", pidfile);
- fprintf (fp, "\n");
- fclose (fp);
+ fprintf(fp, "%s", pidfile);
+ fprintf(fp, "\n");
+ fclose(fp);
retval = true;
}
- free (file);
+ free(file);
}
} else
retval = true;
- rc_strlist_free (match);
- free (dirpath);
+ rc_stringlist_free(match);
+ free(dirpath);
- return (retval);
+ return retval;
}
librc_hidden_def(rc_service_daemon_set)
-bool rc_service_started_daemon (const char *service, const char *const *argv,
- int indx)
+bool
+rc_service_started_daemon (const char *service, const char *const *argv,
+ int indx)
{
char *dirpath;
char *file;
size_t l;
- char **match;
+ RC_STRINGLIST *match;
bool retval = false;
DIR *dp;
struct dirent *d;
- if (! service || ! (argv && *argv))
- return (false);
+ if (!service || !(argv && *argv))
+ return false;
- dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename_c (service),
- (char *) NULL);
+ dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", basename_c(service),
+ (char *) NULL);
- match = _match_list (argv, NULL, NULL);
+ match = _match_list(argv, NULL, NULL);
if (indx > 0) {
l = sizeof (char) * 10;
- file = xmalloc (l);
- snprintf (file, l, "%03d", indx);
- retval = _match_daemon (dirpath, file, match);
- free (file);
+ file = xmalloc(l);
+ snprintf(file, l, "%03d", indx);
+ retval = _match_daemon(dirpath, file, match);
+ free(file);
} else {
- if ((dp = opendir (dirpath))) {
- while ((d = readdir (dp))) {
+ if ((dp = opendir(dirpath))) {
+ while ((d = readdir(dp))) {
if (d->d_name[0] == '.')
continue;
- retval = _match_daemon (dirpath, d->d_name, match);
+ retval = _match_daemon(dirpath, d->d_name, match);
if (retval)
break;
}
- closedir (dp);
+ closedir(dp);
}
}
- free (dirpath);
- rc_strlist_free (match);
- return (retval);
+ free(dirpath);
+ rc_stringlist_free(match);
+ return retval;
}
librc_hidden_def(rc_service_started_daemon)
-bool rc_service_daemons_crashed (const char *service)
+bool rc_service_daemons_crashed(const char *service)
{
char *dirpath;
DIR *dp;
@@ -497,116 +502,123 @@ bool rc_service_daemons_crashed (const char *service)
char *p;
char *token;
bool retval = false;
+ RC_STRINGLIST *list;
+ RC_STRING *s;
+ size_t i;
- if (! service)
- return (false);
+ dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", basename_c(service),
+ (char *) NULL);
- dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename_c (service),
- (char *) NULL);
-
- if (! (dp = opendir (dirpath))) {
- free (dirpath);
- return (false);
+ if (! (dp = opendir(dirpath))) {
+ free(dirpath);
+ return false;
}
- while ((d = readdir (dp))) {
+ 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);
+ path = rc_strcatpaths(dirpath, d->d_name, (char *) NULL);
+ fp = fopen(path, "r");
+ free(path);
if (! fp)
break;
- while ((line = rc_getline (fp))) {
+ list = rc_stringlist_new();
+
+ while ((line = rc_getline(fp))) {
p = line;
- if ((token = strsep (&p, "=")) == NULL || ! p) {
- free (line);
+ if ((token = strsep(&p, "=")) == NULL || ! p) {
+ free(line);
continue;
}
- if (strlen (p) == 0) {
- free (line);
+ if (! *p) {
+ free(line);
continue;
}
- if (strncmp (token, "argv_", 5) == 0) {
- rc_strlist_add (&argv, p);
- } else if (strcmp (token, "exec") == 0) {
+ if (strncmp(token, "argv_", 5) == 0) {
+ rc_stringlist_add(list, p);
+ } else if (strcmp(token, "exec") == 0) {
if (exec)
- free (exec);
- exec = xstrdup (p);
- } else if (strcmp (token, "name") == 0) {
+ free(exec);
+ exec = xstrdup(p);
+ } else if (strcmp(token, "name") == 0) {
if (name)
- free (name);
- name = xstrdup (p);
- } else if (strcmp (token, "pidfile") == 0) {
+ free(name);
+ name = xstrdup(p);
+ } else if (strcmp(token, "pidfile") == 0) {
if (pidfile)
- free (pidfile);
- pidfile = xstrdup (p);
+ free(pidfile);
+ pidfile = xstrdup(p);
}
- free (line);
+ free(line);
}
- fclose (fp);
+ fclose(fp);
pid = 0;
if (pidfile) {
- if (! exists (pidfile)) {
+ if (! exists(pidfile)) {
retval = true;
break;
}
- if ((fp = fopen (pidfile, "r")) == NULL) {
+ if ((fp = fopen(pidfile, "r")) == NULL) {
retval = true;
break;
}
- if (fscanf (fp, "%d", &pid) != 1) {
+ if (fscanf(fp, "%d", &pid) != 1) {
fclose (fp);
retval = true;
break;
}
- fclose (fp);
- free (pidfile);
+ fclose(fp);
+ free(pidfile);
pidfile = NULL;
/* We have the pid, so no need to match on name */
- rc_strlist_free (argv);
- argv = NULL;
+ rc_stringlist_free(list);
+ list = NULL;
free (exec);
exec = NULL;
free (name);
name = NULL;
- }
-
- if (exec && ! argv) {
- rc_strlist_add (&argv, exec);
- free (exec);
+ } else {
+ if (exec && ! TAILQ_FIRST(list)) {
+ rc_stringlist_add(list, exec);
+ }
+ free(exec);
exec = NULL;
- }
- if ((pids = rc_find_pids ((const char *const *)argv, name, 0, pid)) == NULL) {
- retval = true;
- break;
+ /* We need to flatten our linked list into an array */
+ i = 0;
+ TAILQ_FOREACH(s, list, entries)
+ i++;
+ argv = xmalloc(sizeof(char *) * (i + 1));
+ i = 0;
+ TAILQ_FOREACH(s, list, entries)
+ argv[i++] = s->value;
+ argv[i] = '\0';
}
- free (pids);
- rc_strlist_free (argv);
+ if ((pids = rc_find_pids((const char *const *)argv, name, 0, pid)) == NULL)
+ retval = true;
+ free(pids);
+ free(argv);
argv = NULL;
- free (exec);
- exec = NULL;
- free (name);
+ rc_stringlist_free(list);
+ free(name);
name = NULL;
+ if (retval)
+ break;
}
- rc_strlist_free (argv);
- free (exec);
- free (name);
- free (dirpath);
- closedir (dp);
+ free(dirpath);
+ closedir(dp);
- return (retval);
+ return retval;
}
librc_hidden_def(rc_service_daemons_crashed)
diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c
index 2247036..8617d75 100644
--- a/src/librc/librc-depend.c
+++ b/src/librc/librc-depend.c
@@ -37,31 +37,18 @@
static const char *bootlevel = NULL;
-/* We use this so we can pass our char array through many functions */
-struct lhead
-{
- char **list;
-};
-
-static void *xzalloc (size_t size)
-{
- void *value = xmalloc (size);
- memset (value, 0, size);
- return (value);
-}
-
-static char *get_shell_value (char *string)
+static char *get_shell_value(char *string)
{
char *p = string;
char *e;
if (! string)
- return (NULL);
+ return NULL;
if (*p == '\'')
p++;
- e = p + strlen (p) - 1;
+ e = p + strlen(p) - 1;
if (*e == '\n')
*e-- = 0;
if (*e == '\'')
@@ -70,191 +57,184 @@ static char *get_shell_value (char *string)
if (*p != 0)
return p;
- return (NULL);
+ return NULL;
}
-void rc_deptree_free (rc_depinfo_t *deptree)
+void rc_deptree_free(RC_DEPTREE *deptree)
{
- rc_depinfo_t *di = deptree;
+ RC_DEPINFO *di;
+ RC_DEPINFO *di2;
+ RC_DEPTYPE *dt;
+ RC_DEPTYPE *dt2;
+
+ if (! deptree)
+ return;
+
+ di = STAILQ_FIRST(deptree);
while (di)
{
- rc_depinfo_t *dip = di->next;
- rc_deptype_t *dt = di->depends;
- free (di->service);
+ di2 = STAILQ_NEXT(di, entries);
+ dt = STAILQ_FIRST(&di->depends);
while (dt)
{
- rc_deptype_t *dtp = dt->next;
- free (dt->type);
- rc_strlist_free (dt->services);
- free (dt);
- dt = dtp;
+ dt2 = STAILQ_NEXT(dt, entries);
+ rc_stringlist_free(dt->services);
+ free(dt->type);
+ free(dt);
+ dt = dt2;
}
- free (di);
- di = dip;
+ free(di->service);
+ free(di);
+ di = di2;
}
+ free(deptree);
}
librc_hidden_def(rc_deptree_free)
-static rc_depinfo_t *get_depinfo (const rc_depinfo_t *deptree,
- const char *service)
+static RC_DEPINFO *get_depinfo(const RC_DEPTREE *deptree,
+ const char *service)
{
- const rc_depinfo_t *di;
-
- if (! deptree || ! service)
- return (NULL);
+ RC_DEPINFO *di;
- for (di = deptree; di; di = di->next)
- if (strcmp (di->service, service) == 0)
- return ((rc_depinfo_t *)di);
+ STAILQ_FOREACH(di, deptree, entries)
+ if (strcmp(di->service, service) == 0)
+ return di;
- return (NULL);
+ return NULL;
}
-static rc_deptype_t *get_deptype (const rc_depinfo_t *depinfo,
- const char *type)
+static RC_DEPTYPE *get_deptype(const RC_DEPINFO *depinfo,
+ const char *type)
{
- rc_deptype_t *dt;
+ RC_DEPTYPE *dt;
- if (! depinfo || !type)
- return (NULL);
+ STAILQ_FOREACH(dt, &depinfo->depends, entries)
+ if (strcmp(dt->type, type) == 0)
+ return dt;
- for (dt = depinfo->depends; dt; dt = dt->next)
- if (strcmp (dt->type, type) == 0)
- return (dt);
-
- return (NULL);
+ return NULL;
}
-rc_depinfo_t *rc_deptree_load (void)
+RC_DEPTREE *rc_deptree_load(void)
{
FILE *fp;
- rc_depinfo_t *deptree = NULL;
- rc_depinfo_t *depinfo = NULL;
- rc_deptype_t *deptype = NULL;
+ RC_DEPTREE *deptree;
+ RC_DEPINFO *depinfo = NULL;
+ RC_DEPTYPE *deptype = NULL;
char *line;
char *type;
char *p;
char *e;
int i;
- if (! (fp = fopen (RC_DEPTREE, "r")))
- return (NULL);
+ if (!(fp = fopen(RC_DEPTREE_CACHE, "r")))
+ return NULL;
+
+ deptree = xmalloc(sizeof(*deptree));
+ STAILQ_INIT(deptree);
- while ((line = rc_getline (fp)))
+ while ((line = rc_getline(fp)))
{
p = line;
- e = strsep (&p, "_");
- if (! e || strcmp (e, "depinfo") != 0)
+ e = strsep(&p, "_");
+ if (! e || strcmp(e, "depinfo") != 0)
goto next;
e = strsep (&p, "_");
- if (! e || sscanf (e, "%d", &i) != 1)
+ if (! e || sscanf(e, "%d", &i) != 1)
goto next;
- if (! (type = strsep (&p, "_=")))
+ if (! (type = strsep(&p, "_=")))
goto next;
- if (strcmp (type, "service") == 0)
+ if (strcmp(type, "service") == 0)
{
/* Sanity */
- e = get_shell_value (p);
+ e = get_shell_value(p);
if (! e || *e == '\0')
goto next;
- if (! deptree)
- {
- deptree = xzalloc (sizeof (*deptree));
- depinfo = deptree;
- }
- else
- {
- depinfo->next = xzalloc (sizeof (*depinfo->next));
- depinfo = depinfo->next;
- }
- depinfo->service = xstrdup (e);
+ depinfo = xmalloc(sizeof(*depinfo));
+ STAILQ_INIT(&depinfo->depends);
+ depinfo->service = xstrdup(e);
+ STAILQ_INSERT_TAIL(deptree, depinfo, entries);
deptype = NULL;
goto next;
}
- e = strsep (&p, "=");
- if (! e || sscanf (e, "%d", &i) != 1)
+ e = strsep(&p, "=");
+ if (! e || sscanf(e, "%d", &i) != 1)
goto next;
/* Sanity */
- e = get_shell_value (p);
+ e = get_shell_value(p);
if (! e || *e == '\0')
goto next;
- if (! deptype)
- {
- depinfo->depends = xzalloc (sizeof (*depinfo->depends));
- deptype = depinfo->depends;
- }
- else
- if (strcmp (deptype->type, type) != 0)
- {
- deptype->next = xzalloc (sizeof (*deptype->next));
- deptype = deptype->next;
- }
-
- if (! deptype->type)
+ if (! deptype || strcmp(deptype->type, type) != 0) {
+ deptype = xmalloc(sizeof(*deptype));
+ deptype->services = rc_stringlist_new();
deptype->type = xstrdup (type);
+ STAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
+ }
- rc_strlist_addsort (&deptype->services, e);
-
+ rc_stringlist_add(deptype->services, e);
next:
- free (line);
+ free(line);
}
- fclose (fp);
-
- return (deptree);
+ fclose(fp);
+
+ return deptree;
}
librc_hidden_def(rc_deptree_load)
-static bool valid_service (const char *runlevel, const char *service)
+static bool valid_service(const char *runlevel, const char *service)
{
- rc_service_state_t state = rc_service_state (service);
+ RC_SERVICE state = rc_service_state(service);
return ((strcmp (runlevel, bootlevel) != 0 &&
- rc_service_in_runlevel (service, bootlevel)) ||
- rc_service_in_runlevel (service, runlevel) ||
+ rc_service_in_runlevel(service, bootlevel)) ||
+ rc_service_in_runlevel(service, runlevel) ||
state & RC_SERVICE_COLDPLUGGED ||
state & RC_SERVICE_STARTED);
}
-static bool get_provided1 (const char *runlevel, struct lhead *providers,
- rc_deptype_t *deptype,
- const char *level, bool coldplugged,
- rc_service_state_t state)
+static bool get_provided1(const char *runlevel, RC_STRINGLIST *providers,
+ RC_DEPTYPE *deptype,
+ const char *level, bool coldplugged,
+ RC_SERVICE state)
{
- char *service;
- int i;
+ RC_STRING *service;
+ RC_SERVICE st;
bool retval = false;
+ bool ok;
+ const char *svc;
+
+ TAILQ_FOREACH(service, deptype->services, entries) {
+ ok = true;
+ svc = service->value;
+ st = rc_service_state(svc);
- STRLIST_FOREACH (deptype->services, service, i)
- {
- bool ok = true;
- rc_service_state_t s = rc_service_state (service);
if (level)
- ok = rc_service_in_runlevel (service, level);
+ ok = rc_service_in_runlevel(svc, level);
else if (coldplugged)
- ok = (s & RC_SERVICE_COLDPLUGGED &&
- ! rc_service_in_runlevel (service, runlevel) &&
- ! rc_service_in_runlevel (service, bootlevel));
+ ok = (st & RC_SERVICE_COLDPLUGGED &&
+ ! rc_service_in_runlevel(svc, runlevel) &&
+ ! rc_service_in_runlevel(svc, bootlevel));
if (! ok)
continue;
switch (state) {
case RC_SERVICE_STARTED:
- ok = (s & RC_SERVICE_STARTED);
+ ok = (st & RC_SERVICE_STARTED);
break;
case RC_SERVICE_INACTIVE:
case RC_SERVICE_STARTING:
case RC_SERVICE_STOPPING:
- ok = (s & RC_SERVICE_STARTING ||
- s & RC_SERVICE_STOPPING ||
- s & RC_SERVICE_INACTIVE);
+ ok = (st & RC_SERVICE_STARTING ||
+ st & RC_SERVICE_STOPPING ||
+ st & RC_SERVICE_INACTIVE);
break;
default:
break;
@@ -264,10 +244,10 @@ static bool get_provided1 (const char *runlevel, struct lhead *providers,
continue;
retval = true;
- rc_strlist_add (&providers->list, service);
+ rc_stringlist_add(providers, svc);
}
- return (retval);
+ return retval;
}
/* Work out if a service is provided by another service.
@@ -279,50 +259,41 @@ static bool get_provided1 (const char *runlevel, struct lhead *providers,
If there are any bugs in rc-depend, they will probably be here as
provided dependancy can change depending on runlevel state.
*/
-static char **get_provided (const rc_depinfo_t *deptree,
- const rc_depinfo_t *depinfo,
- const char *runlevel, int options)
+static RC_STRINGLIST *get_provided (const RC_DEPINFO *depinfo,
+ const char *runlevel, int options)
{
- rc_deptype_t *dt;
- struct lhead providers;
- char *service;
- int i;
+ RC_DEPTYPE *dt;
+ RC_STRINGLIST *providers = rc_stringlist_new();
+ RC_STRING *service;
- if (! deptree || ! depinfo)
- return (NULL);
-
- if (rc_service_exists (depinfo->service))
- return (NULL);
-
- dt = get_deptype (depinfo, "providedby");
+ dt = get_deptype(depinfo, "providedby");
if (! dt)
- return (NULL);
+ return providers;
- memset (&providers, 0, sizeof (providers));
/* If we are stopping then all depends are true, regardless of state.
This is especially true for net services as they could force a restart
of the local dns resolver which may depend on net. */
if (options & RC_DEP_STOP)
{
- STRLIST_FOREACH (dt->services, service, i)
- rc_strlist_add (&providers.list, service);
-
- return (providers.list);
+ TAILQ_FOREACH(service, dt->services, entries)
+ rc_stringlist_add(providers, service->value);
+ return providers;
}
/* If we're strict or startng, then only use what we have in our
* runlevel and bootlevel. If we starting then check cold-plugged too. */
if (options & RC_DEP_STRICT || options & RC_DEP_START)
{
- STRLIST_FOREACH (dt->services, service, i)
- if (rc_service_in_runlevel (service, runlevel) ||
- rc_service_in_runlevel (service, bootlevel) ||
+
+ TAILQ_FOREACH(service, dt->services, entries)
+ if (rc_service_in_runlevel(service->value, runlevel) ||
+ rc_service_in_runlevel(service->value, bootlevel) ||
(options & RC_DEP_START &&
- rc_service_state (service) & RC_SERVICE_COLDPLUGGED))
- rc_strlist_add (&providers.list, service);
+ rc_service_state(service->value) & RC_SERVICE_COLDPLUGGED))
+ rc_stringlist_add(providers, service->value);
- if (providers.list)
- return (providers.list);
+ if (TAILQ_FIRST(providers))
+ return providers;
}
/* OK, we're not strict or there were no services in our runlevel.
@@ -333,225 +304,211 @@ static char **get_provided (const rc_depinfo_t *deptree,
We apply this to our runlevel, coldplugged services, then bootlevel
and finally any running.*/
#define DO \
- if (providers.list && providers.list[0] && providers.list[1]) \
- { \
- rc_strlist_free (providers.list); \
- return (NULL); \
- } \
- else if (providers.list) \
- return providers.list; \
+ if (TAILQ_FIRST(providers)) { \
+ if (TAILQ_NEXT(TAILQ_FIRST(providers), entries)) { \
+ rc_stringlist_free(providers); \
+ providers = rc_stringlist_new(); \
+ } \
+ return providers; \
+ }
/* Anything in the runlevel has to come first */
- if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STARTED))
+ if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTED))
{ DO }
- if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STARTING))
- return (providers.list);
- if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STOPPED))
- return (providers.list);
+ if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTING))
+ return providers;
+ if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STOPPED))
+ return providers;
/* Check coldplugged services */
- if (get_provided1 (runlevel, &providers, dt, NULL, true, RC_SERVICE_STARTED))
+ if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STARTED))
{ DO }
- if (get_provided1 (runlevel, &providers, dt, NULL, true, RC_SERVICE_STARTING))
- return (providers.list);
+ if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STARTING))
+ return providers;
/* Check bootlevel if we're not in it */
if (bootlevel && strcmp (runlevel, bootlevel) != 0)
{
- if (get_provided1 (runlevel, &providers, dt, bootlevel, false, RC_SERVICE_STARTED))
+ if (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTED))
{ DO }
- if (get_provided1 (runlevel, &providers, dt, bootlevel, false, RC_SERVICE_STARTING))
- return (providers.list);
+ if (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTING))
+ return providers;
}
/* Check coldplugged services */
- if (get_provided1 (runlevel, &providers, dt, NULL, true, RC_SERVICE_STOPPED))
+ if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STOPPED))
{ DO }
/* Check manually started */
- if (get_provided1 (runlevel, &providers, dt, NULL, false, RC_SERVICE_STARTED))
+ if (get_provided1 (runlevel, providers, dt, NULL, false, RC_SERVICE_STARTED))
{ DO }
- if (get_provided1 (runlevel, &providers, dt, NULL, false, RC_SERVICE_STARTING))
- return (providers.list);
+ if (get_provided1 (runlevel, providers, dt, NULL, false, RC_SERVICE_STARTING))
+ return providers;
/* Nothing started then. OK, lets get the stopped services */
- if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STOPPED))
- return (providers.list);
+ if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STOPPED))
+ return providers;
if (bootlevel && (strcmp (runlevel, bootlevel) != 0)
- && (get_provided1 (runlevel, &providers, dt, bootlevel, false, RC_SERVICE_STOPPED)))
- return (providers.list);
+ && (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STOPPED)))
+ return providers;
/* Still nothing? OK, list all services */
- STRLIST_FOREACH (dt->services, service, i)
- rc_strlist_add (&providers.list, service);
+ TAILQ_FOREACH(service, dt->services, entries)
+ rc_stringlist_add(providers, service->value);
- return (providers.list);
+ return providers;
}
-static void visit_service (const rc_depinfo_t *deptree,
- const char * const *types,
- struct lhead *sorted, struct lhead *visited,
- const rc_depinfo_t *depinfo,
+static void visit_service (const RC_DEPTREE *deptree,
+ const RC_STRINGLIST *types,
+ RC_STRINGLIST *sorted,
+ RC_STRINGLIST *visited,
+ const RC_DEPINFO *depinfo,
const char *runlevel, int options)
{
- int i, j, k;
- char *lp;
- const char *item;
- char *service;
- rc_depinfo_t *di;
- rc_deptype_t *dt;
- char **provides;
- char *svcname;
-
- if (! deptree || !sorted || !visited || !depinfo)
- return;
+ RC_STRING *type;
+ RC_STRING *service;
+ RC_DEPTYPE *dt;
+ RC_DEPINFO *di;
+ RC_STRINGLIST *provided;
+ RC_STRING *p;
+ const char *svcname;
/* Check if we have already visited this service or not */
- STRLIST_FOREACH (visited->list, item, i)
- if (strcmp (item, depinfo->service) == 0)
+ TAILQ_FOREACH(type, visited, entries)
+ if (strcmp(type->value, depinfo->service) == 0)
return;
/* Add ourselves as a visited service */
- rc_strlist_add (&visited->list, depinfo->service);
+ rc_stringlist_add(visited, depinfo->service);
- STRLIST_FOREACH (types, item, i)
+ TAILQ_FOREACH(type, types, entries)
{
- if ((dt = get_deptype (depinfo, item)))
- {
- STRLIST_FOREACH (dt->services, service, j)
+ if (!(dt = get_deptype(depinfo, type->value)))
+ continue;
+
+ TAILQ_FOREACH(service, dt->services, entries) {
+ if (! options & RC_DEP_TRACE ||
+ strcmp(type->value, "iprovide") == 0)
{
- if (! options & RC_DEP_TRACE || strcmp (item, "iprovide") == 0)
- {
- rc_strlist_add (&sorted->list, service);
- continue;
- }
+ rc_stringlist_add(sorted, service->value);
+ continue;
+ }
- di = get_depinfo (deptree, service);
- if ((provides = get_provided (deptree, di, runlevel, options)))
- {
- STRLIST_FOREACH (provides, lp, k)
- {
- di = get_depinfo (deptree, lp);
- if (di && (strcmp (item, "ineed") == 0 ||
- strcmp (item, "needsme") == 0 ||
- valid_service (runlevel, di->service)))
- visit_service (deptree, types, sorted, visited, di,
- runlevel, options | RC_DEP_TRACE);
- }
- rc_strlist_free (provides);
+ if (!(di = get_depinfo(deptree, service->value)))
+ continue;
+ provided = get_provided(di, runlevel, options);
+
+ if (TAILQ_FIRST(provided)) {
+ TAILQ_FOREACH(p, provided, entries) {
+ di = get_depinfo(deptree, p->value);
+ if (di &&
+ (strcmp(type->value, "ineed") == 0 ||
+ strcmp(type->value, "needsme") == 0 ||
+ valid_service(runlevel, di->service)))
+ visit_service(deptree, types, sorted, visited, di,
+ runlevel, options | RC_DEP_TRACE);
}
- else
- if (di && (strcmp (item, "ineed") == 0 ||
- strcmp (item, "needsme") == 0 ||
- valid_service (runlevel, service)))
- visit_service (deptree, types, sorted, visited, di,
- runlevel, options | RC_DEP_TRACE);
}
+ else if (di &&
+ (strcmp(type->value, "ineed") == 0 ||
+ strcmp(type->value, "needsme") == 0 ||
+ valid_service(runlevel, service->value)))
+ visit_service(deptree, types, sorted, visited, di,
+ runlevel, options | RC_DEP_TRACE);
+
+ rc_stringlist_free(provided);
}
}
/* Now visit the stuff we provide for */
if (options & RC_DEP_TRACE &&
- (dt = get_deptype (depinfo, "iprovide")))
+ (dt = get_deptype(depinfo, "iprovide")))
{
- STRLIST_FOREACH (dt->services, service, i)
- {
- if ((di = get_depinfo (deptree, service)))
- if ((provides = get_provided (deptree, di, runlevel, options)))
- {
- STRLIST_FOREACH (provides, lp, j)
- if (strcmp (lp, depinfo->service) == 0)
- {
- visit_service (deptree, types, sorted, visited, di,
- runlevel, options | RC_DEP_TRACE);
- break;
- }
- rc_strlist_free (provides);
+ TAILQ_FOREACH(service, dt->services, entries) {
+ if (!(di = get_depinfo(deptree, service->value)))
+ continue;
+
+ provided = get_provided(di, runlevel, options);
+ TAILQ_FOREACH(p, provided, entries)
+ if (strcmp (p->value, depinfo->service) == 0) {
+ //visit_service (deptree, types, sorted, visited, di,
+ // runlevel, options | RC_DEP_TRACE);
+ break;
}
+ rc_stringlist_free(provided);
}
}
/* We've visited everything we need, so add ourselves unless we
are also the service calling us or we are provided by something */
svcname = getenv("SVCNAME");
- if (! svcname || strcmp (svcname, depinfo->service) != 0)
- if (! get_deptype (depinfo, "providedby"))
- rc_strlist_add (&sorted->list, depinfo->service);
+ if (! svcname || strcmp(svcname, depinfo->service) != 0)
+ if (! get_deptype(depinfo, "providedby"))
+ rc_stringlist_add(sorted, depinfo->service);
}
-char **rc_deptree_depend (const rc_depinfo_t *deptree,
- const char *service, const char *type)
+RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *deptree,
+ const char *service, const char *type)
{
- rc_depinfo_t *di;
- rc_deptype_t *dt;
- char **svcs = NULL;
- int i;
- char *svc;
+ RC_DEPINFO *di;
+ RC_DEPTYPE *dt;
+ RC_STRINGLIST *svcs;
+ RC_STRING *svc;
- if (! (di = get_depinfo (deptree, service)) ||
- ! (dt = get_deptype (di, type)))
+ if (!(di = get_depinfo(deptree, service)) ||
+ ! (dt = get_deptype(di, type)))
{
errno = ENOENT;
- return (NULL);
+ return NULL;
}
/* For consistency, we copy the array */
- STRLIST_FOREACH (dt->services, svc, i)
- rc_strlist_add (&svcs, svc);
+ svcs = rc_stringlist_new();
+ TAILQ_FOREACH(svc, dt->services, entries)
+ rc_stringlist_add(svcs, svc->value);
- return (svcs);
+ return svcs;
}
librc_hidden_def(rc_deptree_depend)
-char **rc_deptree_depends (const rc_depinfo_t *deptree,
- const char *const *types,
- const char *const *services,
- const char *runlevel, int options)
+RC_STRINGLIST *rc_deptree_depends (const RC_DEPTREE *deptree,
+ const RC_STRINGLIST *types,
+ const RC_STRINGLIST *services,
+ const char *runlevel, int options)
{
- struct lhead sorted;
- struct lhead visited;
- rc_depinfo_t *di;
- const char *service;
- int i;
-
- if (! deptree || ! services)
- return (NULL);
-
- memset (&sorted, 0, sizeof (sorted));
- memset (&visited, 0, sizeof (visited));
+ RC_STRINGLIST *sorted = rc_stringlist_new();
+ RC_STRINGLIST *visited = rc_stringlist_new();
+ RC_DEPINFO *di;
+ const RC_STRING *service;
bootlevel = getenv ("RC_BOOTLEVEL");
if (! bootlevel)
bootlevel = RC_LEVEL_BOOT;
- STRLIST_FOREACH (services, service, i)
- {
- if (! (di = get_depinfo (deptree, service))) {
+ TAILQ_FOREACH(service, services, entries) {
+ if (! (di = get_depinfo(deptree, service->value))) {
errno = ENOENT;
continue;
}
if (types)
- visit_service (deptree, types, &sorted, &visited,
+ visit_service (deptree, types, sorted, visited,
di, runlevel, options);
}
- rc_strlist_free (visited.list);
- return (sorted.list);
+ rc_stringlist_free (visited);
+ return sorted;
}
librc_hidden_def(rc_deptree_depends)
- static const char * const order_types[] = { "ineed", "iuse", "iafter", NULL };
-char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel,
- int options)
+RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree,
+ const char *runlevel, int options)
{
- char **list = NULL;
- char **services = NULL;
- bool reverse = false;
- char **tmp = NULL;
-
- if (! runlevel)
- return (NULL);
+ RC_STRINGLIST *list;
+ RC_STRINGLIST *list2;
+ RC_STRINGLIST *types;
+ RC_STRINGLIST *services;
bootlevel = getenv ("RC_BOOTLEVEL");
if (! bootlevel)
@@ -562,47 +519,48 @@ char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel,
strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
{
- list = rc_services_in_state (RC_SERVICE_STARTED);
+ list = rc_services_in_state(RC_SERVICE_STARTED);
- tmp = rc_services_in_state (RC_SERVICE_INACTIVE);
- rc_strlist_join (&list, tmp);
- rc_strlist_free (tmp);
+ list2 = rc_services_in_state (RC_SERVICE_INACTIVE);
+ TAILQ_CONCAT(list, list2);
+ free(list2);
- tmp = rc_services_in_state (RC_SERVICE_STARTING);
- rc_strlist_join (&list, tmp);
- rc_strlist_free (tmp);
- reverse = true;
+ list2 = rc_services_in_state (RC_SERVICE_STARTING);
+ TAILQ_CONCAT(list, list2);
+ free(list2);
} else {
list = rc_services_in_runlevel (runlevel);
/* Add coldplugged services */
- tmp = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
- rc_strlist_join (&list, tmp);
- rc_strlist_free (tmp);
+ list2 = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
+ TAILQ_CONCAT(list, list2);
+ free(list2);
/* If we're not the boot runlevel then add that too */
if (strcmp (runlevel, bootlevel) != 0) {
- tmp = rc_services_in_runlevel (bootlevel);
- rc_strlist_join (&list, tmp);
- rc_strlist_free (tmp);
+ list2 = rc_services_in_runlevel (bootlevel);
+ TAILQ_CONCAT(list, list2);
+ free(list2);
}
}
/* Now we have our lists, we need to pull in any dependencies
and order them */
- services = rc_deptree_depends (deptree, order_types, (const char **) list,
- runlevel,
- RC_DEP_STRICT | RC_DEP_TRACE | options);
- rc_strlist_free (list);
+ types = rc_stringlist_new();
+ rc_stringlist_add(types, "ineed");
+ rc_stringlist_add(types, "iuse");
+ rc_stringlist_add(types, "iafter");
- if (reverse)
- rc_strlist_reverse (services);
+ services = rc_deptree_depends(deptree, types, list, runlevel,
+ RC_DEP_STRICT | RC_DEP_TRACE | options);
+ rc_stringlist_free (list);
+ rc_stringlist_free (types);
- return (services);
+ return services;
}
librc_hidden_def(rc_deptree_order)
-bool rc_newer_than (const char *source, const char *target)
+bool rc_newer_than(const char *source, const char *target)
{
struct stat buf;
time_t mtime;
@@ -613,38 +571,38 @@ bool rc_newer_than (const char *source, const char *target)
int serrno = errno;
/* We have to exist */
- if (stat (source, &buf) != 0)
- return (false);
+ if (stat(source, &buf) != 0)
+ return false;
mtime = buf.st_mtime;
/* Of course we are newer than targets that don't exist
such as broken symlinks */
- if (stat (target, &buf) != 0)
- return (true);
+ if (stat(target, &buf) != 0)
+ return true;
if (mtime < buf.st_mtime)
- return (false);
+ return false;
/* If not a dir then reset errno */
- if (! (dp = opendir (target))) {
+ if (! (dp = opendir(target))) {
errno = serrno;
- return (true);
+ return true;
}
/* Check if we're newer than all the entries in the dir */
- while ((d = readdir (dp))) {
+ while ((d = readdir(dp))) {
if (d->d_name[0] == '.')
continue;
- path = rc_strcatpaths (target, d->d_name, (char *) NULL);
- newer = rc_newer_than (source, path);
- free (path);
+ path = rc_strcatpaths(target, d->d_name, (char *) NULL);
+ newer = rc_newer_than(source, path);
+ free(path);
if (! newer)
break;
}
- closedir (dp);
+ closedir(dp);
- return (newer);
+ return newer;
}
librc_hidden_def(rc_newer_than)
@@ -652,12 +610,12 @@ typedef struct deppair
{
const char *depend;
const char *addto;
-} deppair_t;
+} DEPPAIR;
-static const deppair_t deppairs[] = {
- { "ineed", "needsme" },
- { "iuse", "usesme" },
- { "iafter", "ibefore" },
+static const DEPPAIR deppairs[] = {
+ { "ineed", "needsme" },
+ { "iuse", "usesme" },
+ { "iafter", "ibefore" },
{ "ibefore", "iafter" },
{ "iprovide", "providedby" },
{ NULL, NULL }
@@ -679,168 +637,151 @@ static const char *const depdirs[] =
NULL
};
-bool rc_deptree_update_needed (void)
+bool rc_deptree_update_needed(void)
{
bool newer = false;
- char **config;
- char *service;
+ RC_STRINGLIST *config;
+ RC_STRING *s;
int i;
/* Create base directories if needed */
for (i = 0; depdirs[i]; i++)
- if (mkdir (depdirs[i], 0755) != 0 && errno != EEXIST)
- fprintf (stderr, "mkdir `%s': %s\n", depdirs[i], strerror (errno));
+ if (mkdir(depdirs[i], 0755) != 0 && errno != EEXIST)
+ fprintf(stderr, "mkdir `%s': %s\n", depdirs[i], strerror (errno));
/* Quick test to see if anything we use has changed and we have
* data in our deptree */
- if (! existss (RC_DEPTREE) ||
- ! rc_newer_than (RC_DEPTREE, RC_INITDIR) ||
- ! rc_newer_than (RC_DEPTREE, RC_CONFDIR) ||
+ if (! existss(RC_DEPTREE_CACHE) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR) ||
#ifdef RC_PKG_INITDIR
- ! rc_newer_than (RC_DEPTREE, RC_PKG_INITDIR) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR) ||
#endif
#ifdef RC_PKG_CONFDIR
- ! rc_newer_than (RC_DEPTREE, RC_PKG_CONFDIR) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR) ||
#endif
#ifdef RC_LOCAL_INITDIR
- ! rc_newer_than (RC_DEPTREE, RC_LOCAL_INITDIR) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR) ||
#endif
#ifdef RC_LOCAL_CONFDIR
- ! rc_newer_than (RC_DEPTREE, RC_LOCAL_CONFDIR) ||
+ ! rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR) ||
#endif
- ! rc_newer_than (RC_DEPTREE, "/etc/rc.conf"))
- return (true);
+ ! rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf"))
+ return true;
/* Some init scripts dependencies change depending on config files
* outside of baselayout, like syslog-ng, so we check those too. */
config = rc_config_list (RC_DEPCONFIG);
- STRLIST_FOREACH (config, service, i) {
- if (! rc_newer_than (RC_DEPTREE, service)) {
+ TAILQ_FOREACH(s, config, entries) {
+ if (! rc_newer_than(RC_DEPTREE_CACHE, s->value)) {
newer = true;
break;
}
}
- rc_strlist_free (config);
+ rc_stringlist_free(config);
- return (newer);
+ return newer;
}
librc_hidden_def(rc_deptree_update_needed)
- /* This is a 5 phase operation
- Phase 1 is a shell script which loads each init script and config in turn
- and echos their dependency info to stdout
- Phase 2 takes that and populates a depinfo object with that data
- Phase 3 adds any provided services to the depinfo object
- Phase 4 scans that depinfo object and puts in backlinks
- Phase 5 saves the depinfo object to disk
- */
-bool rc_deptree_update (void)
+/* This is a 5 phase operation
+ Phase 1 is a shell script which loads each init script and config in turn
+ and echos their dependency info to stdout
+ Phase 2 takes that and populates a depinfo object with that data
+ Phase 3 adds any provided services to the depinfo object
+ Phase 4 scans that depinfo object and puts in backlinks
+ Phase 5 saves the depinfo object to disk
+ */
+bool rc_deptree_update(void)
{
+ FILE *fp;
+ RC_DEPTREE *deptree;
+ RC_DEPTREE *providers;
+ RC_DEPINFO *depinfo = NULL;
+ RC_DEPINFO *depinfo_np;
+ RC_DEPINFO *di;
+ RC_DEPTYPE *deptype = NULL;
+ RC_DEPTYPE *dt;
+ RC_DEPTYPE *dt_np;
+ RC_STRINGLIST *config;
+ RC_STRING *s;
+ RC_STRING *s2;
+ RC_DEPTYPE *provide;
+ char *line;
+ char *depend;
char *depends;
char *service;
char *type;
- char *depend;
- char **config = NULL;
- int retval = true;
- FILE *fp;
- rc_depinfo_t *deptree = NULL;
- rc_depinfo_t *depinfo;
- rc_depinfo_t *di;
- rc_depinfo_t *last_depinfo = NULL;
- rc_deptype_t *deptype = NULL;
- rc_deptype_t *dt;
- rc_deptype_t *last_deptype = NULL;
- char **removedp = NULL;
- char *line;
- size_t len;
size_t i;
- size_t j;
size_t k;
- bool already_added;
- const char *sys = rc_sys ();
+ size_t len;
+ int retval = true;
+ const char *sys = rc_sys();
+ char *nosys;
/* Some init scripts need RC_LIBDIR to source stuff
Ideally we should be setting our full env instead */
- if (! getenv ("RC_LIBDIR"))
- setenv ("RC_LIBDIR", RC_LIBDIR, 0);
+ if (! getenv("RC_LIBDIR"))
+ setenv("RC_LIBDIR", RC_LIBDIR, 0);
/* Phase 1 - source all init scripts and print dependencies */
- if (! (fp = popen (GENDEP, "r")))
- return (false);
+ if (! (fp = popen(GENDEP, "r")))
+ return false;
+
+ deptree = xmalloc(sizeof(*deptree));
+ STAILQ_INIT(deptree);
- while ((line = rc_getline (fp)))
+ config = rc_stringlist_new();
+
+ while ((line = rc_getline(fp)))
{
depends = line;
- service = strsep (&depends, " ");
+ service = strsep(&depends, " ");
if (! service || ! *service)
goto next;
- type = strsep (&depends, " ");
+ type = strsep(&depends, " ");
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- last_depinfo = depinfo;
- if (depinfo->service && strcmp (depinfo->service, service) == 0)
- break;
- }
-
- if (! depinfo)
- {
- if (! last_depinfo)
- deptree = depinfo = xzalloc (sizeof (*depinfo));
- else if (! last_depinfo->service)
- depinfo = last_depinfo;
- else
- {
- last_depinfo->next = xzalloc (sizeof (*last_depinfo->next));
- depinfo = last_depinfo->next;
+ if (! depinfo || strcmp(depinfo->service, service) != 0) {
+ deptype = NULL;
+ depinfo = get_depinfo(deptree, service);
+ if (! depinfo) {
+ depinfo = xmalloc(sizeof(*depinfo));
+ STAILQ_INIT(&depinfo->depends);
+ depinfo->service = xstrdup(service);
+ STAILQ_INSERT_TAIL(deptree, depinfo, entries);
}
- depinfo->service = xstrdup (service);
}
-
+
/* We may not have any depends */
if (! type || ! depends)
goto next;
/* Get the type */
- if (strcmp (type, "config") != 0) {
- last_deptype = NULL;
- for (deptype = depinfo->depends; deptype; deptype = deptype->next)
- {
- last_deptype = deptype;
- if (strcmp (deptype->type, type) == 0)
- break;
- }
-
- if (! deptype)
- {
- if (! last_deptype)
- {
- depinfo->depends = xzalloc (sizeof (*depinfo->depends));
- deptype = depinfo->depends;
- }
- else
- {
- last_deptype->next = xzalloc (sizeof (*last_deptype->next));
- deptype = last_deptype->next;
- }
- deptype->type = xstrdup (type);
+ if (strcmp(type, "config") != 0) {
+ if (! deptype || strcmp (deptype->type, type) != 0)
+ deptype = get_deptype(depinfo, type);
+ if (! deptype) {
+ deptype = xmalloc(sizeof(*deptype));
+ deptype->type = xstrdup(type);
+ deptype->services = rc_stringlist_new();
+ STAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
}
}
/* Now add each depend to our type.
We do this individually so we handle multiple spaces gracefully */
- while ((depend = strsep (&depends, " ")))
+ while ((depend = strsep(&depends, " ")))
{
if (depend[0] == 0)
continue;
- if (strcmp (type, "config") == 0) {
- rc_strlist_addsort (&config, depend);
+ if (strcmp(type, "config") == 0) {
+ rc_stringlist_add(config, depend);
continue;
}
/* .sh files are not init scripts */
- len = strlen (depend);
+ len = strlen(depend);
if (len > 2 &&
depend[len - 3] == '.' &&
depend[len - 2] == 's' &&
@@ -849,171 +790,114 @@ bool rc_deptree_update (void)
/* Remove our dependency if instructed */
if (depend[0] == '!') {
- rc_strlist_delete (&deptype->services, depend + 1);
+ rc_stringlist_delete(deptype->services, depend + 1);
continue;
}
- rc_strlist_addsort (&deptype->services, depend);
+ rc_stringlist_add(deptype->services, depend);
/* We need to allow `after *; before local;` to work.
* Conversely, we need to allow 'before *; after modules' also */
/* If we're before something, remove us from the after list */
- if (strcmp (type, "ibefore") == 0) {
- if ((dt = get_deptype (depinfo, "iafter")))
- rc_strlist_delete (&dt->services, depend);
+ if (strcmp(type, "ibefore") == 0) {
+ if ((dt = get_deptype(depinfo, "iafter")))
+ rc_stringlist_delete(dt->services, depend);
}
/* If we're after something, remove us from the before list */
if (strcmp (type, "iafter") == 0 ||
strcmp (type, "ineed") == 0 ||
strcmp (type, "iuse") == 0) {
- if ((dt = get_deptype (depinfo, "ibefore")))
- rc_strlist_delete (&dt->services, depend);
+ if ((dt = get_deptype(depinfo, "ibefore")))
+ rc_stringlist_delete(dt->services, depend);
}
}
next:
- free (line);
+ free(line);
}
- pclose (fp);
+ pclose(fp);
/* Phase 2 - if we're a special system, remove services that don't
* work for them. This doesn't stop them from being run directly. */
if (sys) {
- char *nosys;
-
- len = strlen (sys);
- nosys = xmalloc (len + 3);
+ len = strlen(sys);
+ nosys = xmalloc(len + 3);
nosys[0] = 'n';
nosys[1] = 'o';
for (i = 0; i < len; i++)
- nosys[i + 2] = (char) tolower ((int) sys[i]);
+ nosys[i + 2] = (char) tolower((int) sys[i]);
nosys[i + 2] = '\0';
- last_depinfo = NULL;
- depinfo = deptree;
- while (depinfo) {
- bool removed = false;
- if ((deptype = get_deptype (depinfo, "keyword"))) {
- STRLIST_FOREACH (deptype->services, service, i)
- if (strcmp (service, nosys) == 0) {
- if (last_depinfo)
- last_depinfo->next = depinfo->next;
- else
- deptree = depinfo->next;
- removed = true;
- break;
+ STAILQ_FOREACH_SAFE(depinfo, deptree, entries, depinfo_np)
+ if ((deptype = get_deptype(depinfo, "keyword")))
+ TAILQ_FOREACH(s, deptype->services, entries)
+ if (strcmp (s->value, nosys) == 0) {
+ provide = get_deptype(depinfo, "iprovide");
+ STAILQ_REMOVE(deptree, depinfo, rc_depinfo, entries);
+ STAILQ_FOREACH(di, deptree, entries) {
+ STAILQ_FOREACH_SAFE(dt, &di->depends, entries, dt_np) {
+ rc_stringlist_delete(dt->services, depinfo->service);
+ if (provide)
+ TAILQ_FOREACH(s2, provide->services, entries)
+ rc_stringlist_delete(dt->services, s2->value);
+ if (! TAILQ_FIRST(dt->services)) {
+ STAILQ_REMOVE(&di->depends, dt, rc_deptype, entries);
+ free(dt->type);
+ free(dt->services);
+ free(dt);
+ }
+ }
+ }
}
- }
- if (removed) {
- dt = get_deptype (depinfo, "iprovide");
- if (dt)
- STRLIST_FOREACH (dt->services, service, i)
- rc_strlist_addu (&removedp, service);
- for (di = deptree; di; di = di->next) {
- for (dt = di->depends; dt; dt = dt->next)
- rc_strlist_delete (&dt->services, depinfo->service);
- }
- di = depinfo->next;
- depinfo->next = NULL;
- rc_deptree_free (depinfo);
- depinfo = di;
- } else {
- last_depinfo = depinfo;
- depinfo = depinfo->next;
- }
- }
-
free (nosys);
}
- /* Phase 3 - add our providors to the tree */
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- if ((deptype = get_deptype (depinfo, "iprovide")))
- STRLIST_FOREACH (deptype->services, service, i)
- {
- for (di = deptree; di; di = di->next)
- {
- last_depinfo = di;
- if (strcmp (di->service, service) == 0)
+ /* Phase 3 - add our providers to the tree */
+ providers = xmalloc(sizeof(*providers));
+ STAILQ_INIT(providers);
+ STAILQ_FOREACH(depinfo, deptree, entries)
+ if ((deptype = get_deptype(depinfo, "iprovide")))
+ TAILQ_FOREACH(s, deptype->services, entries) {
+ STAILQ_FOREACH(di, providers, entries)
+ if (strcmp(di->service, s->value) == 0)
break;
- }
- if (! di)
- {
- last_depinfo->next = xzalloc (sizeof (*last_depinfo->next));
- di = last_depinfo->next;
- di->service = xstrdup (service);
+ if (! di) {
+ di = xmalloc(sizeof(*di));
+ STAILQ_INIT(&di->depends);
+ di->service = xstrdup(s->value);
+ STAILQ_INSERT_TAIL(providers, di, entries);
}
}
- }
+ STAILQ_CONCAT(deptree, providers);
+ free(providers);
/* Phase 4 - backreference our depends */
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- for (i = 0; deppairs[i].depend; i++)
- {
- deptype = get_deptype (depinfo, deppairs[i].depend);
+ STAILQ_FOREACH(depinfo, deptree, entries)
+ for (i = 0; deppairs[i].depend; i++) {
+ deptype = get_deptype(depinfo, deppairs[i].depend);
if (! deptype)
continue;
-
- STRLIST_FOREACH (deptype->services, service, j)
- {
- di = get_depinfo (deptree, service);
- if (! di)
- {
+ TAILQ_FOREACH(s, deptype->services, entries) {
+ di = get_depinfo(deptree, s->value);
+ if (! di) {
if (strcmp (deptype->type, "ineed") == 0)
- {
- bool removed = false;
- STRLIST_FOREACH (removedp, line, k) {
- if (strcmp (line, service) == 0) {
- removed = true;
- break;
- }
- }
- if (! removed)
- fprintf (stderr,
- "Service `%s' needs non existant service `%s'\n",
- depinfo->service, service);
- }
+ fprintf (stderr,
+ "Service `%s' needs non"
+ " existant service `%s'\n",
+ depinfo->service, s->value);
continue;
}
- /* Add our deptype now */
- last_deptype = NULL;
- for (dt = di->depends; dt; dt = dt->next)
- {
- last_deptype = dt;
- if (strcmp (dt->type, deppairs[i].addto) == 0)
- break;
+ dt = get_deptype(di, deppairs[i].addto);
+ if (! dt) {
+ dt = xmalloc(sizeof(*dt));
+ dt->type = xstrdup(deppairs[i].addto);
+ dt->services = rc_stringlist_new();
+ STAILQ_INSERT_TAIL(&di->depends, dt, entries);
}
- if (! dt)
- {
- if (! last_deptype)
- {
- di->depends = xzalloc (sizeof (*di->depends));
- dt = di->depends;
- }
- else
- {
- last_deptype->next = xzalloc (sizeof (*last_deptype->next));
- dt = last_deptype->next;
- }
- dt->type = xstrdup (deppairs[i].addto);
- }
-
- already_added = false;
- STRLIST_FOREACH (dt->services, service, k)
- if (strcmp (service, depinfo->service) == 0)
- {
- already_added = true;
- break;
- }
-
- if (! already_added)
- rc_strlist_addsort (&dt->services, depinfo->service);
+ rc_stringlist_add(dt->services, depinfo->service);
}
}
- }
/* Phase 5 - save to disk
Now that we're purely in C, do we need to keep a shell parseable file?
@@ -1021,49 +905,47 @@ next:
This works and should be entirely shell parseable provided that depend
names don't have any non shell variable characters in
*/
- if ((fp = fopen (RC_DEPTREE, "w"))) {
+ if ((fp = fopen (RC_DEPTREE_CACHE, "w"))) {
i = 0;
- for (depinfo = deptree; depinfo; depinfo = depinfo->next)
- {
- fprintf (fp, "depinfo_%zu_service='%s'\n",
- i, depinfo->service);
- for (deptype = depinfo->depends; deptype; deptype = deptype->next)
- {
+ STAILQ_FOREACH(depinfo, deptree, entries) {
+ fprintf(fp, "depinfo_%zu_service='%s'\n",
+ i, depinfo->service);
+ STAILQ_FOREACH(deptype, &depinfo->depends, entries) {
k = 0;
- STRLIST_FOREACH (deptype->services, service, j)
- {
- fprintf (fp,
- "depinfo_%zu_%s_%zu='%s'\n",
- i,
- deptype->type,
- k, service);
+ TAILQ_FOREACH(s, deptype->services, entries) {
+ fprintf(fp,
+ "depinfo_%zu_%s_%zu='%s'\n",
+ i, deptype->type, k, s->value);
k++;
}
}
i++;
}
- fclose (fp);
+ fclose(fp);
} else {
- fprintf (stderr, "fopen `%s': %s\n", RC_DEPTREE, strerror (errno));
+ fprintf(stderr, "fopen `%s': %s\n",
+ RC_DEPTREE_CACHE, strerror(errno));
retval = false;
}
/* Save our external config files to disk */
- if (config) {
- if ((fp = fopen (RC_DEPCONFIG, "w"))) {
- STRLIST_FOREACH (config, service, i)
- fprintf (fp, "%s\n", service);
- fclose (fp);
+ if (TAILQ_FIRST(config)) {
+ if ((fp = fopen(RC_DEPCONFIG, "w"))) {
+ TAILQ_FOREACH(s, config, entries)
+ fprintf (fp, "%s\n", s->value);
+ fclose(fp);
} else {
- fprintf (stderr, "fopen `%s': %s\n", RC_DEPCONFIG, strerror (errno));
+ fprintf(stderr, "fopen `%s': %s\n",
+ RC_DEPCONFIG, strerror(errno));
retval = false;
}
- rc_strlist_free (config);
+ rc_stringlist_free (config);
+ } else {
+ unlink(RC_DEPCONFIG);
}
- rc_strlist_free (removedp);
- rc_deptree_free (deptree);
+ rc_deptree_free(deptree);
- return (retval);
+ return retval;
}
librc_hidden_def(rc_deptree_update)
diff --git a/src/librc/librc-depend.h b/src/librc/librc-depend.h
deleted file mode 100644
index 737920e..0000000
--- a/src/librc/librc-depend.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * librc-depend.h
- * Internal header file for dependency structures
- */
-
-/*
- * Copyright 2007-2008 Roy Marples
- * All rights reserved
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _LIBRC_DEPEND_H
-#define _LIBRC_DEPEND_H
-
-/*! @name Dependency structures
- * private to librc - rc.h exposes them just a pointers */
-
-/*! Singly linked list of dependency types that list the services the
- * type is for */
-typedef struct rc_deptype
-{
- /*! ineed, iuse, iafter, etc */
- char *type;
- /*! NULL terminated list of services */
- char **services;
- /*! Next dependency type */
- struct rc_deptype *next;
-} rc_deptype_t;
-
-/*! Singly linked list of services and their dependencies */
-typedef struct rc_depinfo
-{
- /*! Name of service */
- char *service;
- /*! Dependencies */
- rc_deptype_t *depends;
- /*! Next service dependency type */
- struct rc_depinfo *next;
-} rc_depinfo_t;
-
-#endif
diff --git a/src/librc/librc-misc.c b/src/librc/librc-misc.c
index f08a762..fac78e2 100644
--- a/src/librc/librc-misc.c
+++ b/src/librc/librc-misc.c
@@ -35,14 +35,14 @@ bool rc_yesno (const char *value)
{
if (! value) {
errno = ENOENT;
- return (false);
+ return false;
}
if (strcasecmp (value, "yes") == 0 ||
strcasecmp (value, "y") == 0 ||
strcasecmp (value, "true") == 0 ||
strcasecmp (value, "1") == 0)
- return (true);
+ return true;
if (strcasecmp (value, "no") != 0 &&
strcasecmp (value, "n") != 0 &&
@@ -50,7 +50,7 @@ bool rc_yesno (const char *value)
strcasecmp (value, "0") != 0)
errno = EINVAL;
- return (false);
+ return false;
}
librc_hidden_def(rc_yesno)
@@ -64,7 +64,7 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...)
char *pathp;
if (! path1 || ! paths)
- return (NULL);
+ return NULL;
length = strlen (path1) + strlen (paths) + 1;
if (*paths != '/')
@@ -101,7 +101,7 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...)
*pathp++ = 0;
- return (path);
+ return path;
}
librc_hidden_def(rc_strcatpaths)
@@ -113,7 +113,7 @@ char *rc_getline (FILE *fp)
size_t last = 0;
if (feof (fp))
- return (NULL);
+ return NULL;
do {
len += BUFSIZ;
@@ -128,74 +128,78 @@ char *rc_getline (FILE *fp)
if (*line && line[--last] == '\n')
line[last] = '\0';
- return (line);
+ return line;
}
librc_hidden_def(rc_getline)
-char **rc_config_list (const char *file)
+RC_STRINGLIST *rc_config_list(const char *file)
{
FILE *fp;
char *buffer;
char *p;
char *token;
- char **list = NULL;
+ RC_STRINGLIST *list;
- if (! (fp = fopen (file, "r")))
- return (NULL);
+ if (!(fp = fopen(file, "r")))
+ return NULL;
- while ((p = buffer = rc_getline (fp))) {
+ list = rc_stringlist_new();
+
+ while ((p = buffer = rc_getline(fp))) {
/* Strip leading spaces/tabs */
while ((*p == ' ') || (*p == '\t'))
p++;
/* Get entry - we do not want comments */
- token = strsep (&p, "#");
- if (token && (strlen (token) > 1)) {
+ token = strsep(&p, "#");
+ if (token && (strlen(token) > 1)) {
/* If not variable assignment then skip */
- if (strchr (token, '=')) {
+ if (strchr(token, '=')) {
/* Stip the newline if present */
- if (token[strlen (token) - 1] == '\n')
- token[strlen (token) - 1] = 0;
+ if (token[strlen(token) - 1] == '\n')
+ token[strlen(token) - 1] = 0;
- rc_strlist_add (&list, token);
+ rc_stringlist_add(list, token);
}
}
- free (buffer);
+ free(buffer);
}
- fclose (fp);
+ fclose(fp);
- return (list);
+ return list;
}
librc_hidden_def(rc_config_list)
-char **rc_config_load (const char *file)
+RC_STRINGLIST *rc_config_load(const char *file)
{
- char **list = NULL;
- char **config = NULL;
+ RC_STRINGLIST *list = NULL;
+ RC_STRINGLIST *config = NULL;
char *token;
- char *line;
- char *linep;
- char *linetok;
+ RC_STRING *line;
+ RC_STRING *cline;
size_t i = 0;
- int j;
bool replaced;
char *entry;
char *newline;
+ char *p;
- list = rc_config_list (file);
- STRLIST_FOREACH (list, line, j) {
+ config = rc_stringlist_new();
+
+ list = rc_config_list(file);
+ TAILQ_FOREACH(line, list, entries) {
/* Get entry */
- if (! (token = strsep (&line, "=")))
+ p = line->value;
+ if (! (token = strsep(&p, "=")))
continue;
entry = xstrdup (token);
/* Preserve shell coloring */
- if (*line == '$')
- token = line;
+ if (*p == '$')
+ token = line->value;
else
do {
/* Bash variables are usually quoted */
- token = strsep (&line, "\"\'");
+ token = strsep(&p, "\"\'");
} while (token && *token == '\0');
/* Drop a newline if that's all we have */
@@ -205,57 +209,54 @@ char **rc_config_load (const char *file)
token[i] = 0;
i = strlen (entry) + strlen (token) + 2;
- newline = xmalloc (sizeof (char) * i);
- snprintf (newline, i, "%s=%s", entry, token);
+ newline = xmalloc(sizeof(char) * i);
+ snprintf(newline, i, "%s=%s", entry, token);
} else {
i = strlen (entry) + 2;
- newline = xmalloc (sizeof (char) * i);
- snprintf (newline, i, "%s=", entry);
+ newline = xmalloc(sizeof(char) * i);
+ snprintf(newline, i, "%s=", entry);
}
replaced = false;
/* In shells the last item takes precedence, so we need to remove
any prior values we may already have */
- STRLIST_FOREACH (config, line, i) {
- char *tmp = xstrdup (line);
- linep = tmp;
- linetok = strsep (&linep, "=");
- if (strcmp (linetok, entry) == 0) {
+ TAILQ_FOREACH(cline, config, entries) {
+ p = strchr(cline->value, '=');
+ if (p && strncmp(entry, cline->value,
+ (size_t) (p - cline->value)) == 0)
+ {
/* We have a match now - to save time we directly replace it */
- free (config[i - 1]);
- config[i - 1] = newline;
+ free(cline->value);
+ cline->value = newline;
replaced = true;
- free (tmp);
break;
}
- free (tmp);
}
if (! replaced) {
- rc_strlist_addsort (&config, newline);
- free (newline);
+ rc_stringlist_add(config, newline);
+ free(newline);
}
- free (entry);
+ free(entry);
}
- rc_strlist_free (list);
+ rc_stringlist_free(list);
- return (config);
+ return config;
}
librc_hidden_def(rc_config_load)
-char *rc_config_value (const char *const *list, const char *entry)
+char *rc_config_value(RC_STRINGLIST *list, const char *entry)
{
- const char *line;
- int i;
+ RC_STRING *line;
char *p;
- STRLIST_FOREACH (list, line, i) {
- p = strchr (line, '=');
- if (p && strncmp (entry, line, (size_t) (p - line)) == 0)
- return (p += 1);
+ TAILQ_FOREACH(line, list, entries) {
+ p = strchr(line->value, '=');
+ if (p &&
+ strncmp(entry, line->value, (size_t)(p - line->value)) == 0)
+ return p += 1;
}
- return (NULL);
+ return NULL;
}
librc_hidden_def(rc_config_value)
-
diff --git a/src/librc/librc-strlist.c b/src/librc/librc-strlist.c
deleted file mode 100644
index 9b62269..0000000
--- a/src/librc/librc-strlist.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- librc-strlist.h
- String list functions for using char ** arrays
-
- Based on a previous implementation by Martin Schlemmer
- */
-
-/*
- * Copyright 2007-2008 Roy Marples
- * All rights reserved
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "librc.h"
-
-static char *_rc_strlist_add (char ***list, const char *item, bool uniq)
-{
- char **newlist;
- char **lst = *list;
- int i = 0;
-
- if (! item)
- return (NULL);
-
- while (lst && lst[i]) {
- if (uniq && strcmp (lst[i], item) == 0) {
- errno = EEXIST;
- return (NULL);
- }
- i++;
- }
-
- newlist = xrealloc (lst, sizeof (char *) * (i + 2));
- newlist[i] = xstrdup (item);
- newlist[i + 1] = NULL;
-
- *list = newlist;
- return (newlist[i]);
-}
-
-char *rc_strlist_add (char ***list, const char *item)
-{
- return (_rc_strlist_add (list, item, false));
-}
-librc_hidden_def(rc_strlist_add)
-
-char *rc_strlist_addu (char ***list, const char *item)
-{
- return (_rc_strlist_add (list, item, true));
-}
-librc_hidden_def(rc_strlist_addu)
-
-static char *_rc_strlist_addsort (char ***list, const char *item,
- int (*sortfunc) (const char *s1,
- const char *s2),
- bool uniq)
-{
- char **newlist;
- char **lst = *list;
- int i = 0;
- char *tmp1;
- char *tmp2;
- char *retval;
-
- if (! item)
- return (NULL);
-
- while (lst && lst[i]) {
- if (uniq && strcmp (lst[i], item) == 0) {
- errno = EEXIST;
- return (NULL);
- }
- i++;
- }
-
- newlist = xrealloc (lst, sizeof (char *) * (i + 2));
-
- if (! i)
- newlist[i] = NULL;
- newlist[i + 1] = NULL;
-
- i = 0;
- while (newlist[i] && sortfunc (newlist[i], item) < 0)
- i++;
-
- tmp1 = newlist[i];
- retval = newlist[i] = xstrdup (item);
- do {
- i++;
- tmp2 = newlist[i];
- newlist[i] = tmp1;
- tmp1 = tmp2;
- } while (tmp1);
-
- *list = newlist;
- return (retval);
-}
-
-char *rc_strlist_addsort (char ***list, const char *item)
-{
- return (_rc_strlist_addsort (list, item, strcoll, false));
-}
-librc_hidden_def(rc_strlist_addsort)
-
-char *rc_strlist_addsortc (char ***list, const char *item)
-{
- return (_rc_strlist_addsort (list, item, strcmp, false));
-}
-librc_hidden_def(rc_strlist_addsortc)
-
-char *rc_strlist_addsortu (char ***list, const char *item)
-{
- return (_rc_strlist_addsort (list, item, strcmp, true));
-}
-librc_hidden_def(rc_strlist_addsortu)
-
-bool rc_strlist_delete (char ***list, const char *item)
-{
- char **lst = *list;
- int i = 0;
-
- if (!lst || ! item)
- return (false);
-
- while (lst[i]) {
- if (strcmp (lst[i], item) == 0) {
- free (lst[i]);
- do {
- lst[i] = lst[i + 1];
- i++;
- } while (lst[i]);
- return (true);
- }
- i++;
- }
-
- errno = ENOENT;
- return (false);
-}
-librc_hidden_def(rc_strlist_delete)
-
-char *rc_strlist_join (char ***list1, char **list2)
-{
- char **lst1 = *list1;
- char **newlist;
- int i = 0;
- int j = 0;
-
- if (! list2)
- return (NULL);
-
- while (lst1 && lst1[i])
- i++;
-
- while (list2[j])
- j++;
-
- newlist = xrealloc (lst1, sizeof (char *) * (i + j + 1));
-
- j = 0;
- while (list2[j]) {
- newlist[i] = list2[j];
- /* Take the item off the 2nd list as it's only a shallow copy */
- list2[j] = NULL;
- i++;
- j++;
- }
- newlist[i] = NULL;
-
- *list1 = newlist;
- return (newlist[i == 0 ? 0 : i - 1]);
-}
-librc_hidden_def(rc_strlist_join)
-
-void rc_strlist_reverse (char **list)
-{
- char *item;
- int i = 0;
- int j = 0;
-
- if (! list)
- return;
-
- while (list[j])
- j++;
- j--;
-
- while (i < j && list[i] && list[j]) {
- item = list[i];
- list[i] = list[j];
- list[j] = item;
- i++;
- j--;
- }
-}
-librc_hidden_def(rc_strlist_reverse)
-
-void rc_strlist_free (char **list)
-{
- int i = 0;
-
- if (! list)
- return;
-
- while (list[i])
- free (list[i++]);
-
- free (list);
-}
-librc_hidden_def(rc_strlist_free)
diff --git a/src/librc/librc.c b/src/librc/librc.c
index 7344e37..301a388 100644
--- a/src/librc/librc.c
+++ b/src/librc/librc.c
@@ -47,7 +47,7 @@ const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
FILE *rc_environ_fd = NULL;
typedef struct rc_service_state_name {
- rc_service_state_t state;
+ RC_SERVICE state;
const char *name;
} rc_service_state_name_t;
@@ -68,49 +68,53 @@ static const rc_service_state_name_t rc_service_state_names[] = {
#define LS_INITD 0x01
#define LS_DIR 0x02
-static char **ls_dir (const char *dir, int options)
+static RC_STRINGLIST *ls_dir(const char *dir, int options)
{
DIR *dp;
struct dirent *d;
- char **list = NULL;
+ RC_STRINGLIST *list;
struct stat buf;
+ size_t l;
+ char *file;
+ int r;
- if ((dp = opendir (dir)) == NULL)
- return (NULL);
+ if ((dp = opendir(dir)) == NULL)
+ return NULL;
- while (((d = readdir (dp)) != NULL)) {
+ list = rc_stringlist_new();
+ while (((d = readdir(dp)) != NULL)) {
if (d->d_name[0] != '.') {
if (options & LS_INITD) {
- int l = strlen (d->d_name);
-
/* Check that our file really exists.
* This is important as a service maybe in a runlevel, but
* could also have been removed. */
- char *file = rc_strcatpaths (dir, d->d_name, NULL);
- int ok = stat (file, &buf);
- free (file);
- if (ok != 0)
+ file = rc_strcatpaths(dir, d->d_name, NULL);
+ r = stat(file, &buf);
+ free(file);
+ if (r != 0)
continue;
/* .sh files are not init scripts */
+ l = strlen(d->d_name);
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) {
- if (stat (d->d_name, &buf) == 0 && ! S_ISDIR (buf.st_mode))
+ if (stat(d->d_name, &buf) == 0 &&
+ ! S_ISDIR(buf.st_mode))
continue;
}
- rc_strlist_addsort (&list, d->d_name);
+ rc_stringlist_add(list, d->d_name);
}
}
- closedir (dp);
+ closedir(dp);
- return (list);
+ return list;
}
-static bool rm_dir (const char *pathname, bool top)
+static bool rm_dir(const char *pathname, bool top)
{
DIR *dp;
struct dirent *d;
@@ -118,49 +122,49 @@ static bool rm_dir (const char *pathname, bool top)
struct stat s;
bool retval = true;
- if ((dp = opendir (pathname)) == NULL)
- return (false);
+ if ((dp = opendir(pathname)) == NULL)
+ return false;
errno = 0;
- while (((d = readdir (dp)) != NULL) && errno == 0) {
- if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0) {
- free (tmp);
- tmp = rc_strcatpaths (pathname, d->d_name, (char *) NULL);
+ while (((d = readdir(dp)) != NULL) && errno == 0) {
+ if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) {
+ free(tmp);
+ tmp = rc_strcatpaths(pathname, d->d_name, (char *) NULL);
- if (stat (tmp, &s) != 0) {
+ if (stat(tmp, &s) != 0) {
retval = false;
break;
}
- if (S_ISDIR (s.st_mode)) {
- if (! rm_dir (tmp, true))
+ if (S_ISDIR(s.st_mode)) {
+ if (! rm_dir(tmp, true))
{
retval = false;
break;
}
} else {
- if (unlink (tmp)) {
+ if (unlink(tmp)) {
retval = false;
break;
}
}
}
}
- closedir (dp);
- free (tmp);
+ closedir(dp);
+ free(tmp);
if (! retval)
- return (false);
+ return false;
- if (top && rmdir (pathname) != 0)
- return (false);
+ if (top && rmdir(pathname) != 0)
+ return false;
- return (true);
+ return true;
}
/* Other systems may need this at some point, but for now it's Linux only */
#ifdef __linux__
-static bool file_regex (const char *file, const char *regex)
+static bool file_regex(const char *file, const char *regex)
{
FILE *fp;
char *line;
@@ -168,153 +172,153 @@ static bool file_regex (const char *file, const char *regex)
bool retval = false;
int result;
- if (! (fp = fopen (file, "r")))
- return (false);
+ if (! (fp = fopen(file, "r")))
+ return false;
- if ((result = regcomp (&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) {
- fclose (fp);
- line = xmalloc (sizeof (char) * BUFSIZ);
- regerror (result, &re, line, BUFSIZ);
- fprintf (stderr, "file_regex: %s", line);
- free (line);
- return (false);
+ if ((result = regcomp(&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) {
+ fclose(fp);
+ line = xmalloc(sizeof (char) * BUFSIZ);
+ regerror(result, &re, line, BUFSIZ);
+ fprintf(stderr, "file_regex: %s", line);
+ free(line);
+ return false;
}
- while ((line = rc_getline (fp))) {
- if (regexec (&re, line, 0, NULL, 0) == 0)
+ while ((line = rc_getline(fp))) {
+ if (regexec(&re, line, 0, NULL, 0) == 0)
retval = true;
- free (line);
+ free(line);
if (retval)
break;
}
- fclose (fp);
- regfree (&re);
+ fclose(fp);
+ regfree(&re);
- return (retval);
+ return retval;
}
#endif
-const char *rc_sys (void)
+const char *rc_sys(void)
{
#ifdef PREFIX
- return (RC_SYS_PREFIX);
+ return RC_SYS_PREFIX;
#else
#ifdef __FreeBSD__
int jailed = 0;
- size_t len = sizeof (jailed);
+ size_t len = sizeof(jailed);
- if (sysctlbyname ("security.jail.jailed", &jailed, &len, NULL, 0) == 0)
+ if (sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0) == 0)
if (jailed == 1)
- return (RC_SYS_JAIL);
+ return RC_SYS_JAIL;
#endif
#ifdef __linux__
- if (exists ("/proc/xen")) {
- if (file_regex ("/proc/xen/capabilities", "control_d"))
- return (RC_SYS_XEN0);
- return (RC_SYS_XENU);
- } else if (file_regex ("/proc/cpuinfo", "UML"))
- return (RC_SYS_UML);
- else if (file_regex ("/proc/self/status",
- "(s_context|VxID):[[:space:]]*[1-9]"))
- return (RC_SYS_VSERVER);
- else if (file_regex ("/proc/self/status",
- "envID:[[:space:]]*[1-9]"))
- return (RC_SYS_OPENVZ);
+ if (exists("/proc/xen")) {
+ if (file_regex("/proc/xen/capabilities", "control_d"))
+ return RC_SYS_XEN0;
+ return RC_SYS_XENU;
+ } else if (file_regex("/proc/cpuinfo", "UML"))
+ return RC_SYS_UML;
+ else if (file_regex("/proc/self/status",
+ "(s_context|VxID):[[:space:]]*[1-9]"))
+ return RC_SYS_VSERVER;
+ else if (file_regex("/proc/self/status",
+ "envID:[[:space:]]*[1-9]"))
+ return RC_SYS_OPENVZ;
#endif
- return (NULL);
+ return NULL;
#endif /* PREFIX */
}
-static const char *rc_parse_service_state (rc_service_state_t state)
+static const char *rc_parse_service_state(RC_SERVICE state)
{
int i;
for (i = 0; rc_service_state_names[i].name; i++) {
if (rc_service_state_names[i].state == state)
- return (rc_service_state_names[i].name);
+ return rc_service_state_names[i].name;
}
- return (NULL);
+ return NULL;
}
-bool rc_runlevel_starting (void)
+bool rc_runlevel_starting(void)
{
- return (exists (RC_STARTING));
+ return exists(RC_STARTING);
}
librc_hidden_def(rc_runlevel_starting)
-bool rc_runlevel_stopping (void)
+bool rc_runlevel_stopping(void)
{
- return (exists (RC_STOPPING));
+ return exists(RC_STOPPING);
}
librc_hidden_def(rc_runlevel_stopping)
-char **rc_runlevel_list (void)
+RC_STRINGLIST *rc_runlevel_list(void)
{
- return (ls_dir (RC_RUNLEVELDIR, LS_DIR));
+ return ls_dir(RC_RUNLEVELDIR, LS_DIR);
}
librc_hidden_def(rc_runlevel_list)
-char *rc_runlevel_get (void)
+char *rc_runlevel_get(void)
{
FILE *fp;
char *runlevel = NULL;
- if ((fp = fopen (SOFTLEVEL, "r"))) {
- runlevel = xmalloc (sizeof (char) * PATH_MAX);
- if (fgets (runlevel, PATH_MAX, fp)) {
- int i = strlen (runlevel) - 1;
+ if ((fp = fopen(SOFTLEVEL, "r"))) {
+ runlevel = xmalloc(sizeof(char) * PATH_MAX);
+ if (fgets(runlevel, PATH_MAX, fp)) {
+ int i = strlen(runlevel) - 1;
if (runlevel[i] == '\n')
runlevel[i] = 0;
} else
*runlevel = '\0';
- fclose (fp);
+ fclose(fp);
}
if (! runlevel || ! *runlevel) {
- free (runlevel);
- runlevel = xstrdup (RC_LEVEL_SYSINIT);
+ free(runlevel);
+ runlevel = xstrdup(RC_LEVEL_SYSINIT);
}
- return (runlevel);
+ return runlevel;
}
librc_hidden_def(rc_runlevel_get)
-bool rc_runlevel_set (const char *runlevel)
+bool rc_runlevel_set(const char *runlevel)
{
- FILE *fp = fopen (SOFTLEVEL, "w");
+ FILE *fp = fopen(SOFTLEVEL, "w");
if (! fp)
- return (false);
- fprintf (fp, "%s", runlevel);
- fclose (fp);
- return (true);
+ return false;
+ fprintf(fp, "%s", runlevel);
+ fclose(fp);
+ return true;
}
librc_hidden_def(rc_runlevel_set)
-bool rc_runlevel_exists (const char *runlevel)
+bool rc_runlevel_exists(const char *runlevel)
{
char *path;
struct stat buf;
bool retval = false;
if (! runlevel)
- return (false);
+ return false;
- path = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
- if (stat (path, &buf) == 0 && S_ISDIR (buf.st_mode))
+ path = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, (char *) NULL);
+ if (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode))
retval = true;
- free (path);
- return (retval);
+ free(path);
+ return retval;
}
librc_hidden_def(rc_runlevel_exists)
- /* Resolve a service name to it's full path */
-char *rc_service_resolve (const char *service)
+/* Resolve a service name to it's full path */
+char *rc_service_resolve(const char *service)
{
char buffer[PATH_MAX];
char *file;
@@ -322,53 +326,53 @@ char *rc_service_resolve (const char *service)
struct stat buf;
if (! service)
- return (NULL);
+ return NULL;
if (service[0] == '/')
- return (xstrdup (service));
+ return xstrdup(service);
/* First check started services */
- file = rc_strcatpaths (RC_SVCDIR, "started", service, (char *) NULL);
- if (lstat (file, &buf) || ! S_ISLNK (buf.st_mode)) {
- free (file);
- file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL);
- if (lstat (file, &buf) || ! S_ISLNK (buf.st_mode)) {
- free (file);
+ file = rc_strcatpaths(RC_SVCDIR, "started", service, (char *) NULL);
+ if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode)) {
+ free(file);
+ file = rc_strcatpaths(RC_SVCDIR, "inactive", service, (char *) NULL);
+ if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode)) {
+ free(file);
file = NULL;
}
}
- memset (buffer, 0, sizeof (buffer));
+ memset(buffer, 0, sizeof(buffer));
/* Nope, so lets see if the user has written it */
#ifdef RC_LOCAL_INITDIR
- snprintf (buffer, sizeof (buffer), RC_LOCAL_INITDIR "/%s", service);
- if (stat (buffer, &buf) == 0)
- return (xstrdup (buffer));
+ snprintf(buffer, sizeof(buffer), RC_LOCAL_INITDIR "/%s", service);
+ if (stat(buffer, &buf) == 0)
+ return xstrdup(buffer);
#endif
if (file) {
- r = readlink (file, buffer, sizeof (buffer));
- free (file);
+ r = readlink(file, buffer, sizeof(buffer));
+ free(file);
if (r > 0)
- return (xstrdup (buffer));
+ return xstrdup(buffer);
}
- snprintf (buffer, sizeof (buffer), RC_INITDIR "/%s", service);
+ snprintf(buffer, sizeof(buffer), RC_INITDIR "/%s", service);
/* So we don't exist in /etc/init.d - check RC_PKG_INITDIR */
#ifdef RC_PKG_INITDIR
- if (stat (buffer, &buf) != 0) {
- snprintf (buffer, sizeof (buffer), RC_PKG_INITDIR "/%s", service);
- if (stat (buffer, &buf) != 0)
- return (NULL);
+ if (stat(buffer, &buf) != 0) {
+ snprintf(buffer, sizeof(buffer), RC_PKG_INITDIR "/%s", service);
+ if (stat(buffer, &buf) != 0)
+ return NULL;
}
#endif
- return (xstrdup (buffer));
+ return xstrdup(buffer);
}
librc_hidden_def(rc_service_resolve)
-bool rc_service_exists (const char *service)
+bool rc_service_exists(const char *service)
{
char *file;
bool retval = false;
@@ -376,59 +380,62 @@ bool rc_service_exists (const char *service)
struct stat buf;
if (! service)
- return (false);
+ return false;
- len = strlen (service);
+ len = strlen(service);
/* .sh files are not init scripts */
if (len > 2 && service[len - 3] == '.' &&
service[len - 2] == 's' &&
service[len - 1] == 'h')
- return (false);
+ return false;
- if (! (file = rc_service_resolve (service)))
- return (false);
+ if (! (file = rc_service_resolve(service)))
+ return false;
- if (stat (file, &buf) == 0 && buf.st_mode & S_IXUGO)
+ if (stat(file, &buf) == 0 && buf.st_mode & S_IXUGO)
retval = true;
- free (file);
- return (retval);
+ free(file);
+ return retval;
}
librc_hidden_def(rc_service_exists)
#define OPTSTR ". '%s'; echo \"${opts}\""
-char **rc_service_extra_commands (const char *service)
+RC_STRINGLIST *rc_service_extra_commands(const char *service)
{
char *svc;
char *cmd = NULL;
char *buffer = NULL;
- char **commands = NULL;
+ RC_STRINGLIST *commands;
char *token;
char *p;
FILE *fp;
size_t l;
- if (! (svc = rc_service_resolve (service)))
- return (NULL);
-
- l = strlen (OPTSTR) + strlen (svc) + 1;
- cmd = xmalloc (sizeof (char) * l);
- snprintf (cmd, l, OPTSTR, svc);
- free (svc);
- if ((fp = popen (cmd, "r"))) {
- p = buffer = rc_getline (fp);
- while ((token = strsep (&p, " ")))
- rc_strlist_addsort (&commands, token);
- pclose (fp);
- free (buffer);
- }
- free (cmd);
- return (commands);
+ if (! (svc = rc_service_resolve(service)))
+ return NULL;
+
+ commands = rc_stringlist_new();
+
+ l = strlen(OPTSTR) + strlen(svc) + 1;
+ cmd = xmalloc(sizeof(char) * l);
+ snprintf(cmd, l, OPTSTR, svc);
+ free(svc);
+
+ if ((fp = popen(cmd, "r"))) {
+ p = buffer = rc_getline(fp);
+ while ((token = strsep(&p, " ")))
+ rc_stringlist_add(commands, token);
+ pclose(fp);
+ free(buffer);
+ }
+ free(cmd);
+ return commands;
}
librc_hidden_def(rc_service_extra_commands)
#define DESCSTR ". '%s'; echo \"${description%s%s}\""
-char *rc_service_description (const char *service, const char *option)
+char *rc_service_description(const char *service, const char *option)
{
char *svc;
char *cmd;
@@ -436,85 +443,90 @@ char *rc_service_description (const char *service, const char *option)
FILE *fp;
size_t l;
- if (! (svc = rc_service_resolve (service)))
- return (NULL);
+ if (! (svc = rc_service_resolve(service)))
+ return NULL;
if (! option)
option = "";
- l = strlen (DESCSTR) + strlen (svc) + strlen (option) + 2;
- cmd = xmalloc (sizeof (char) * l);
- snprintf (cmd, l, DESCSTR, svc, option ? "_" : "", option);
- free (svc);
- if ((fp = popen (cmd, "r"))) {
- desc = rc_getline (fp);
- pclose (fp);
+ l = strlen(DESCSTR) + strlen(svc) + strlen(option) + 2;
+ cmd = xmalloc(sizeof(char) * l);
+ snprintf(cmd, l, DESCSTR, svc, option ? "_" : "", option);
+ free(svc);
+ if ((fp = popen(cmd, "r"))) {
+ desc = rc_getline(fp);
+ pclose(fp);
}
- free (cmd);
- return (desc);
+ free(cmd);
+ return desc;
}
librc_hidden_def(rc_service_description)
-bool rc_service_in_runlevel (const char *service, const char *runlevel)
+bool rc_service_in_runlevel(const char *service, const char *runlevel)
{
char *file;
bool retval;
if (! runlevel || ! service)
- return (false);
+ return false;
- file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename_c (service),
- (char *) NULL);
- retval = exists (file);
- free (file);
+ file = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, basename_c(service),
+ (char *) NULL);
+ retval = exists(file);
+ free(file);
- return (retval);
+ return retval;
}
librc_hidden_def(rc_service_in_runlevel)
-bool rc_service_mark (const char *service, const rc_service_state_t state)
+bool rc_service_mark(const char *service, const RC_SERVICE state)
{
char *file;
int i = 0;
int skip_state = -1;
const char *base;
- char *init = rc_service_resolve (service);
+ char *init = rc_service_resolve(service);
bool skip_wasinactive = false;
+ int s;
+ char *was;
+ RC_STRINGLIST *dirs;
+ RC_STRING *dir;
+ int serrno;
if (! init)
- return (false);
+ return false;
- base = basename_c (service);
+ base = basename_c(service);
if (state != RC_SERVICE_STOPPED) {
- if (! exists (init)) {
- free (init);
- return (false);
+ if (! exists(init)) {
+ free(init);
+ return false;
}
- file = rc_strcatpaths (RC_SVCDIR, rc_parse_service_state (state), base,
- (char *) NULL);
- if (exists (file))
- unlink (file);
- i = symlink (init, file);
- if (i != 0) {
- free (file);
- free (init);
- return (false);
+ file = rc_strcatpaths(RC_SVCDIR, rc_parse_service_state (state), base,
+ (char *) NULL);
+ if (exists(file))
+ unlink(file);
+ i = symlink(init, file);
+ if (i != 0) {
+ free(file);
+ free(init);
+ return false;
}
- free (file);
+ free(file);
skip_state = state;
}
if (state == RC_SERVICE_COLDPLUGGED || state == RC_SERVICE_FAILED) {
- free (init);
- return (true);
+ free(init);
+ return true;
}
/* Remove any old states now */
for (i = 0; rc_service_state_names[i].name; i++) {
- int s = rc_service_state_names[i].state;
+ s = rc_service_state_names[i].state;
if ((s != skip_state &&
s != RC_SERVICE_STOPPED &&
@@ -522,24 +534,24 @@ bool rc_service_mark (const char *service, const rc_service_state_t state)
s != RC_SERVICE_SCHEDULED) &&
(! skip_wasinactive || s != RC_SERVICE_WASINACTIVE))
{
- file = rc_strcatpaths (RC_SVCDIR, rc_parse_service_state (s), base,
- (char *) NULL);
- if (exists (file)) {
+ file = rc_strcatpaths(RC_SVCDIR, rc_parse_service_state(s), base,
+ (char *) NULL);
+ if (exists(file)) {
if ((state == RC_SERVICE_STARTING ||
state == RC_SERVICE_STOPPING) &&
s == RC_SERVICE_INACTIVE)
{
- char *wasfile = rc_strcatpaths (RC_SVCDIR,
- rc_parse_service_state (RC_SERVICE_WASINACTIVE),
- base, (char *) NULL);
+ was = rc_strcatpaths(RC_SVCDIR,
+ rc_parse_service_state(RC_SERVICE_WASINACTIVE),
+ base, (char *) NULL);
- symlink (init, wasfile);
+ symlink(init, was);
skip_wasinactive = true;
- free (wasfile);
+ free(was);
}
- unlink (file);
+ unlink(file);
}
- free (file);
+ free(file);
}
}
@@ -548,126 +560,133 @@ bool rc_service_mark (const char *service, const rc_service_state_t state)
state == RC_SERVICE_STOPPED ||
state == RC_SERVICE_INACTIVE)
{
- file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL);
- unlink (file);
- free (file);
+ file = rc_strcatpaths(RC_SVCDIR, "exclusive", base, (char *) NULL);
+ unlink(file);
+ free(file);
}
/* Remove any options and daemons the service may have stored */
if (state == RC_SERVICE_STOPPED) {
- char *dir = rc_strcatpaths (RC_SVCDIR, "options", base, (char *) NULL);
- rm_dir (dir, true);
- free (dir);
+ file = rc_strcatpaths(RC_SVCDIR, "options", base, (char *) NULL);
+ rm_dir(file, true);
+ free(file);
- dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL);
- rm_dir (dir, true);
- free (dir);
+ file = rc_strcatpaths(RC_SVCDIR, "daemons", base, (char *) NULL);
+ rm_dir(file, true);
+ free(file);
- rc_service_schedule_clear (service);
+ rc_service_schedule_clear(service);
}
/* 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 = ls_dir (sdir, 0);
- char *dir;
- int serrno;
+ file = rc_strcatpaths(RC_SVCDIR, "scheduled", (char *) NULL);
+ dirs = ls_dir(file, 0);
- STRLIST_FOREACH (dirs, dir, i) {
- char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL);
- file = rc_strcatpaths (bdir, base, (char *) NULL);
- unlink (file);
- free (file);
+ TAILQ_FOREACH(dir, dirs, entries) {
+ was = rc_strcatpaths(file, dir->value, base, (char *) NULL);
+ unlink(was);
+ free(was);
/* Try and remove the dir - we don't care about errors */
+ was = rc_strcatpaths(file, dir->value, (char *) NULL);
serrno = errno;
- rmdir (bdir);
+ rmdir(was);
errno = serrno;
- free (bdir);
+ free(was);
}
- rc_strlist_free (dirs);
- free (sdir);
+ rc_stringlist_free(dirs);
}
- free (init);
- return (true);
+ free(init);
+ return true;
}
librc_hidden_def(rc_service_mark)
-rc_service_state_t rc_service_state (const char *service)
+RC_SERVICE rc_service_state(const char *service)
{
int i;
int state = RC_SERVICE_STOPPED;
+ char *file;
+ RC_STRINGLIST *dirs;
+ RC_STRING *dir;
for (i = 0; rc_service_state_names[i].name; i++) {
- char *file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i].name,
- basename_c (service), (char*) NULL);
- if (exists (file)) {
+ file = rc_strcatpaths(RC_SVCDIR, rc_service_state_names[i].name,
+ basename_c(service), (char*) NULL);
+ if (exists(file)) {
if (rc_service_state_names[i].state <= 0x10)
state = rc_service_state_names[i].state;
else
state |= rc_service_state_names[i].state;
}
- free (file);
+ free(file);
}
if (state & RC_SERVICE_STOPPED) {
- char **services = rc_services_scheduled_by (service);
- if (services) {
- state |= RC_SERVICE_SCHEDULED;
- free (services);
+ dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
+ TAILQ_FOREACH (dir, dirs, entries) {
+ file = rc_strcatpaths(RC_SVCDIR, "scheduled",
+ dir->value,
+ service, (char *) NULL);
+ if (exists(file))
+ state |= RC_SERVICE_SCHEDULED;
+ free(file);
+ if (state & RC_SERVICE_SCHEDULED)
+ break;
}
+ rc_stringlist_free(dirs);
}
- return (state);
+ return state;
}
librc_hidden_def(rc_service_state)
-char *rc_service_value_get (const char *service, const char *option)
+char *rc_service_value_get(const char *service, const char *option)
{
FILE *fp;
char *line = NULL;
- char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option,
- (char *) NULL);
+ char *file = rc_strcatpaths(RC_SVCDIR, "options", service, option,
+ (char *) NULL);
- if ((fp = fopen (file, "r"))) {
- line = rc_getline (fp);
- fclose (fp);
+ if ((fp = fopen(file, "r"))) {
+ line = rc_getline(fp);
+ fclose(fp);
}
- free (file);
+ free(file);
- return (line);
+ return line;
}
librc_hidden_def(rc_service_value_get)
-bool rc_service_value_set (const char *service, const char *option,
- const char *value)
+bool rc_service_value_set(const char *service, const char *option,
+ const char *value)
{
FILE *fp;
- char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL);
- char *file = rc_strcatpaths (path, option, (char *) NULL);
+ char *path = rc_strcatpaths(RC_SVCDIR, "options", service, (char *) NULL);
+ char *file = rc_strcatpaths(path, option, (char *) NULL);
bool retval = false;
- if (mkdir (path, 0755) != 0 && errno != EEXIST) {
- free (path);
- free (file);
- return (false);
+ if (mkdir(path, 0755) != 0 && errno != EEXIST) {
+ free(path);
+ free(file);
+ return false;
}
- if ((fp = fopen (file, "w"))) {
+ if ((fp = fopen(file, "w"))) {
if (value)
- fprintf (fp, "%s", value);
- fclose (fp);
+ fprintf(fp, "%s", value);
+ fclose(fp);
retval = true;
}
- free (path);
- free (file);
- return (retval);
+ free(path);
+ free(file);
+ return retval;
}
librc_hidden_def(rc_service_value_set)
-static pid_t _exec_service (const char *service, const char *arg)
+static pid_t _exec_service(const char *service, const char *arg)
{
char *file;
char *fifo;
@@ -676,92 +695,92 @@ static pid_t _exec_service (const char *service, const char *arg)
sigset_t old;
struct sigaction sa;
- file = rc_service_resolve (service);
- if (! exists (file)) {
- rc_service_mark (service, RC_SERVICE_STOPPED);
- free (file);
- return (0);
+ file = rc_service_resolve(service);
+ if (! exists(file)) {
+ rc_service_mark(service, RC_SERVICE_STOPPED);
+ free(file);
+ return 0;
}
/* We create a fifo so that other services can wait until we complete */
- fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename_c (service),
- (char *) NULL);
+ fifo = rc_strcatpaths(RC_SVCDIR, "exclusive", basename_c(service),
+ (char *) NULL);
- if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) {
- free (fifo);
- free (file);
- return (-1);
+ if (mkfifo(fifo, 0600) != 0 && errno != EEXIST) {
+ free(fifo);
+ free(file);
+ return -1;
}
/* We need to block signals until we have forked */
- memset (&sa, 0, sizeof (sa));
+ memset(&sa, 0, sizeof (sa));
sa.sa_handler = SIG_DFL;
- sigemptyset (&sa.sa_mask);
- sigfillset (&full);
- sigprocmask (SIG_SETMASK, &full, &old);
+ sigemptyset(&sa.sa_mask);
+ sigfillset(&full);
+ sigprocmask(SIG_SETMASK, &full, &old);
- if ((pid = fork ()) == 0) {
+ if ((pid = fork()) == 0) {
/* Restore default handlers */
- sigaction (SIGCHLD, &sa, NULL);
- sigaction (SIGHUP, &sa, NULL);
- sigaction (SIGINT, &sa, NULL);
- sigaction (SIGQUIT, &sa, NULL);
- sigaction (SIGTERM, &sa, NULL);
- sigaction (SIGUSR1, &sa, NULL);
- sigaction (SIGWINCH, &sa, NULL);
+ sigaction(SIGCHLD, &sa, NULL);
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGQUIT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGUSR1, &sa, NULL);
+ sigaction(SIGWINCH, &sa, NULL);
/* Unmask signals */
- sigprocmask (SIG_SETMASK, &old, NULL);
+ sigprocmask(SIG_SETMASK, &old, NULL);
/* Safe to run now */
- execl (file, file, arg, (char *) NULL);
- fprintf (stderr, "unable to exec `%s': %s\n",
- file, strerror (errno));
- unlink (fifo);
- _exit (EXIT_FAILURE);
+ execl(file, file, arg, (char *) NULL);
+ fprintf(stderr, "unable to exec `%s': %s\n",
+ file, strerror(errno));
+ unlink(fifo);
+ _exit(EXIT_FAILURE);
}
if (pid == -1)
- fprintf (stderr, "fork: %s\n", strerror (errno));
+ fprintf(stderr, "fork: %s\n",strerror (errno));
- sigprocmask (SIG_SETMASK, &old, NULL);
+ sigprocmask(SIG_SETMASK, &old, NULL);
- free (fifo);
- free (file);
+ free(fifo);
+ free(file);
- return (pid);
+ return pid;
}
-pid_t rc_service_stop (const char *service)
+pid_t rc_service_stop(const char *service)
{
- rc_service_state_t state = rc_service_state (service);
+ RC_SERVICE state = rc_service_state(service);
if (state & RC_SERVICE_FAILED)
- return (-1);
+ return -1;
if (state & RC_SERVICE_STOPPED)
- return (0);
+ return 0;
- return (_exec_service (service, "stop"));
+ return _exec_service(service, "stop");
}
librc_hidden_def(rc_service_stop)
-pid_t rc_service_start (const char *service)
+pid_t rc_service_start(const char *service)
{
- rc_service_state_t state = rc_service_state (service);
+ RC_SERVICE state = rc_service_state(service);
if (state & RC_SERVICE_FAILED)
- return (-1);
+ return -1;
if (! state & RC_SERVICE_STOPPED)
- return (0);
+ return 0;
- return (_exec_service (service, "start"));
+ return _exec_service(service, "start");
}
librc_hidden_def(rc_service_start)
-bool rc_service_schedule_start (const char *service,
- const char *service_to_start)
+bool rc_service_schedule_start(const char *service,
+ const char *service_to_start)
{
char *dir;
char *init;
@@ -769,162 +788,156 @@ bool rc_service_schedule_start (const char *service,
bool retval;
/* service may be a provided service, like net */
- if (! service || ! rc_service_exists (service_to_start))
- return (false);
+ if (! service || ! rc_service_exists(service_to_start))
+ return false;
- dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename_c (service),
- (char *) NULL);
- if (mkdir (dir, 0755) != 0 && errno != EEXIST) {
- free (dir);
- return (false);
+ dir = rc_strcatpaths(RC_SVCDIR, "scheduled", basename_c(service),
+ (char *) NULL);
+ if (mkdir(dir, 0755) != 0 && errno != EEXIST) {
+ free(dir);
+ return false;
}
- init = rc_service_resolve (service_to_start);
- file = rc_strcatpaths (dir, basename_c (service_to_start), (char *) NULL);
- retval = (exists (file) || symlink (init, file) == 0);
- free (init);
- free (file);
- free (dir);
+ init = rc_service_resolve(service_to_start);
+ file = rc_strcatpaths(dir, basename_c(service_to_start), (char *) NULL);
+ retval = (exists(file) || symlink(init, file) == 0);
+ free(init);
+ free(file);
+ free(dir);
- return (retval);
+ return retval;
}
librc_hidden_def(rc_service_schedule_start)
-bool rc_service_schedule_clear (const char *service)
+bool rc_service_schedule_clear(const char *service)
{
- char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename_c (service),
- (char *) NULL);
+ char *dir = rc_strcatpaths(RC_SVCDIR, "scheduled", basename_c(service),
+ (char *) NULL);
bool retval;
- if (! (retval = rm_dir (dir, true)) && errno == ENOENT)
+ if (! (retval = rm_dir(dir, true)) && errno == ENOENT)
retval = true;
- free (dir);
- return (retval);
+ free(dir);
+ return retval;
}
librc_hidden_def(rc_service_schedule_clear)
-
-char **rc_services_in_runlevel (const char *runlevel)
+RC_STRINGLIST *rc_services_in_runlevel(const char *runlevel)
{
char *dir;
- char **list = NULL;
+ RC_STRINGLIST *list;
if (! runlevel) {
-#if defined(RC_PKG_INITDIR) || defined(RC_LOCAL_INITDIR)
- int i;
-#endif
#ifdef RC_PKG_INITDIR
- char **pkg = ls_dir (RC_PKG_INITDIR, LS_INITD);
+ RC_STRINGLIST *pkg = ls_dir(RC_PKG_INITDIR, LS_INITD);
#endif
#ifdef RC_LOCAL_INITDIR
- char **local = ls_dir (RC_LOCAL_INITDIR, LS_INITD);
+ RC_STRINGLIST *local = ls_dir(RC_LOCAL_INITDIR, LS_INITD);
#endif
- list = ls_dir (RC_INITDIR, LS_INITD);
+ list = ls_dir(RC_INITDIR, LS_INITD);
#ifdef RC_PKG_INITDIR
- STRLIST_FOREACH (pkg, dir, i)
- rc_strlist_addsortu (&list, dir);
- rc_strlist_free (pkg);
+ if (pkg) {
+ TAILQ_CONCAT(list, pkg);
+ free(pkg);
+ }
#endif
#ifdef RC_LOCAL_DIR
- STRLIST_FOREACH (local, dir, i)
- rc_strlist_addsortu (&list, dir);
- rc_strlist_free (local);
+ if (local) {
+ TAILQ_CONCAT(list, local);
+ free(local);
+ }
#endif
- return (list);
+ return list;
}
/* These special levels never contain any services */
- if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 ||
- strcmp (runlevel, RC_LEVEL_SINGLE) == 0)
- return (NULL);
-
- dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
- list = ls_dir (dir, LS_INITD);
- free (dir);
- return (list);
+ if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0 ||
+ strcmp(runlevel, RC_LEVEL_SINGLE) == 0) {
+ list = rc_stringlist_new();
+ return list;
+ }
+
+ dir = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, (char *) NULL);
+ list = ls_dir(dir, LS_INITD);
+ free(dir);
+ return list;
}
librc_hidden_def(rc_services_in_runlevel)
-char **rc_services_in_state (rc_service_state_t state)
+RC_STRINGLIST *rc_services_in_state(RC_SERVICE state)
{
- char *dir = rc_strcatpaths (RC_SVCDIR, rc_parse_service_state (state),
- (char *) NULL);
- char **list = NULL;
+ char *dir = rc_strcatpaths(RC_SVCDIR, rc_parse_service_state(state),
+ (char *) NULL);
+ RC_STRINGLIST *services;
+ RC_STRINGLIST *list;
+ RC_STRINGLIST *dirs;
+ RC_STRING *d;
+ char *p;
if (state == RC_SERVICE_SCHEDULED) {
- 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 = ls_dir (p, LS_INITD);
- char *e;
- int j;
-
- STRLIST_FOREACH (entries, e, j)
- rc_strlist_addsortu (&list, e);
-
- if (entries)
- free (entries);
+ dirs = ls_dir(dir, 0);
+ list = rc_stringlist_new();
+ TAILQ_FOREACH(d, dirs, entries) {
+ p = rc_strcatpaths(dir, d->value, (char *) NULL);
+ services = ls_dir(p, LS_INITD);
+ free(p);
+ TAILQ_CONCAT(list, services);
+ free(services);
}
-
- if (dirs)
- free (dirs);
+ rc_stringlist_free(dirs);
} else {
- list = ls_dir (dir, LS_INITD);
+ list = ls_dir(dir, LS_INITD);
}
- free (dir);
- return (list);
+ free(dir);
+ return list;
}
librc_hidden_def(rc_services_in_state)
-bool rc_service_add (const char *runlevel, const char *service)
+bool rc_service_add(const char *runlevel, const char *service)
{
bool retval;
char *init;
char *file;
+ char path[MAXPATHLEN] = { '\0' };
+ char *p;
- if (! rc_runlevel_exists (runlevel)) {
+ if (! rc_runlevel_exists(runlevel)) {
errno = ENOENT;
- return (false);
+ return false;
}
- if (rc_service_in_runlevel (service, runlevel)) {
+ if (rc_service_in_runlevel(service, runlevel)) {
errno = EEXIST;
- return (false);
+ return false;
}
- init = rc_service_resolve (service);
+ init = rc_service_resolve(service);
/* We need to ensure that only things in /etc/init.d are added
* to the boot runlevel */
if (strcmp (runlevel, RC_LEVEL_BOOT) == 0) {
- char tmp[MAXPATHLEN] = { '\0' };
- char *p;
-
- p = realpath (dirname (init), tmp);
- free (init);
+ p = realpath(dirname (init), path);
+ free(init);
if (! *p)
- return (false);
+ return false;
- retval = (strcmp (tmp, RC_INITDIR) == 0);
+ retval = (strcmp(path, RC_INITDIR) == 0);
if (! retval) {
errno = EPERM;
- return (false);
+ return false;
}
- init = rc_strcatpaths (RC_INITDIR, service, (char *) NULL);
+ init = rc_strcatpaths(RC_INITDIR, service, (char *) NULL);
}
- file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename_c (service),
- (char *) NULL);
- retval = (symlink (init, file) == 0);
- free (init);
- free (file);
- return (retval);
+ file = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, basename_c(service),
+ (char *) NULL);
+ retval = (symlink(init, file) == 0);
+ free(init);
+ free(file);
+ return retval;
}
librc_hidden_def(rc_service_add)
@@ -934,46 +947,46 @@ bool rc_service_delete (const char *runlevel, const char *service)
bool retval = false;
if (! runlevel || ! service)
- return (false);
+ return false;
- file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename_c (service),
+ file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename_c(service),
(char *) NULL);
- if (unlink (file) == 0)
+ if (unlink(file) == 0)
retval = true;
- free (file);
- return (retval);
+ free(file);
+ return retval;
}
librc_hidden_def(rc_service_delete)
-char **rc_services_scheduled_by (const char *service)
+RC_STRINGLIST *rc_services_scheduled_by(const char *service)
{
- char **dirs = ls_dir (RC_SVCDIR "/scheduled", 0);
- char **list = NULL;
- char *dir;
- int i;
+ RC_STRINGLIST *dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
+ RC_STRINGLIST *list;
+ RC_STRING *dir;
+ char *file;
- STRLIST_FOREACH (dirs, dir, i) {
- char *file = rc_strcatpaths (RC_SVCDIR, "scheduled", dir, service,
- (char *) NULL);
- if (exists (file))
- rc_strlist_add (&list, file);
- free (file);
+ list = rc_stringlist_new();
+ TAILQ_FOREACH (dir, dirs, entries) {
+ file = rc_strcatpaths(RC_SVCDIR, "scheduled", dir->value,
+ service, (char *) NULL);
+ if (exists(file))
+ rc_stringlist_add(list, file);
+ free(file);
}
- rc_strlist_free (dirs);
+ rc_stringlist_free(dirs);
- return (list);
+ return list;
}
librc_hidden_def(rc_services_scheduled_by)
-char **rc_services_scheduled (const char *service)
+RC_STRINGLIST *rc_services_scheduled(const char *service)
{
- char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename_c (service),
- (char *) NULL);
- char **list = NULL;
+ char *dir = rc_strcatpaths(RC_SVCDIR, "scheduled", basename_c(service),
+ (char *) NULL);
+ RC_STRINGLIST *list = ls_dir(dir, LS_INITD);
- list = ls_dir (dir, LS_INITD);
- free (dir);
- return (list);
+ free(dir);
+ return list;
}
librc_hidden_def(rc_services_scheduled)
diff --git a/src/librc/librc.h b/src/librc/librc.h
index edbebaf..aaad7cc 100644
--- a/src/librc/librc.h
+++ b/src/librc/librc.h
@@ -64,10 +64,8 @@
#include <kvm.h>
#endif
-#include "librc-depend.h"
#include "rc.h"
#include "rc-misc.h"
-#include "strlist.h"
#include "hidden-visibility.h"
#define librc_hidden_proto(x) hidden_proto(x)
@@ -115,15 +113,11 @@ librc_hidden_proto(rc_service_state)
librc_hidden_proto(rc_service_value_get)
librc_hidden_proto(rc_service_value_set)
librc_hidden_proto(rc_strcatpaths)
-librc_hidden_proto(rc_strlist_add)
-librc_hidden_proto(rc_strlist_addu)
-librc_hidden_proto(rc_strlist_addsort)
-librc_hidden_proto(rc_strlist_addsortc)
-librc_hidden_proto(rc_strlist_addsortu)
-librc_hidden_proto(rc_strlist_delete)
-librc_hidden_proto(rc_strlist_free)
-librc_hidden_proto(rc_strlist_join)
-librc_hidden_proto(rc_strlist_reverse)
+librc_hidden_proto(rc_stringlist_add)
+librc_hidden_proto(rc_stringlist_addu)
+librc_hidden_proto(rc_stringlist_delete)
+librc_hidden_proto(rc_stringlist_free)
+librc_hidden_proto(rc_stringlist_sort)
librc_hidden_proto(rc_yesno)
#endif
diff --git a/src/librc/rc.h b/src/librc/rc.h
index 0b811f4..061959e 100644
--- a/src/librc/rc.h
+++ b/src/librc/rc.h
@@ -32,15 +32,24 @@
# if (GCC_VERSION >= 3005)
# define SENTINEL __attribute__ ((__sentinel__))
# endif
+# define DEPRECATED __attribute__ ((deprecated))
#endif
#ifndef SENTINEL
# define SENTINEL
#endif
#include <sys/types.h>
+#include <sys/queue.h>
#include <stdbool.h>
#include <stdio.h>
+/* A doubly linked list using queue(3) for ease of use */
+typedef struct rc_string {
+ char *value;
+ TAILQ_ENTRY(rc_string) entries;
+} RC_STRING;
+typedef TAILQ_HEAD(rc_stringlist, rc_string) RC_STRINGLIST;
+
/*! @name Reserved runlevel names */
#define RC_LEVEL_SYSINIT "sysinit"
#define RC_LEVEL_SINGLE "single"
@@ -49,30 +58,30 @@
/*! Return the current runlevel.
* @return the current runlevel */
-char *rc_runlevel_get (void);
+char *rc_runlevel_get(void);
/*! Checks if the runlevel exists or not
* @param runlevel to check
* @return true if the runlevel exists, otherwise false */
-bool rc_runlevel_exists (const char *runlevel);
+bool rc_runlevel_exists(const char *);
/*! Return a NULL terminated list of runlevels
* @return a NULL terminated list of runlevels */
-char **rc_runlevel_list (void);
+RC_STRINGLIST *rc_runlevel_list(void);
/*! Set the runlevel.
* This just changes the stored runlevel and does not start or stop any
* services.
* @param runlevel to store */
-bool rc_runlevel_set (const char *runlevel);
+bool rc_runlevel_set(const char *);
/*! Is the runlevel starting?
* @return true if yes, otherwise false */
-bool rc_runlevel_starting (void);
+bool rc_runlevel_starting(void);
/*! Is the runlevel stopping?
* @return true if yes, otherwise false */
-bool rc_runlevel_stopping (void);
+bool rc_runlevel_stopping(void);
/*! @name RC
* A service can be given as a full path or just its name.
@@ -97,19 +106,19 @@ typedef enum
RC_SERVICE_FAILED = 0x0200,
RC_SERVICE_SCHEDULED = 0x0400,
RC_SERVICE_WASINACTIVE = 0x0800
-} rc_service_state_t;
+} RC_SERVICE;
/*! Add the service to the runlevel
* @param runlevel to add to
* @param service to add
* @return true if successful, otherwise false */
-bool rc_service_add (const char *runlevel, const char *service);
+bool rc_service_add(const char *, const char *);
/*! Remove the service from the runlevel
* @param runlevel to remove from
* @param service to remove
* @return true if sucessful, otherwise false */
-bool rc_service_delete (const char *runlevel, const char *service);
+bool rc_service_delete(const char *, const char *);
/*! Save the arguments to find a running daemon
* @param service to save arguments for
@@ -117,116 +126,113 @@ bool rc_service_delete (const char *runlevel, const char *service);
* @param name of the process (optional)
* @param pidfile of the process (optional)
* @param started if true, add the arguments otherwise remove existing matching arguments */
-bool rc_service_daemon_set (const char *service, const char *const *argv,
- const char *name, const char *pidfile,
- bool started);
+bool rc_service_daemon_set(const char *, const char *const *, const char *, const char *,
+ bool);
/*! Returns a description of what the service and/or option does.
* @param service to check
* @param option to check (if NULL, service description)
* @return a newly allocated pointer to the description */
-char *rc_service_description (const char *service, const char *option);
+char *rc_service_description(const char *, const char *);
/*! Checks if a service exists or not.
* @param service to check
* @return true if service exists, otherwise false */
-bool rc_service_exists (const char *service);
+bool rc_service_exists(const char *);
/*! Checks if a service is in a runlevel
* @param service to check
* @param runlevel it should be in
* @return true if service is in the runlevel, otherwise false */
-bool rc_service_in_runlevel (const char *service, const char *runlevel);
+bool rc_service_in_runlevel(const char *, const char *);
/*! Marks the service state
* @param service to mark
* @param state service should be in
* @return true if service state change was successful, otherwise false */
-bool rc_service_mark (const char *service, rc_service_state_t state);
+bool rc_service_mark(const char *, RC_SERVICE);
/*! Lists the extra commands a service has
* @param service to load the commands from
* @return NULL terminated string list of commands */
-char **rc_service_extra_commands (const char *service);
+RC_STRINGLIST *rc_service_extra_commands(const char *);
/*! Resolves a service name to its full path.
* @param service to check
* @return pointer to full path of service */
-char *rc_service_resolve (const char *service);
+char *rc_service_resolve(const char *);
/*! Schedule a service to be started when another service starts
* @param service that starts the scheduled service when started
* @param service_to_start service that will be started */
-bool rc_service_schedule_start (const char *service,
- const char *service_to_start);
+bool rc_service_schedule_start(const char *, const char *);
+
/*! Return a NULL terminated list of services that are scheduled to start
* when the given service has started
* @param service to check
* @return NULL terminated list of services scheduled to start */
-char **rc_services_scheduled_by (const char *service);
+RC_STRINGLIST *rc_services_scheduled_by(const char *);
/*! Clear the list of services scheduled to be started by this service
* @param service to clear
* @return true if no errors, otherwise false */
-bool rc_service_schedule_clear (const char *service);
+bool rc_service_schedule_clear(const char *);
/*! Checks if a service in in a state
* @param service to check
* @return state of the service */
-rc_service_state_t rc_service_state (const char *service);
+RC_SERVICE rc_service_state(const char *);
/*! Start a service
* @param service to start
* @return pid of the service starting process */
-pid_t rc_service_start (const char *service);
+pid_t rc_service_start(const char *);
/*! Stop a service
* @param service to stop
* @return pid of service stopping process */
-pid_t rc_service_stop (const char *service);
+pid_t rc_service_stop(const char *);
/*! Check if the service started the daemon
* @param service to check
* @param exec to check
* @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc)
* @return true if started by this service, otherwise false */
-bool rc_service_started_daemon (const char *service, const char *const *argv,
- int indx);
+bool rc_service_started_daemon(const char *, const char *const *, int);
/*! Return a saved value for a service
* @param service to check
* @param option to load
* @return saved value */
-char *rc_service_value_get (const char *service, const char *option);
+char *rc_service_value_get(const char *, const char *);
/*! Save a persistent value for a service
* @param service to save for
* @param option to save
* @param value of the option
* @return true if saved, otherwise false */
-bool rc_service_value_set (const char *service, const char *option,
- const char *value);
+bool rc_service_value_set(const char *, const char *, const char *);
/*! List the services in a runlevel
* @param runlevel to list
* @return NULL terminated list of services */
-char **rc_services_in_runlevel (const char *runlevel);
+RC_STRINGLIST *rc_services_in_runlevel(const char *);
/*! List the services in a state
* @param state to list
* @return NULL terminated list of services */
-char **rc_services_in_state (rc_service_state_t state);
+RC_STRINGLIST *rc_services_in_state(RC_SERVICE);
/*! List the services shceduled to start when this one does
* @param service to check
* @return NULL terminated list of services */
-char **rc_services_scheduled (const char *service);
+RC_STRINGLIST *rc_services_scheduled(const char *);
/*! Checks that all daemons started with start-stop-daemon by the service
* are still running.
* @param service to check
* @return true if all daemons started are still running, otherwise false */
-bool rc_service_daemons_crashed (const char *service);
+bool rc_service_daemons_crashed(const char *);
/*! @name System types
* OpenRC can support some special sub system types, normally virtualization.
@@ -238,7 +244,7 @@ bool rc_service_daemons_crashed (const char *service);
#define RC_SYS_VSERVER "VSERVER"
#define RC_SYS_XEN0 "XEN0"
#define RC_SYS_XENU "XENU"
-const char *rc_sys (void);
+const char *rc_sys(void);
/*! @name Dependency options
* These options can change the services found by the rc_get_depinfo and
@@ -256,40 +262,67 @@ const char *rc_sys (void);
* We analyse each init script and cache the resultant dependency tree.
* This tree can be accessed using the below functions. */
-#ifndef _IN_LIBRC
+#ifdef _IN_LIBRC
+/*! @name Dependency structures
+ * private to librc */
+
+/*! Singly linked list of dependency types that list the services the
+ * type is for */
+typedef struct rc_deptype
+{
+ /*! ineed, iuse, iafter, etc */
+ char *type;
+ /*! list of services */
+ RC_STRINGLIST *services;
+ /*! list of types */
+ STAILQ_ENTRY(rc_deptype) entries;
+} RC_DEPTYPE;
+
+/*! Singly linked list of services and their dependencies */
+typedef struct rc_depinfo
+{
+ /*! Name of service */
+ char *service;
+ /*! Dependencies */
+ STAILQ_HEAD(, rc_deptype) depends;
+ /*! List of entries */
+ STAILQ_ENTRY(rc_depinfo) entries;
+} RC_DEPINFO;
+
+typedef STAILQ_HEAD(,rc_depinfo) RC_DEPTREE;
+#else
/* Handles to internal structures */
-typedef void *rc_depinfo_t;
+typedef void *RC_DEPTREE;
#endif
/*! Check to see if source is newer than target.
* If target is a directory then we traverse it and it's children.
* @return true if source is newer than target, otherwise false */
-bool rc_newer_than (const char *source, const char *target);
+bool rc_newer_than(const char *, const char *);
/*! Update the cached dependency tree if it's older than any init script,
* its configuration file or an external configuration file the init script
* has specified.
* @return true if successful, otherwise false */
-bool rc_deptree_update (void);
+bool rc_deptree_update(void);
/*! Check if the cached dependency tree is older than any init script,
* its configuration file or an external configuration file the init script
* has specified.
* @return true if it needs updating, otherwise false */
-bool rc_deptree_update_needed (void);
+bool rc_deptree_update_needed(void);
/*! Load the cached dependency tree and return a pointer to it.
* This pointer should be freed with rc_deptree_free when done.
* @return pointer to the dependency tree */
-rc_depinfo_t *rc_deptree_load (void);
+RC_DEPTREE *rc_deptree_load(void);
/*! List the depend for the type of service
* @param deptree to search
* @param type to use (keywords, etc)
* @param service to check
* @return NULL terminated list of services in order */
-char **rc_deptree_depend (const rc_depinfo_t *deptree,
- const char *type, const char *service);
+RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *, const char *, const char *);
/*! List all the services in order that the given services have
* for the given types and options.
@@ -298,10 +331,8 @@ char **rc_deptree_depend (const rc_depinfo_t *deptree,
* @param services to check
* @param options to pass
* @return NULL terminated list of services in order */
-char **rc_deptree_depends (const rc_depinfo_t *deptree,
- const char *const *types,
- const char *const *services, const char *runlevel,
- int options);
+RC_STRINGLIST *rc_deptree_depends(const RC_DEPTREE *, const RC_STRINGLIST *,
+ const RC_STRINGLIST *, const char *, int);
/*! List all the services that should be stoppned and then started, in order,
* for the given runlevel, including sysinit and boot services where
@@ -310,12 +341,11 @@ char **rc_deptree_depends (const rc_depinfo_t *deptree,
* @param runlevel to change into
* @param options to pass
* @return NULL terminated list of services in order */
-char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel,
- int options);
+RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *, const char *, int);
/*! Free a deptree and its information
* @param deptree to free */
-void rc_deptree_free (rc_depinfo_t *deptree);
+void rc_deptree_free(RC_DEPTREE *);
/*! @name Plugins
* For each plugin loaded we will call rc_plugin_hook with the below
@@ -347,13 +377,13 @@ typedef enum
RC_HOOK_SERVICE_START_NOW = 106,
RC_HOOK_SERVICE_START_DONE = 107,
RC_HOOK_SERVICE_START_OUT = 108
-} rc_hook_t;
+} RC_HOOK;
/*! Plugin entry point
* @param hook point
* @param name of runlevel or service
* @return 0 for success otherwise -1 */
-int rc_plugin_hook (rc_hook_t hook, const char *name);
+int rc_plugin_hook(RC_HOOK, const char *);
/*! Plugins should write FOO=BAR to this fd to set any environment
* variables they wish. Variables should be separated by NULLs. */
@@ -362,91 +392,64 @@ extern FILE *rc_environ_fd;
/*! @name Configuration
* These functions help to deal with shell based configuration files */
/*! Return a line from a file, stripping the trailing newline. */
-char *rc_getline (FILE *fp);
+char *rc_getline(FILE *);
/*! Return a NULL terminated list of non comment lines from a file. */
-char **rc_config_list (const char *file);
+RC_STRINGLIST *rc_config_list(const char *);
/*! Return a NULL terminated list of key=value lines from a file. */
-char **rc_config_load (const char *file);
+RC_STRINGLIST *rc_config_load(const char *);
/*! Return the value of the entry from a key=value list. */
-char *rc_config_value (const char *const *list, const char *entry);
+char *rc_config_value(RC_STRINGLIST *, const char *);
/*! Check if a variable is a boolean and return it's value.
* If variable is not a boolean then we set errno to be ENOENT when it does
* not exist or EINVAL if it's not a boolean.
* @param variable to check
* @return true if it matches true, yes or 1, false if otherwise. */
-bool rc_yesno (const char *variable);
+bool rc_yesno(const char *);
/*! @name String List functions
- * Handy functions for dealing with string arrays of char **.
- * It's safe to assume that any function here that uses char ** is a string
- * list that can be manipulated with the below functions. Every string list
- * should be released with a call to rc_strlist_free. */
+ * Every string list should be released with a call to rc_stringlist_free. */
+
+/*! Create a new stringlinst
+ * @return pointer to new list */
+RC_STRINGLIST *rc_stringlist_new(void);
/*! Duplicate the item, add it to end of the list and return a pointer to it.
* @param list to add the item too
* @param item to add.
* @return pointer to newly added item */
-char *rc_strlist_add (char ***list, const char *item);
+RC_STRING *rc_stringlist_add(RC_STRINGLIST *, const char *);
/*! If the item does not exist in the list, duplicate it, add it to the
* list and then return a pointer to it.
* @param list to add the item too
* @param item to add.
* @return pointer to newly added item */
-char *rc_strlist_addu (char ***list, const char *item);
-
-/*! Duplicate the item, add it to the list at the point based on locale and
- * then return a pointer to it.
- * @param list to add the item too
- * @param item to add.
- * @return pointer to newly added item */
-char *rc_strlist_addsort (char ***list, const char *item);
-
-/*! Duplicate the item, add it to the list at the point based on C locale and
- * then return a pointer to it.
- * @param list to add the item too
- * @param item to add.
- * @return pointer to newly added item */
-char *rc_strlist_addsortc (char ***list, const char *item);
-
-/*! If the item does not exist in the list, duplicate it, add it to the
- * list based on locale and then return a pointer to it.
- * @param list to add the item too
- * @param item to add.
- * @return pointer to newly added item */
-char *rc_strlist_addsortu (char ***list, const char *item);
+RC_STRING *rc_stringlist_addu(RC_STRINGLIST *, const char *);
/*! Free the item and remove it from the list. Return 0 on success otherwise -1.
* @param list to add the item too
* @param item to add.
* @return true on success, otherwise false */
-bool rc_strlist_delete (char ***list, const char *item);
-
-/*! Moves the contents of list2 onto list1, so list2 is effectively emptied.
- * Returns a pointer to the last item on the new list.
- * @param list1 to append to
- * @param list2 to move from
- * @return pointer to the last item on the list */
-char *rc_strlist_join (char ***list1, char **list2);
+bool rc_stringlist_delete(RC_STRINGLIST *, const char *);
-/*! Reverses the contents of the list.
- * @param list to reverse */
-void rc_strlist_reverse (char **list);
+/*! Sort the list according to C locale
+ * @param list to sort */
+void rc_stringlist_sort(RC_STRINGLIST **);
/*! Frees each item on the list and the list itself.
* @param list to free */
-void rc_strlist_free (char **list);
+void rc_stringlist_free(RC_STRINGLIST *);
/*! Concatenate paths adding '/' if needed. The resultant pointer should be
* freed when finished with.
* @param path1 starting path
* @param paths NULL terminated list of paths to add
* @return pointer to the new path */
-char *rc_strcatpaths (const char *path1, const char *paths, ...) SENTINEL;
+char *rc_strcatpaths(const char *, const char *, ...) SENTINEL;
/*! Find processes based on criteria.
* All of these are optional.
@@ -457,7 +460,6 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...) SENTINEL;
* @param uid to check for
* @param pid to check for
* @return NULL terminated list of pids */
-pid_t *rc_find_pids (const char *const *argv, const char *cmd,
- uid_t uid, pid_t pid);
+pid_t *rc_find_pids(const char *const *, const char *, uid_t, pid_t);
#endif
diff --git a/src/librc/rc.map b/src/librc/rc.map
index e5fd350..8ad4e18 100644
--- a/src/librc/rc.map
+++ b/src/librc/rc.map
@@ -43,15 +43,12 @@ global:
rc_service_value_get;
rc_service_value_set;
rc_strcatpaths;
- rc_strlist_add;
- rc_strlist_addu;
- rc_strlist_addsort;
- rc_strlist_addsortc;
- rc_strlist_addsortu;
- rc_strlist_delete;
- rc_strlist_free;
- rc_strlist_join;
- rc_strlist_reverse;
+ rc_stringlist_add;
+ rc_stringlist_addu;
+ rc_stringlist_delete;
+ rc_stringlist_new;
+ rc_stringlist_sort;
+ rc_stringlist_free;
rc_sys;
rc_yesno;