summaryrefslogtreecommitdiff
path: root/src/librc
diff options
context:
space:
mode:
Diffstat (limited to 'src/librc')
-rw-r--r--src/librc/.gitignore2
-rw-r--r--src/librc/Makefile48
-rw-r--r--src/librc/librc-daemon.c645
-rw-r--r--src/librc/librc-depend.c1054
-rw-r--r--src/librc/librc-misc.c425
-rw-r--r--src/librc/librc-stringlist.c164
-rw-r--r--src/librc/librc.c1061
-rw-r--r--src/librc/librc.h137
-rw-r--r--src/librc/rc.h.in619
-rw-r--r--src/librc/rc.map68
10 files changed, 0 insertions, 4223 deletions
diff --git a/src/librc/.gitignore b/src/librc/.gitignore
deleted file mode 100644
index e7fafe8c..00000000
--- a/src/librc/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-librc.so.1
-rc.h
diff --git a/src/librc/Makefile b/src/librc/Makefile
deleted file mode 100644
index 73075608..00000000
--- a/src/librc/Makefile
+++ /dev/null
@@ -1,48 +0,0 @@
-LIB= rc
-SHLIB_MAJOR= 1
-SRCS= librc.c librc-daemon.c librc-depend.c librc-misc.c \
- librc-stringlist.c
-INCS= rc.h
-VERSION_MAP= rc.map
-
-LDADD+= ${LIBKVM}
-
-CPPFLAGS+= -I../includes
-
-MK= ../../mk
-include ${MK}/lib.mk
-include ${MK}/cc.mk
-
-# Massage our header file for our dirs
-SED_CMD= -e 's:@PREFIX@:${PREFIX}:g'
-SED_CMD+= -e 's:@LIB@:${LIBNAME}:g'
-SED_CMD+= -e 's:@SYSCONFDIR@:${SYSCONFDIR}:g'
-SED_CMD+= -e 's:@LIBEXECDIR@:${LIBEXECDIR}:g'
-SED_CMD+= -e 's:@BINDIR@:${BINDIR}:g'
-SED_CMD+= -e 's:@SBINDIR@:${SBINDIR}:g'
-
-_PKG_PREFIX= -e 's:.*@PKG_PREFIX@.*:\#undef RC_PKG_PREFIX:g'
-ifneq (${PKG_PREFIX},)
-ifneq (${PKG_PREFIX},/)
-ifneq (${PKG_PREFIX},${PREFIX})
-_PKG_PREFIX= -e 's:@PKG_PREFIX@:${PKG_PREFIX}:g'
-endif
-endif
-endif
-SED_CMD+= ${_PKG_PREFIX}
-
-_LCL_PREFIX= -e 's:@LOCAL_PREFIX@::g'
-ifneq (${LOCAL_PREFIX},)
-ifneq (${LOCAL_PREFIX},/)
-ifneq (${LOCAL_PREFIX},${PREFIX})
-_LCL_PREFIX= -e 's:@LOCAL_PREFIX@:${LOCAL_PREFIX}:g'
-endif
-endif
-endif
-SED_CMD+= ${_LCL_PREFIX}
-
-%.h: %.h.in
- ${SED} ${SED_CMD} $< > $@
-${SRCS}: rc.h
-
-CLEANFILES+= rc.h
diff --git a/src/librc/librc-daemon.c b/src/librc/librc-daemon.c
deleted file mode 100644
index 02aff5a9..00000000
--- a/src/librc/librc-daemon.c
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
- librc-daemon
- Finds PID for given daemon criteria
-*/
-
-/*
- * Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
- *
- * 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 "queue.h"
-#include "librc.h"
-
-#if defined(__linux__) || (defined (__FreeBSD_kernel__) && defined(__GLIBC__))
-static bool
-pid_is_exec(pid_t pid, const char *exec)
-{
- char buffer[32];
- FILE *fp;
- int c;
- bool retval = false;
-
- exec = basename_c(exec);
- snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
- if ((fp = fopen(buffer, "r"))) {
- while ((c = getc(fp)) != EOF && c != '(')
- ;
- if (c == '(') {
- while ((c = getc(fp)) != EOF && c == *exec)
- exec++;
- if (c == ')' && *exec == '\0')
- retval = true;
- }
- fclose(fp);
- }
- return retval;
-}
-
-static bool
-pid_is_argv(pid_t pid, const char *const *argv)
-{
- char cmdline[32];
- int fd;
- char buffer[PATH_MAX];
- char *p;
- ssize_t bytes;
-
- snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
- if ((fd = open(cmdline, O_RDONLY)) < 0)
- return false;
- bytes = read(fd, buffer, sizeof(buffer));
- close(fd);
- if (bytes == -1)
- return false;
-
- buffer[bytes] = '\0';
- p = buffer;
- while (*argv) {
- if (strcmp(*argv, p) != 0)
- return false;
- argv++;
- p += strlen(p) + 1;
- if ((unsigned)(p - buffer) > sizeof(buffer))
- return false;
- }
- return true;
-}
-
-RC_PIDLIST *
-rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
-{
- DIR *procdir;
- struct dirent *entry;
- FILE *fp;
- bool container_pid = false;
- bool openvz_host = false;
- char *line = NULL;
- size_t len = 0;
- pid_t p;
- char buffer[PATH_MAX];
- struct stat sb;
- pid_t runscript_pid = 0;
- char *pp;
- RC_PIDLIST *pids = NULL;
- RC_PID *pi;
-
- if ((procdir = opendir("/proc")) == NULL)
- return NULL;
-
- /*
- We never match RC_RUNSCRIPT_PID if present so we avoid the below
- scenario
-
- /etc/init.d/ntpd stop does
- start-stop-daemon --stop --name ntpd
- catching /etc/init.d/ntpd stop
-
- nasty
- */
-
- if ((pp = getenv("RC_RUNSCRIPT_PID"))) {
- if (sscanf(pp, "%d", &runscript_pid) != 1)
- runscript_pid = 0;
- }
-
- /*
- If /proc/self/status contains EnvID: 0, then we are an OpenVZ host,
- and we will need to filter out processes that are inside containers
- from our list of pids.
- */
-
- if (exists("/proc/self/status")) {
- fp = fopen("/proc/self/status", "r");
- if (fp) {
- while (! feof(fp)) {
- rc_getline(&line, &len, fp);
- if (strncmp(line, "envID:\t0", 8) == 0) {
- openvz_host = true;
- break;
- }
- }
- fclose(fp);
- }
- }
-
- while ((entry = readdir(procdir)) != NULL) {
- if (sscanf(entry->d_name, "%d", &p) != 1)
- continue;
- if (runscript_pid != 0 && runscript_pid == p)
- continue;
- if (pid != 0 && pid != p)
- continue;
- if (uid) {
- snprintf(buffer, sizeof(buffer), "/proc/%d", p);
- if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
- continue;
- }
- if (exec && !pid_is_exec(p, exec))
- continue;
- if (argv &&
- !pid_is_argv(p, (const char *const *)argv))
- continue;
- /* If this is an OpenVZ host, filter out container processes */
- if (openvz_host) {
- snprintf(buffer, sizeof(buffer), "/proc/%d/status", p);
- if (exists(buffer)) {
- fp = fopen(buffer, "r");
- if (! fp)
- continue;
- while (! feof(fp)) {
- rc_getline(&line, &len, fp);
- if (strncmp(line, "envID:", 6) == 0) {
- container_pid = ! (strncmp(line, "envID:\t0", 8) == 0);
- break;
- }
- }
- fclose(fp);
- }
- }
- if (container_pid)
- continue;
- if (!pids) {
- pids = xmalloc(sizeof(*pids));
- LIST_INIT(pids);
- }
- pi = xmalloc(sizeof(*pi));
- pi->pid = p;
- LIST_INSERT_HEAD(pids, pi, entries);
- }
- if (line != NULL)
- free(line);
- closedir(procdir);
- return pids;
-}
-librc_hidden_def(rc_find_pids)
-
-#elif BSD
-
-# if defined(__NetBSD__) || defined(__OpenBSD__)
-# define _KVM_GETPROC2
-# define _KINFO_PROC kinfo_proc2
-# define _KVM_GETARGV kvm_getargv2
-# define _GET_KINFO_UID(kp) (kp.p_ruid)
-# define _GET_KINFO_COMM(kp) (kp.p_comm)
-# define _GET_KINFO_PID(kp) (kp.p_pid)
-# define _KVM_PATH NULL
-# define _KVM_FLAGS KVM_NO_FILES
-# else
-# ifndef KERN_PROC_PROC
-# define KERN_PROC_PROC KERN_PROC_ALL
-# endif
-# define _KINFO_PROC kinfo_proc
-# define _KVM_GETARGV kvm_getargv
-# if defined(__DragonFly__)
-# define _GET_KINFO_UID(kp) (kp.kp_ruid)
-# define _GET_KINFO_COMM(kp) (kp.kp_comm)
-# define _GET_KINFO_PID(kp) (kp.kp_pid)
-# else
-# define _GET_KINFO_UID(kp) (kp.ki_ruid)
-# define _GET_KINFO_COMM(kp) (kp.ki_comm)
-# define _GET_KINFO_PID(kp) (kp.ki_pid)
-# endif
-# define _KVM_PATH _PATH_DEVNULL
-# define _KVM_FLAGS O_RDONLY
-# endif
-
-RC_PIDLIST *
-rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
-{
- static kvm_t *kd = NULL;
- char errbuf[_POSIX2_LINE_MAX];
- struct _KINFO_PROC *kp;
- int i;
- int processes = 0;
- int pargc = 0;
- char **pargv;
- RC_PIDLIST *pids = NULL;
- RC_PID *pi;
- pid_t p;
- const char *const *arg;
- int match;
-
- if ((kd = kvm_openfiles(_KVM_PATH, _KVM_PATH,
- NULL, _KVM_FLAGS, errbuf)) == NULL)
- {
- fprintf(stderr, "kvm_open: %s\n", errbuf);
- return NULL;
- }
-
-#ifdef _KVM_GETPROC2
- kp = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(*kp), &processes);
-#else
- 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;
- }
-
- if (exec)
- exec = basename_c(exec);
- for (i = 0; i < processes; i++) {
- p = _GET_KINFO_PID(kp[i]);
- if (pid != 0 && pid != p)
- continue;
- if (uid != 0 && uid != _GET_KINFO_UID(kp[i]))
- continue;
- if (exec) {
- if (!_GET_KINFO_COMM(kp[i]) ||
- strcmp(exec, _GET_KINFO_COMM(kp[i])) != 0)
- continue;
- }
- if (argv && *argv) {
- pargv = _KVM_GETARGV(kd, &kp[i], pargc);
- if (!pargv || !*pargv)
- continue;
- arg = argv;
- match = 1;
- while (*arg && *pargv)
- if (strcmp(*arg++, *pargv++) != 0) {
- match = 0;
- break;
- }
- if (!match)
- continue;
- }
- if (!pids) {
- pids = xmalloc(sizeof(*pids));
- LIST_INIT(pids);
- }
- pi = xmalloc(sizeof(*pi));
- pi->pid = p;
- LIST_INSERT_HEAD(pids, pi, entries);
- }
- kvm_close(kd);
-
- return pids;
-}
-librc_hidden_def(rc_find_pids)
-
-#else
-# error "Platform not supported!"
-#endif
-
-static bool
-_match_daemon(const char *path, const char *file, RC_STRINGLIST *match)
-{
- char *line = NULL;
- size_t len = 0;
- char ffile[PATH_MAX];
- FILE *fp;
- RC_STRING *m;
-
- snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
- fp = fopen(ffile, "r");
-
- if (!fp)
- return false;
-
- while ((rc_getline(&line, &len, 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);
- free(line);
- if (TAILQ_FIRST(match))
- return false;
- return true;
-}
-
-static RC_STRINGLIST *
-_match_list(const char *exec, const char *const *argv, const char *pidfile)
-{
- RC_STRINGLIST *match = rc_stringlist_new();
- int i = 0;
- size_t l;
- char *m;
-
- if (exec) {
- l = strlen(exec) + 6;
- m = xmalloc(sizeof(char) * l);
- snprintf(m, l, "exec=%s", exec);
- rc_stringlist_add(match, m);
- free(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_stringlist_add(match, m);
- free(m);
- }
-
- if (pidfile) {
- l = strlen(pidfile) + 9;
- m = xmalloc(sizeof(char) * l);
- snprintf(m, l, "pidfile=%s", pidfile);
- rc_stringlist_add(match, m);
- free(m);
- }
-
- return match;
-}
-
-bool
-rc_service_daemon_set(const char *service, const char *exec,
- const char *const *argv,
- const char *pidfile, bool started)
-{
- char dirpath[PATH_MAX];
- char file[PATH_MAX];
- int nfiles = 0;
- char oldfile[PATH_MAX] = { '\0' };
- bool retval = false;
- DIR *dp;
- struct dirent *d;
- RC_STRINGLIST *match;
- int i = 0;
- FILE *fp;
-
- if (!exec && !pidfile) {
- errno = EINVAL;
- return false;
- }
-
- snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
- basename_c(service));
-
- /* Regardless, erase any existing daemon info */
- if ((dp = opendir(dirpath))) {
- match = _match_list(exec, argv, pidfile);
- while ((d = readdir(dp))) {
- if (d->d_name[0] == '.')
- continue;
-
- snprintf(file, sizeof(file), "%s/%s",
- dirpath, d->d_name);
- nfiles++;
-
- if (!*oldfile) {
- if (_match_daemon(dirpath, d->d_name, match)) {
- unlink(file);
- strlcpy(oldfile, file, sizeof(oldfile));
- nfiles--;
- }
- } else {
- rename(file, oldfile);
- strlcpy(oldfile, file, sizeof(oldfile));
- }
- }
- closedir(dp);
- rc_stringlist_free(match);
- }
-
- /* Now store our daemon info */
- if (started) {
- if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
- snprintf(file, sizeof(file), "%s/%03d",
- dirpath, nfiles + 1);
- if ((fp = fopen(file, "w"))) {
- fprintf(fp, "exec=");
- if (exec)
- fprintf(fp, "%s", exec);
- while (argv && argv[i]) {
- fprintf(fp, "\nargv_%d=%s", i, argv[i]);
- i++;
- }
- fprintf(fp, "\npidfile=");
- if (pidfile)
- fprintf(fp, "%s", pidfile);
- fprintf(fp, "\n");
- fclose(fp);
- retval = true;
- }
- }
- } else
- retval = true;
-
- return retval;
-}
-librc_hidden_def(rc_service_daemon_set)
-
-bool
-rc_service_started_daemon(const char *service,
- const char *exec, const char *const *argv, int indx)
-{
- char dirpath[PATH_MAX];
- char file[16];
- RC_STRINGLIST *match;
- bool retval = false;
- DIR *dp;
- struct dirent *d;
-
- if (!service || !exec)
- return false;
-
- snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
- basename_c(service));
- match = _match_list(exec, argv, NULL);
-
- if (indx > 0) {
- snprintf(file, sizeof(file), "%03d", indx);
- retval = _match_daemon(dirpath, file, match);
- } else {
- if ((dp = opendir(dirpath))) {
- while ((d = readdir(dp))) {
- if (d->d_name[0] == '.')
- continue;
- retval = _match_daemon(dirpath, d->d_name, match);
- if (retval)
- break;
- }
- closedir(dp);
- }
- }
-
- rc_stringlist_free(match);
- return retval;
-}
-librc_hidden_def(rc_service_started_daemon)
-
-bool
-rc_service_daemons_crashed(const char *service)
-{
- char dirpath[PATH_MAX];
- DIR *dp;
- struct dirent *d;
- char *path = dirpath;
- FILE *fp;
- char *line = NULL;
- size_t len = 0;
- char **argv = NULL;
- char *exec = NULL;
- char *name = NULL;
- char *pidfile = NULL;
- pid_t pid = 0;
- RC_PIDLIST *pids;
- RC_PID *p1;
- RC_PID *p2;
- char *p;
- char *token;
- bool retval = false;
- RC_STRINGLIST *list = NULL;
- RC_STRING *s;
- size_t i;
-
- path += snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
- basename_c(service));
-
- if (!(dp = opendir(dirpath)))
- return false;
-
- while ((d = readdir(dp))) {
- if (d->d_name[0] == '.')
- continue;
-
- snprintf(path, sizeof(dirpath) - (path - dirpath), "/%s",
- d->d_name);
- fp = fopen(dirpath, "r");
- if (!fp)
- break;
-
- while ((rc_getline(&line, &len, fp))) {
- p = line;
- if ((token = strsep(&p, "=")) == NULL || !p)
- continue;
-
- if (!*p)
- continue;
-
- if (strcmp(token, "exec") == 0) {
- if (exec)
- free(exec);
- exec = xstrdup(p);
- } else if (strncmp(token, "argv_", 5) == 0) {
- if (!list)
- list = rc_stringlist_new();
- rc_stringlist_add(list, p);
- } else if (strcmp(token, "name") == 0) {
- if (name)
- free(name);
- name = xstrdup(p);
- } else if (strcmp(token, "pidfile") == 0) {
- pidfile = xstrdup(p);
- break;
- }
- }
- fclose(fp);
-
- char *ch_root = rc_service_value_get(basename_c(service), "chroot");
- char *spidfile = pidfile;
- if (ch_root && pidfile) {
- spidfile = xmalloc(strlen(ch_root) + strlen(pidfile) + 1);
- strcpy(spidfile, ch_root);
- strcat(spidfile, pidfile);
- }
-
- pid = 0;
- if (spidfile) {
- retval = true;
- if ((fp = fopen(spidfile, "r"))) {
- if (fscanf(fp, "%d", &pid) == 1)
- retval = false;
- fclose(fp);
- }
- free(spidfile);
- spidfile = NULL;
- if (ch_root) {
- free(pidfile);
- pidfile = NULL;
- }
-
- /* We have the pid, so no need to match
- on exec or name */
- free(exec);
- exec = NULL;
- free(name);
- name = NULL;
- } else {
- if (exec) {
- if (!list)
- list = rc_stringlist_new();
- if (!TAILQ_FIRST(list))
- rc_stringlist_add(list, exec);
-
- free(exec);
- exec = NULL;
- }
-
- if (list) {
- /* 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';
- }
- }
-
- if (!retval) {
- if (pid != 0) {
- if (kill(pid, 0) == -1 && errno == ESRCH)
- retval = true;
- } else if ((pids = rc_find_pids(exec,
- (const char *const *)argv,
- 0, pid)))
- {
- p1 = LIST_FIRST(pids);
- while (p1) {
- p2 = LIST_NEXT(p1, entries);
- free(p1);
- p1 = p2;
- }
- free(pids);
- } else
- retval = true;
- }
- rc_stringlist_free(list);
- list = NULL;
- free(argv);
- argv = NULL;
- free(exec);
- exec = NULL;
- free(name);
- name = NULL;
- if (retval)
- break;
- }
- closedir(dp);
- free(line);
-
- return retval;
-}
-librc_hidden_def(rc_service_daemons_crashed)
diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c
deleted file mode 100644
index d7a8ae14..00000000
--- a/src/librc/librc-depend.c
+++ /dev/null
@@ -1,1054 +0,0 @@
-/*
- librc-depend
- rc service dependency and ordering
- */
-
-/*
- * Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
- *
- * 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 <sys/utsname.h>
-
-#include "queue.h"
-#include "librc.h"
-
-#define GENDEP RC_LIBEXECDIR "/sh/gendepends.sh"
-
-#define RC_DEPCONFIG RC_SVCDIR "/depconfig"
-
-static const char *bootlevel = NULL;
-
-static char *
-get_shell_value(char *string)
-{
- char *p = string;
- char *e;
-
- if (! string)
- return NULL;
-
- if (*p == '\'')
- p++;
-
- e = p + strlen(p) - 1;
- if (*e == '\n')
- *e-- = 0;
- if (*e == '\'')
- *e-- = 0;
-
- if (*p != 0)
- return p;
-
- return NULL;
-}
-
-void
-rc_deptree_free(RC_DEPTREE *deptree)
-{
- RC_DEPINFO *di;
- RC_DEPINFO *di2;
- RC_DEPTYPE *dt;
- RC_DEPTYPE *dt2;
-
- if (!deptree)
- return;
-
- di = TAILQ_FIRST(deptree);
- while (di) {
- di2 = TAILQ_NEXT(di, entries);
- dt = TAILQ_FIRST(&di->depends);
- while (dt) {
- dt2 = TAILQ_NEXT(dt, entries);
- rc_stringlist_free(dt->services);
- free(dt->type);
- free(dt);
- dt = dt2;
- }
- free(di->service);
- free(di);
- di = di2;
- }
- free(deptree);
-}
-librc_hidden_def(rc_deptree_free)
-
-static RC_DEPINFO *
-get_depinfo(const RC_DEPTREE *deptree, const char *service)
-{
- RC_DEPINFO *di;
-
- TAILQ_FOREACH(di, deptree, entries)
- if (strcmp(di->service, service) == 0)
- return di;
- return NULL;
-}
-
-static RC_DEPTYPE *
-get_deptype(const RC_DEPINFO *depinfo, const char *type)
-{
- RC_DEPTYPE *dt;
-
- TAILQ_FOREACH(dt, &depinfo->depends, entries)
- if (strcmp(dt->type, type) == 0)
- return dt;
- return NULL;
-}
-
-RC_DEPTREE *
-rc_deptree_load(void) {
- return rc_deptree_load_file(RC_DEPTREE_CACHE);
-}
-librc_hidden_def(rc_deptree_load)
-
-RC_DEPTREE *
-rc_deptree_load_file(const char *deptree_file)
-{
- FILE *fp;
- RC_DEPTREE *deptree;
- RC_DEPINFO *depinfo = NULL;
- RC_DEPTYPE *deptype = NULL;
- char *line = NULL;
- size_t len = 0;
- char *type;
- char *p;
- char *e;
- int i;
-
- if (!(fp = fopen(deptree_file, "r")))
- return NULL;
-
- deptree = xmalloc(sizeof(*deptree));
- TAILQ_INIT(deptree);
- while ((rc_getline(&line, &len, fp)))
- {
- p = line;
- e = strsep(&p, "_");
- if (!e || strcmp(e, "depinfo") != 0)
- continue;
- e = strsep(&p, "_");
- if (!e || sscanf(e, "%d", &i) != 1)
- continue;
- if (!(type = strsep(&p, "_=")))
- continue;
- if (strcmp(type, "service") == 0) {
- /* Sanity */
- e = get_shell_value(p);
- if (! e || *e == '\0')
- continue;
- depinfo = xmalloc(sizeof(*depinfo));
- TAILQ_INIT(&depinfo->depends);
- depinfo->service = xstrdup(e);
- TAILQ_INSERT_TAIL(deptree, depinfo, entries);
- deptype = NULL;
- continue;
- }
- e = strsep(&p, "=");
- if (!e || sscanf(e, "%d", &i) != 1)
- continue;
- /* Sanity */
- e = get_shell_value(p);
- if (!e || *e == '\0')
- continue;
- if (!deptype || strcmp(deptype->type, type) != 0) {
- deptype = xmalloc(sizeof(*deptype));
- deptype->services = rc_stringlist_new();
- deptype->type = xstrdup(type);
- TAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries);
- }
- rc_stringlist_add(deptype->services, e);
- }
- fclose(fp);
- free(line);
-
- return deptree;
-}
-librc_hidden_def(rc_deptree_load_file)
-
-static bool
-valid_service(const char *runlevel, const char *service, const char *type)
-{
- RC_SERVICE state;
-
- if (!runlevel ||
- strcmp(type, "ineed") == 0 ||
- strcmp(type, "needsme") == 0)
- return true;
-
- if (rc_service_in_runlevel(service, runlevel))
- return true;
- if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0)
- return false;
- if (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 &&
- strcmp(type, "iafter") == 0)
- return false;
- if (strcmp(runlevel, bootlevel) != 0) {
- if (rc_service_in_runlevel(service, bootlevel))
- return true;
- }
-
- state = rc_service_state(service);
- if (state & RC_SERVICE_HOTPLUGGED ||
- state & RC_SERVICE_STARTED)
- return true;
-
- return false;
-}
-
-static bool
-get_provided1(const char *runlevel, RC_STRINGLIST *providers,
- RC_DEPTYPE *deptype, const char *level,
- bool hotplugged, RC_SERVICE state)
-{
- 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);
-
- if (level)
- ok = rc_service_in_runlevel(svc, level);
- else if (hotplugged)
- ok = (st & RC_SERVICE_HOTPLUGGED &&
- !rc_service_in_runlevel(svc, runlevel) &&
- !rc_service_in_runlevel(svc, bootlevel));
- if (!ok)
- continue;
- switch (state) {
- case RC_SERVICE_STARTED:
- ok = (st & RC_SERVICE_STARTED);
- break;
- case RC_SERVICE_INACTIVE:
- case RC_SERVICE_STARTING:
- case RC_SERVICE_STOPPING:
- ok = (st & RC_SERVICE_STARTING ||
- st & RC_SERVICE_STOPPING ||
- st & RC_SERVICE_INACTIVE);
- break;
- default:
- break;
- }
- if (!ok)
- continue;
- retval = true;
- rc_stringlist_add(providers, svc);
- }
-
- return retval;
-}
-
-/* Work out if a service is provided by another service.
- For example metalog provides logger.
- We need to be able to handle syslogd providing logger too.
- We do this by checking whats running, then what's starting/stopping,
- then what's run in the runlevels and finally alphabetical order.
-
- If there are any bugs in rc-depend, they will probably be here as
- provided dependancy can change depending on runlevel state.
- */
-static RC_STRINGLIST *
-get_provided(const RC_DEPINFO *depinfo, const char *runlevel, int options)
-{
- RC_DEPTYPE *dt;
- RC_STRINGLIST *providers = rc_stringlist_new();
- RC_STRING *service;
-
- dt = get_deptype(depinfo, "providedby");
- if (!dt)
- return 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) {
- TAILQ_FOREACH(service, dt->services, entries)
- rc_stringlist_add(providers, service->value);
- return providers;
- }
-
- /* If we're strict or starting, then only use what we have in our
- * runlevel and bootlevel. If we starting then check hotplugged too. */
- if (options & RC_DEP_STRICT || options & RC_DEP_START) {
- 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->value) & RC_SERVICE_HOTPLUGGED))
- rc_stringlist_add(providers, service->value);
- if (TAILQ_FIRST(providers))
- return providers;
- }
-
- /* OK, we're not strict or there were no services in our runlevel.
- * This is now where the logic gets a little fuzzy :)
- * If there is >1 running service then we return NULL.
- * We do this so we don't hang around waiting for inactive services and
- * our need has already been satisfied as it's not strict.
- * We apply this to these states in order:-
- * started, starting | stopping | inactive, stopped
- * Our sub preference in each of these is in order:-
- * runlevel, hotplugged, bootlevel, any
- */
-#define DO \
- if (TAILQ_FIRST(providers)) { \
- if (TAILQ_NEXT(TAILQ_FIRST(providers), entries)) { \
- rc_stringlist_free(providers); \
- providers = rc_stringlist_new(); \
- } \
- return providers; \
- }
-
- /* Anything running has to come first */
- if (get_provided1(runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTED))
- { DO }
- if (get_provided1(runlevel, providers, dt, NULL, true, RC_SERVICE_STARTED))
- { DO }
- if (bootlevel && strcmp(runlevel, bootlevel) != 0 &&
- get_provided1(runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTED))
- { DO }
- if (get_provided1(runlevel, providers, dt, NULL, false, RC_SERVICE_STARTED))
- { DO }
-
- /* Check starting services */
- if (get_provided1(runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTING))
- return providers;
- if (get_provided1(runlevel, providers, dt, NULL, true, RC_SERVICE_STARTING))
- return providers;
- if (bootlevel && strcmp(runlevel, bootlevel) != 0 &&
- get_provided1(runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTING))
- return providers;
- 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;
- if (get_provided1(runlevel, providers, dt, NULL, true, RC_SERVICE_STOPPED))
- { DO }
- if (bootlevel && (strcmp(runlevel, bootlevel) != 0) &&
- get_provided1(runlevel, providers, dt, bootlevel, false, RC_SERVICE_STOPPED))
- return providers;
-
- /* Still nothing? OK, list our first provided service. */
- service = TAILQ_FIRST(dt->services);
- if (service != NULL)
- rc_stringlist_add(providers, service->value);
-
- return providers;
-}
-
-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)
-{
- 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 */
- TAILQ_FOREACH(type, visited, entries)
- if (strcmp(type->value, depinfo->service) == 0)
- return;
- /* Add ourselves as a visited service */
- rc_stringlist_add(visited, depinfo->service);
-
- TAILQ_FOREACH(type, types, entries)
- {
- if (!(dt = get_deptype(depinfo, type->value)))
- continue;
-
- TAILQ_FOREACH(service, dt->services, entries) {
- if (!(options & RC_DEP_TRACE) ||
- strcmp(type->value, "iprovide") == 0)
- {
- rc_stringlist_add(sorted, service->value);
- continue;
- }
-
- 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 && valid_service(runlevel, di->service, type->value))
- visit_service(deptree, types, sorted, visited, di,
- runlevel, options | RC_DEP_TRACE);
- }
- }
- else if (di && valid_service(runlevel, service->value, type->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")))
- {
- 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("RC_SVCNAME");
- if (!svcname || strcmp(svcname, depinfo->service) != 0) {
- if (!get_deptype(depinfo, "providedby"))
- rc_stringlist_add(sorted, depinfo->service);
- }
-}
-
-RC_STRINGLIST *
-rc_deptree_depend(const RC_DEPTREE *deptree,
- const char *service, const char *type)
-{
- RC_DEPINFO *di;
- RC_DEPTYPE *dt;
- RC_STRINGLIST *svcs;
- RC_STRING *svc;
-
- svcs = rc_stringlist_new();
- if (!(di = get_depinfo(deptree, service)) ||
- !(dt = get_deptype(di, type)))
- {
- errno = ENOENT;
- return svcs;
- }
-
- /* For consistency, we copy the array */
- TAILQ_FOREACH(svc, dt->services, entries)
- rc_stringlist_add(svcs, svc->value);
- return svcs;
-}
-librc_hidden_def(rc_deptree_depend)
-
-RC_STRINGLIST *
-rc_deptree_depends(const RC_DEPTREE *deptree,
- const RC_STRINGLIST *types,
- const RC_STRINGLIST *services,
- const char *runlevel, int options)
-{
- 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;
- TAILQ_FOREACH(service, services, entries) {
- if (!(di = get_depinfo(deptree, service->value))) {
- errno = ENOENT;
- continue;
- }
- if (types)
- visit_service(deptree, types, sorted, visited,
- di, runlevel, options);
- }
- rc_stringlist_free(visited);
- return sorted;
-}
-librc_hidden_def(rc_deptree_depends)
-
-RC_STRINGLIST *
-rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
-{
- RC_STRINGLIST *list;
- RC_STRINGLIST *list2;
- RC_STRINGLIST *types;
- RC_STRINGLIST *services;
-
- bootlevel = getenv("RC_BOOTLEVEL");
- if (! bootlevel)
- bootlevel = RC_LEVEL_BOOT;
-
- /* When shutting down, list all running services */
- if (strcmp(runlevel, RC_LEVEL_SINGLE) == 0 ||
- strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0)
- {
- list = rc_services_in_state(RC_SERVICE_STARTED);
- list2 = rc_services_in_state(RC_SERVICE_INACTIVE);
- TAILQ_CONCAT(list, list2, entries);
- free(list2);
- list2 = rc_services_in_state(RC_SERVICE_STARTING);
- TAILQ_CONCAT(list, list2, entries);
- free(list2);
- } else {
- list = rc_services_in_runlevel(RC_LEVEL_SYSINIT);
- if (strcmp(runlevel, RC_LEVEL_SYSINIT) != 0) {
- list2 = rc_services_in_runlevel(runlevel);
- TAILQ_CONCAT(list, list2, entries);
- free(list2);
- list2 = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
- TAILQ_CONCAT(list, list2, entries);
- free(list2);
- /* If we're not the boot runlevel then add that too */
- if (strcmp(runlevel, bootlevel) != 0) {
- list2 = rc_services_in_runlevel(bootlevel);
- TAILQ_CONCAT(list, list2, entries);
- free(list2);
- }
- }
- }
-
- /* Now we have our lists, we need to pull in any dependencies
- and order them */
- types = rc_stringlist_new();
- rc_stringlist_add(types, "ineed");
- rc_stringlist_add(types, "iuse");
- rc_stringlist_add(types, "iafter");
- 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;
-}
-librc_hidden_def(rc_deptree_order)
-
-static bool
-mtime_check(const char *source, const char *target, bool newer,
- time_t *rel, char *file)
-{
- struct stat buf;
- time_t mtime;
- bool retval = true;
- DIR *dp;
- struct dirent *d;
- char path[PATH_MAX];
- int serrno = errno;
-
- /* We have to exist */
- if (stat(source, &buf) != 0)
- return false;
- mtime = buf.st_mtime;
-
- /* If target does not exist, return true to mimic shell test */
- if (stat(target, &buf) != 0)
- return true;
-
- if (newer) {
- if (mtime < buf.st_mtime) {
- if (rel == NULL)
- return false;
- retval = false;
- }
- if (rel != NULL) {
- if (*rel < buf.st_mtime) {
- if (file)
- strlcpy(file, target, PATH_MAX);
- *rel = buf.st_mtime;
- }
- }
- } else {
- if (mtime > buf.st_mtime) {
- if (rel == NULL)
- return false;
- retval = false;
- }
- if (rel != NULL) {
- if (*rel > buf.st_mtime) {
- if (file)
- strlcpy(file, target, PATH_MAX);
- *rel = buf.st_mtime;
- }
- }
- }
-
- /* If not a dir then reset errno */
- if (!(dp = opendir(target))) {
- errno = serrno;
- return retval;
- }
-
- /* Check all the entries in the dir */
- while ((d = readdir(dp))) {
- if (d->d_name[0] == '.')
- continue;
- snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
- if (!mtime_check(source, path, newer, rel, file)) {
- retval = false;
- if (rel == NULL)
- break;
- }
- }
- closedir(dp);
- return retval;
-}
-
-bool
-rc_newer_than(const char *source, const char *target,
- time_t *newest, char *file)
-{
-
- return mtime_check(source, target, true, newest, file);
-}
-librc_hidden_def(rc_newer_than)
-
-bool
-rc_older_than(const char *source, const char *target,
- time_t *oldest, char *file)
-{
- return mtime_check(source, target, false, oldest, file);
-}
-librc_hidden_def(rc_older_than)
-
-typedef struct deppair
-{
- const char *depend;
- const char *addto;
-} DEPPAIR;
-
-static const DEPPAIR deppairs[] = {
- { "ineed", "needsme" },
- { "iuse", "usesme" },
- { "iafter", "ibefore" },
- { "ibefore", "iafter" },
- { "iprovide", "providedby" },
- { NULL, NULL }
-};
-
-static const char *const depdirs[] =
-{
- RC_SVCDIR,
- RC_SVCDIR "/starting",
- RC_SVCDIR "/started",
- RC_SVCDIR "/stopping",
- RC_SVCDIR "/inactive",
- RC_SVCDIR "/wasinactive",
- RC_SVCDIR "/failed",
- RC_SVCDIR "/hotplugged",
- RC_SVCDIR "/daemons",
- RC_SVCDIR "/options",
- RC_SVCDIR "/exclusive",
- RC_SVCDIR "/scheduled",
- RC_SVCDIR "/tmp",
- NULL
-};
-
-bool
-rc_deptree_update_needed(time_t *newest, char *file)
-{
- bool newer = false;
- 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));
-
- /* Quick test to see if anything we use has changed and we have
- * data in our deptree */
- if (!existss(RC_DEPTREE_CACHE))
- return true;
- if (!rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR, newest, file))
- return true;
- if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR, newest, file))
- return true;
-#ifdef RC_PKG_INITDIR
- if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR, newest, file))
- return true;
-#endif
-#ifdef RC_PKG_CONFDIR
- if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR, newest, file))
- return true;
-#endif
-#ifdef RC_LOCAL_INITDIR
- if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR, newest, file))
- return true;
-#endif
-#ifdef RC_LOCAL_CONFDIR
- if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR, newest, file))
- return true;
-#endif
- if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONF, newest, file))
- 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);
- TAILQ_FOREACH(s, config, entries) {
- if (!rc_newer_than(RC_DEPTREE_CACHE, s->value, newest, file)) {
- newer = true;
- break;
- }
- }
- rc_stringlist_free(config);
- return newer;
-}
-librc_hidden_def(rc_deptree_update_needed)
-
-/* This is a 6 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 removes broken before dependencies
- Phase 6 saves the depinfo object to disk
- */
-bool
-rc_deptree_update(void)
-{
- FILE *fp;
- RC_DEPTREE *deptree, *providers;
- RC_DEPINFO *depinfo = NULL, *depinfo_np, *di;
- RC_DEPTYPE *deptype = NULL, *dt_np, *dt, *provide;
- RC_STRINGLIST *config, *types, *sorted, *visited;
- RC_STRING *s, *s2, *s2_np, *s3, *s4;
- char *line = NULL;
- size_t len = 0;
- char *depend, *depends, *service, *type, *nosys, *onosys;
- size_t i, k, l;
- bool retval = true;
- const char *sys = rc_sys();
- struct utsname uts;
-
- /* Some init scripts need RC_LIBEXECDIR to source stuff
- Ideally we should be setting our full env instead */
- if (!getenv("RC_LIBEXECDIR"))
- setenv("RC_LIBEXECDIR", RC_LIBEXECDIR, 0);
-
- if (uname(&uts) == 0)
- setenv("RC_UNAME", uts.sysname, 1);
- /* Phase 1 - source all init scripts and print dependencies */
- if (!(fp = popen(GENDEP, "r")))
- return false;
-
- deptree = xmalloc(sizeof(*deptree));
- TAILQ_INIT(deptree);
- config = rc_stringlist_new();
- while ((rc_getline(&line, &len, fp)))
- {
- depends = line;
- service = strsep(&depends, " ");
- if (!service || !*service)
- continue;
-
- type = strsep(&depends, " ");
- if (!depinfo || strcmp(depinfo->service, service) != 0) {
- deptype = NULL;
- depinfo = get_depinfo(deptree, service);
- if (!depinfo) {
- depinfo = xmalloc(sizeof(*depinfo));
- TAILQ_INIT(&depinfo->depends);
- depinfo->service = xstrdup(service);
- TAILQ_INSERT_TAIL(deptree, depinfo, entries);
- }
- }
-
- /* We may not have any depends */
- if (!type || !depends)
- continue;
-
- /* Get the 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();
- TAILQ_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, " ")))
- {
- if (depend[0] == 0)
- continue;
-
- if (strcmp(type, "config") == 0) {
- rc_stringlist_addu(config, depend);
- continue;
- }
-
- /* Don't provide ourself */
- if (strcmp(type, "iprovide") == 0 &&
- strcmp(depend, service) == 0)
- continue;
-
- /* .sh files are not init scripts */
- l = strlen(depend);
- if (l > 2 &&
- depend[l - 3] == '.' &&
- depend[l - 2] == 's' &&
- depend[l - 1] == 'h')
- continue;
-
- /* Remove our dependency if instructed */
- if (depend[0] == '!') {
- rc_stringlist_delete(deptype->services, depend + 1);
- continue;
- }
-
- 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_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_stringlist_delete(dt->services, depend);
- }
- }
- }
- free(line);
- 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) {
- len = strlen(sys);
- nosys = xmalloc(len + 2);
- nosys[0] = '-';
- for (i = 0; i < len; i++)
- nosys[i + 1] = (char)tolower((unsigned char)sys[i]);
- nosys[i + 1] = '\0';
-
- onosys = xmalloc(len + 3);
- onosys[0] = 'n';
- onosys[1] = 'o';
- for (i = 0; i < len; i++)
- onosys[i + 2] = (char)tolower((unsigned char)sys[i]);
- onosys[i + 2] = '\0';
-
- TAILQ_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 ||
- strcmp(s->value, onosys) == 0)
- {
- provide = get_deptype(depinfo, "iprovide");
- TAILQ_REMOVE(deptree, depinfo, entries);
- TAILQ_FOREACH(di, deptree, entries) {
- TAILQ_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)) {
- TAILQ_REMOVE(&di->depends, dt, entries);
- free(dt->type);
- free(dt->services);
- free(dt);
- }
- }
- }
- }
- free(nosys);
- free(onosys);
- }
-
- /* Phase 3 - add our providers to the tree */
- providers = xmalloc(sizeof(*providers));
- TAILQ_INIT(providers);
- TAILQ_FOREACH(depinfo, deptree, entries)
- if ((deptype = get_deptype(depinfo, "iprovide")))
- TAILQ_FOREACH(s, deptype->services, entries) {
- TAILQ_FOREACH(di, providers, entries)
- if (strcmp(di->service, s->value) == 0)
- break;
- if (!di) {
- di = xmalloc(sizeof(*di));
- TAILQ_INIT(&di->depends);
- di->service = xstrdup(s->value);
- TAILQ_INSERT_TAIL(providers, di, entries);
- }
- }
- TAILQ_CONCAT(deptree, providers, entries);
- free(providers);
-
- /* Phase 4 - backreference our depends */
- TAILQ_FOREACH(depinfo, deptree, entries)
- for (i = 0; deppairs[i].depend; i++) {
- deptype = get_deptype(depinfo, deppairs[i].depend);
- if (!deptype)
- continue;
- TAILQ_FOREACH(s, deptype->services, entries) {
- di = get_depinfo(deptree, s->value);
- if (!di) {
- if (strcmp(deptype->type, "ineed") == 0) {
- fprintf(stderr,
- "Service `%s' needs non"
- " existent service `%s'\n",
- depinfo->service, s->value);
- dt = get_deptype(depinfo, "broken");
- if (!dt) {
- dt = xmalloc(sizeof(*dt));
- dt->type = xstrdup("broken");
- dt->services = rc_stringlist_new();
- TAILQ_INSERT_TAIL(&depinfo->depends, dt, entries);
- }
- rc_stringlist_addu(dt->services, s->value);
- }
- continue;
- }
-
- dt = get_deptype(di, deppairs[i].addto);
- if (!dt) {
- dt = xmalloc(sizeof(*dt));
- dt->type = xstrdup(deppairs[i].addto);
- dt->services = rc_stringlist_new();
- TAILQ_INSERT_TAIL(&di->depends, dt, entries);
- }
- rc_stringlist_addu(dt->services, depinfo->service);
- }
- }
-
-
- /* Phase 5 - Remove broken before directives */
- types = rc_stringlist_new();
- rc_stringlist_add(types, "ineed");
- rc_stringlist_add(types, "iuse");
- rc_stringlist_add(types, "iafter");
- TAILQ_FOREACH(depinfo, deptree, entries) {
- deptype = get_deptype(depinfo, "ibefore");
- if (!deptype)
- continue;
- sorted = rc_stringlist_new();
- visited = rc_stringlist_new();
- visit_service(deptree, types, sorted, visited, depinfo,
- NULL, 0);
- rc_stringlist_free(visited);
- TAILQ_FOREACH_SAFE(s2, deptype->services, entries, s2_np) {
- TAILQ_FOREACH(s3, sorted, entries) {
- di = get_depinfo(deptree, s3->value);
- if (!di)
- continue;
- if (strcmp(s2->value, s3->value) == 0) {
- dt = get_deptype(di, "iafter");
- if (dt)
- rc_stringlist_delete(dt->services, depinfo->service);
- break;
- }
- dt = get_deptype(di, "iprovide");
- if (!dt)
- continue;
- TAILQ_FOREACH(s4, dt->services, entries) {
- if (strcmp(s4->value, s2->value) == 0)
- break;
- }
- if (s4) {
- di = get_depinfo(deptree, s4->value);
- if (di) {
- dt = get_deptype(di, "iafter");
- if (dt)
- rc_stringlist_delete(dt->services, depinfo->service);
- }
- break;
- }
- }
- if (s3)
- rc_stringlist_delete(deptype->services, s2->value);
- }
- rc_stringlist_free(sorted);
- }
- rc_stringlist_free(types);
-
- /* Phase 6 - save to disk
- Now that we're purely in C, do we need to keep a shell parseable file?
- I think yes as then it stays human readable
- 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_CACHE, "w"))) {
- i = 0;
- TAILQ_FOREACH(depinfo, deptree, entries) {
- fprintf(fp, "depinfo_%zu_service='%s'\n",
- i, depinfo->service);
- TAILQ_FOREACH(deptype, &depinfo->depends, entries) {
- k = 0;
- TAILQ_FOREACH(s, deptype->services, entries) {
- fprintf(fp,
- "depinfo_%zu_%s_%zu='%s'\n",
- i, deptype->type, k, s->value);
- k++;
- }
- }
- i++;
- }
- fclose(fp);
- } else {
- fprintf(stderr, "fopen `%s': %s\n",
- RC_DEPTREE_CACHE, strerror(errno));
- retval = false;
- }
-
- /* Save our external config files to disk */
- 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));
- retval = false;
- }
- } else {
- unlink(RC_DEPCONFIG);
- }
-
- rc_stringlist_free(config);
- rc_deptree_free(deptree);
- return retval;
-}
-librc_hidden_def(rc_deptree_update)
diff --git a/src/librc/librc-misc.c b/src/librc/librc-misc.c
deleted file mode 100644
index 2e9de801..00000000
--- a/src/librc/librc-misc.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- rc-misc.c
- rc misc functions
-*/
-
-/*
- * Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
- *
- * 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 "queue.h"
-#include "librc.h"
-
-bool
-rc_yesno(const char *value)
-{
- if (!value) {
- errno = ENOENT;
- return false;
- }
-
- if (strcasecmp(value, "yes") == 0 ||
- strcasecmp(value, "y") == 0 ||
- strcasecmp(value, "true") == 0 ||
- strcasecmp(value, "1") == 0)
- return true;
-
- if (strcasecmp(value, "no") != 0 &&
- strcasecmp(value, "n") != 0 &&
- strcasecmp(value, "false") != 0 &&
- strcasecmp(value, "0") != 0)
- errno = EINVAL;
-
- return false;
-}
-librc_hidden_def(rc_yesno)
-
-
-/**
- * Read the entire @file into the buffer and set @len to the
- * size of the buffer when finished. For C strings, this will
- * be strlen(buffer) + 1.
- * Don't forget to free the buffer afterwards!
- */
-bool
-rc_getfile(const char *file, char **buffer, size_t *len)
-{
- bool ret = false;
- FILE *fp;
- int fd;
- struct stat st;
- size_t done, left;
-
- fp = fopen(file, "re");
- if (!fp)
- return false;
-
- /* assume fileno() never fails */
- fd = fileno(fp);
-
- if (fstat(fd, &st))
- goto finished;
-
- left = st.st_size;
- *len = left + 1; /* NUL terminator */
- *buffer = xrealloc(*buffer, *len);
- while (left) {
- done = fread(*buffer, sizeof(*buffer[0]), left, fp);
- if (done == 0 && ferror(fp))
- goto finished;
- left -= done;
- }
- ret = true;
-
- finished:
- if (!ret) {
- free(*buffer);
- *len = 0;
- } else
- (*buffer)[*len - 1] = '\0';
- fclose(fp);
- return ret;
-}
-librc_hidden_def(rc_getfile)
-
-ssize_t
-rc_getline(char **line, size_t *len, FILE *fp)
-{
- char *p;
- size_t last = 0;
-
- while (!feof(fp)) {
- if (*line == NULL || last != 0) {
- *len += BUFSIZ;
- *line = xrealloc(*line, *len);
- }
- p = *line + last;
- memset(p, 0, BUFSIZ);
- if (fgets(p, BUFSIZ, fp) == NULL)
- break;
- last += strlen(p);
- if (last && (*line)[last - 1] == '\n') {
- (*line)[last - 1] = '\0';
- break;
- }
- }
- return last;
-}
-librc_hidden_def(rc_getline)
-
-char *
-rc_proc_getent(const char *ent)
-{
-#ifdef __linux__
- FILE *fp;
- char *proc, *p, *value = NULL;
- size_t i, len;
-
- if (!exists("/proc/cmdline"))
- return NULL;
-
- if (!(fp = fopen("/proc/cmdline", "r")))
- return NULL;
-
- proc = NULL;
- i = 0;
- if (rc_getline(&proc, &i, fp) == -1 || proc == NULL)
- return NULL;
-
- if (proc != NULL) {
- len = strlen(ent);
-
- while ((p = strsep(&proc, " "))) {
- if (strncmp(ent, p, len) == 0 && (p[len] == '\0' || p[len] == ' ' || p[len] == '=')) {
- p += len;
-
- if (*p == '=')
- p++;
-
- value = xstrdup(p);
- }
- }
- }
-
- if (!value)
- errno = ENOENT;
-
- fclose(fp);
- free(proc);
-
- return value;
-#else
- return NULL;
-#endif
-}
-librc_hidden_def(rc_proc_getent)
-
-RC_STRINGLIST *
-rc_config_list(const char *file)
-{
- FILE *fp;
- char *buffer = NULL;
- size_t len = 0;
- char *p;
- char *token;
- RC_STRINGLIST *list = rc_stringlist_new();
-
- if (!(fp = fopen(file, "r")))
- return list;
-
- while ((rc_getline(&buffer, &len, fp))) {
- p = buffer;
- /* Strip leading spaces/tabs */
- while ((*p == ' ') || (*p == '\t'))
- p++;
-
- /* Get entry - we do not want comments */
- token = strsep(&p, "#");
- if (token && (strlen(token) > 1)) {
- /* If not variable assignment then skip */
- if (strchr(token, '=')) {
- /* Stip the newline if present */
- if (token[strlen(token) - 1] == '\n')
- token[strlen(token) - 1] = 0;
-
- rc_stringlist_add(list, token);
- }
- }
- }
- fclose(fp);
- free(buffer);
-
- return list;
-}
-librc_hidden_def(rc_config_list)
-
-/*
- * Override some specific rc.conf options on the kernel command line
- */
-#ifdef __linux__
-static RC_STRINGLIST *rc_config_override(RC_STRINGLIST *config)
-{
- RC_STRINGLIST *overrides;
- RC_STRING *cline, *override, *config_np;
- char *tmp = NULL;
- char *value = NULL;
- size_t varlen = 0;
- size_t len = 0;
-
- overrides = rc_stringlist_new();
-
- /* A list of variables which may be overridden on the kernel command line */
- rc_stringlist_add(overrides, "rc_parallel");
-
- TAILQ_FOREACH(override, overrides, entries) {
- varlen = strlen(override->value);
- value = rc_proc_getent(override->value);
-
- /* No need to continue if there's nothing to override */
- if (!value) {
- free(value);
- continue;
- }
-
- if (value != NULL) {
- len = varlen + strlen(value) + 2;
- tmp = xmalloc(sizeof(char) * len);
- snprintf(tmp, len, "%s=%s", override->value, value);
- }
-
- /*
- * Whenever necessary remove the old config entry first to prevent
- * duplicates
- */
- TAILQ_FOREACH_SAFE(cline, config, entries, config_np) {
- if (strncmp(override->value, cline->value, varlen) == 0
- && cline->value[varlen] == '=') {
- rc_stringlist_delete(config, cline->value);
- break;
- }
- }
-
- /* Add the option (var/value) to the current config */
- rc_stringlist_add(config, tmp);
-
- free(tmp);
- free(value);
- }
-
- rc_stringlist_free(overrides);
- return config;
-}
-#endif
-
-RC_STRINGLIST *
-rc_config_load(const char *file)
-{
- RC_STRINGLIST *list;
- RC_STRINGLIST *config;
- char *token;
- RC_STRING *line;
- RC_STRING *cline;
- size_t i = 0;
- bool replaced;
- char *entry;
- char *newline;
- char *p;
-
- list = rc_config_list(file);
- config = rc_stringlist_new();
- TAILQ_FOREACH(line, list, entries) {
- /* Get entry */
- p = line->value;
- if (! p)
- continue;
- if (strncmp(p, "export ", 7) == 0)
- p += 7;
- if (! (token = strsep(&p, "=")))
- continue;
-
- entry = xstrdup(token);
- /* Preserve shell coloring */
- if (*p == '$')
- token = line->value;
- else
- do {
- /* Bash variables are usually quoted */
- token = strsep(&p, "\"\'");
- } while (token && *token == '\0');
-
- /* Drop a newline if that's all we have */
- if (token) {
- i = strlen(token) - 1;
- if (token[i] == '\n')
- token[i] = 0;
-
- i = strlen(entry) + strlen(token) + 2;
- 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);
- }
-
- replaced = false;
- /* In shells the last item takes precedence, so we need to remove
- any prior values we may already have */
- TAILQ_FOREACH(cline, config, entries) {
- i = strlen(entry);
- if (strncmp(entry, cline->value, i) == 0 && cline->value[i] == '=') {
- /* We have a match now - to save time we directly replace it */
- free(cline->value);
- cline->value = newline;
- replaced = true;
- break;
- }
- }
-
- if (!replaced) {
- rc_stringlist_add(config, newline);
- free(newline);
- }
- free(entry);
- }
- rc_stringlist_free(list);
-
-#ifdef __linux__
- /* Only override rc.conf settings */
- if (strcmp(file, RC_CONF) == 0) {
- config = rc_config_override(config);
- }
-#endif
-
- return config;
-}
-librc_hidden_def(rc_config_load)
-
-char *
-rc_config_value(RC_STRINGLIST *list, const char *entry)
-{
- RC_STRING *line;
- char *p;
- size_t len;
-
- len = strlen(entry);
- TAILQ_FOREACH(line, list, entries) {
- p = strchr(line->value, '=');
- if (p != NULL) {
- if (strncmp(entry, line->value, len) == 0 && line->value[len] == '=')
- return ++p;
- }
- }
- return NULL;
-}
-librc_hidden_def(rc_config_value)
-
-/* Global for caching the strings loaded from rc.conf to avoid reparsing for
- * each rc_conf_value call */
-static RC_STRINGLIST *rc_conf = NULL;
-
-char *
-rc_conf_value(const char *setting)
-{
- RC_STRINGLIST *old;
- RC_STRING *s;
- char *p;
-
- if (! rc_conf) {
- rc_conf = rc_config_load(RC_CONF);
-#ifdef DEBUG_MEMORY
- atexit(_free_rc_conf);
-#endif
-
- /* Support old configs. */
- if (exists(RC_CONF_OLD)) {
- old = rc_config_load(RC_CONF_OLD);
- TAILQ_CONCAT(rc_conf, old, entries);
-#ifdef DEBUG_MEMORY
- free(old);
-#endif
- }
-
- /* Convert old uppercase to lowercase */
- TAILQ_FOREACH(s, rc_conf, entries) {
- p = s->value;
- while (p && *p && *p != '=') {
- if (isupper((unsigned char)*p))
- *p = tolower((unsigned char)*p);
- p++;
- }
- }
- }
-
- return rc_config_value(rc_conf, setting);
-}
-librc_hidden_def(rc_conf_value)
-
-#ifdef DEBUG_MEMORY
-static void
-_free_rc_conf(void)
-{
- rc_stringlist_free(rc_conf);
-}
-#endif
diff --git a/src/librc/librc-stringlist.c b/src/librc/librc-stringlist.c
deleted file mode 100644
index bf8d3f40..00000000
--- a/src/librc/librc-stringlist.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- librc-strlist.h
- String list functions to make using queue(3) a little easier.
-*/
-
-/*
- * Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
- *
- * 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 "queue.h"
-#include "librc.h"
-
-RC_STRINGLIST *
-rc_stringlist_new(void)
-{
- RC_STRINGLIST *l = xmalloc(sizeof(*l));
- TAILQ_INIT(l);
- return l;
-}
-librc_hidden_def(rc_stringlist_new)
-
-RC_STRING *
-rc_stringlist_add(RC_STRINGLIST *list, const char *value)
-{
- RC_STRING *s = xmalloc(sizeof(*s));
-
- s->value = xstrdup(value);
- TAILQ_INSERT_TAIL(list, s, entries);
- return s;
-}
-librc_hidden_def(rc_stringlist_add)
-
-RC_STRING *
-rc_stringlist_addu(RC_STRINGLIST *list, const char *value)
-{
- RC_STRING *s;
-
- TAILQ_FOREACH(s, list, entries)
- if (strcmp(s->value, value) == 0) {
- errno = EEXIST;
- return NULL;
- }
-
- return rc_stringlist_add(list, value);
-}
-librc_hidden_def(rc_stringlist_addu)
-
-bool
-rc_stringlist_delete(RC_STRINGLIST *list, const char *value)
-{
- RC_STRING *s;
-
- TAILQ_FOREACH(s, list, entries)
- if (strcmp(s->value, value) == 0) {
- TAILQ_REMOVE(list, s, entries);
- free(s->value);
- free(s);
- return true;
- }
-
- errno = EEXIST;
- return false;
-}
-librc_hidden_def(rc_stringlist_delete)
-
-RC_STRING *
-rc_stringlist_find(RC_STRINGLIST *list, const char *value)
-{
- RC_STRING *s;
-
- if (list) {
- TAILQ_FOREACH(s, list, entries)
- if (strcmp(s->value, value) == 0)
- return s;
- }
- return NULL;
-}
-librc_hidden_def(rc_stringlist_find)
-
-RC_STRINGLIST *
-rc_stringlist_split(const char *value, const char *sep)
-{
- RC_STRINGLIST *list = rc_stringlist_new();
- char *d = xstrdup(value);
- char *p = d, *token;
-
- while ((token = strsep(&p, sep)))
- rc_stringlist_add(list, token);
- free(d);
-
- return list;
-}
-librc_hidden_def(rc_stringlist_split)
-
-void
-rc_stringlist_sort(RC_STRINGLIST **list)
-{
- RC_STRINGLIST *l = *list;
- RC_STRINGLIST *new = rc_stringlist_new();
- RC_STRING *s;
- RC_STRING *sn;
- RC_STRING *n;
- RC_STRING *last;
-
- TAILQ_FOREACH_SAFE(s, l, entries, sn) {
- TAILQ_REMOVE(l, s, entries);
- last = NULL;
- TAILQ_FOREACH(n, new, entries) {
- if (strcmp(s->value, n->value) < 0)
- break;
- last = n;
- }
- if (last)
- TAILQ_INSERT_AFTER(new, last, s, entries);
- else
- TAILQ_INSERT_HEAD(new, s, entries);
- }
-
- /* Now we've sorted the list, copy across the new head */
- free(l);
- *list = new;
-}
-librc_hidden_def(rc_stringlist_sort)
-
-void
-rc_stringlist_free(RC_STRINGLIST *list)
-{
- RC_STRING *s1;
- RC_STRING *s2;
-
- if (!list)
- return;
-
- s1 = TAILQ_FIRST(list);
- while (s1) {
- s2 = TAILQ_NEXT(s1, entries);
- free(s1->value);
- free(s1);
- s1 = s2;
- }
- free(list);
-}
-librc_hidden_def(rc_stringlist_free)
diff --git a/src/librc/librc.c b/src/librc/librc.c
deleted file mode 100644
index ca51aa61..00000000
--- a/src/librc/librc.c
+++ /dev/null
@@ -1,1061 +0,0 @@
-/*
- librc
- core RC functions
-*/
-
-/*
- * Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
- *
- * 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.
- */
-
-const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
-
-#include "queue.h"
-#include "librc.h"
-#ifdef __FreeBSD__
-# include <sys/sysctl.h>
-#endif
-
-#define RC_RUNLEVEL RC_SVCDIR "/softlevel"
-
-#ifndef S_IXUGO
-# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
-#endif
-
-/* File stream used for plugins to write environ vars to */
-FILE *rc_environ_fd = NULL;
-
-typedef struct rc_service_state_name {
- RC_SERVICE state;
- const char *name;
-} rc_service_state_name_t;
-
-/* We MUST list the states below 0x10 first
- * The rest can be in any order */
-static const rc_service_state_name_t rc_service_state_names[] = {
- { RC_SERVICE_STARTED, "started" },
- { RC_SERVICE_STOPPED, "stopped" },
- { RC_SERVICE_STARTING, "starting" },
- { RC_SERVICE_STOPPING, "stopping" },
- { RC_SERVICE_INACTIVE, "inactive" },
- { RC_SERVICE_WASINACTIVE, "wasinactive" },
- { RC_SERVICE_HOTPLUGGED, "hotplugged" },
- { RC_SERVICE_FAILED, "failed" },
- { RC_SERVICE_SCHEDULED, "scheduled"},
- { 0, NULL}
-};
-
-#define LS_INITD 0x01
-#define LS_DIR 0x02
-static RC_STRINGLIST *
-ls_dir(const char *dir, int options)
-{
- DIR *dp;
- struct dirent *d;
- RC_STRINGLIST *list = NULL;
- struct stat buf;
- size_t l;
- char file[PATH_MAX];
- int r;
-
- list = rc_stringlist_new();
- if ((dp = opendir(dir)) == NULL)
- return list;
- while (((d = readdir(dp)) != NULL)) {
- if (d->d_name[0] != '.') {
- if (options & LS_INITD) {
- /* Check that our file really exists.
- * This is important as a service maybe in a
- * runlevel, but could have been removed. */
- snprintf(file, sizeof(file), "%s/%s",
- dir, d->d_name);
- r = stat(file, &buf);
- 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))
- continue;
- }
- rc_stringlist_add(list, d->d_name);
- }
- }
- closedir(dp);
- return list;
-}
-
-static bool
-rm_dir(const char *pathname, bool top)
-{
- DIR *dp;
- struct dirent *d;
- char file[PATH_MAX];
- struct stat s;
- bool retval = true;
-
- 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)
- {
- snprintf(file, sizeof(file),
- "%s/%s", pathname, d->d_name);
- if (stat(file, &s) != 0) {
- retval = false;
- break;
- }
- if (S_ISDIR(s.st_mode)) {
- if (!rm_dir(file, true))
- {
- retval = false;
- break;
- }
- } else {
- if (unlink(file)) {
- retval = false;
- break;
- }
- }
- }
- }
- closedir(dp);
-
- if (!retval)
- return false;
-
- if (top && rmdir(pathname) != 0)
- return false;
-
- 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)
-{
- FILE *fp;
- char *line = NULL;
- size_t len = 0;
- regex_t re;
- bool retval = true;
- int result;
-
- 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;
- }
-
- while ((rc_getline(&line, &len, fp))) {
- char *str = line;
- /* some /proc files have \0 separated content so we have to
- loop through the 'line' */
- do {
- if (regexec(&re, str, 0, NULL, 0) == 0)
- goto found;
- str += strlen(str) + 1;
- /* len is the size of allocated buffer and we don't
- want call regexec BUFSIZE times. find next str */
- while (str < line + len && *str == '\0')
- str++;
- } while (str < line + len);
- }
- retval = false;
-found:
- fclose(fp);
- free(line);
- regfree(&re);
-
- return retval;
-}
-#endif
-
-/* New sys identification code
- * Not to be used for any binaries outside of openrc. */
-const char *
-rc_sys_v2(void)
-{
-#define __STRING_SWITCH(x) { char *__string_switch = x; if (false) {}
-#define __STRING_CASE(y) else if (strcmp(__string_switch,y) == 0)
-#define __STRING_SWITCH_END() }
- char *systype = rc_conf_value("rc_sys");
- if (systype) {
- char *s = systype;
- /* Convert to uppercase */
- while (s && *s) {
- if (islower((unsigned char) *s))
- *s = toupper((unsigned char) *s);
- s++;
- }
- /* Now do detection */
- __STRING_SWITCH(systype)
- __STRING_CASE(RC_SYS_PREFIX) { return RC_SYS_PREFIX; }
-#ifdef __FreeBSD__
- __STRING_CASE(RC_SYS_JAIL) { return RC_SYS_JAIL; }
-#endif /* __FreeBSD__ */
-#ifdef __NetBSD__
- __STRING_CASE(RC_SYS_XEN0) { return RC_SYS_XEN0; }
- __STRING_CASE(RC_SYS_XENU) { return RC_SYS_XENU; }
-#endif /* __NetBSD__ */
-#ifdef __linux__
- __STRING_CASE(RC_SYS_XEN0) { return RC_SYS_XEN0; }
- __STRING_CASE(RC_SYS_XENU) { return RC_SYS_XENU; }
- __STRING_CASE(RC_SYS_UML) { return RC_SYS_UML; }
- __STRING_CASE(RC_SYS_VSERVER) { return RC_SYS_VSERVER; }
- __STRING_CASE(RC_SYS_OPENVZ) { return RC_SYS_OPENVZ; }
- __STRING_CASE(RC_SYS_LXC) { return RC_SYS_LXC; }
-#endif /* __linux__ */
- __STRING_SWITCH_END()
- }
-#undef __STRING_SWITCH
-#undef __STRING_CASE
-#undef __STRING_SWITCH_END
- return NULL;
-}
-librc_hidden_def(rc_sys_v2)
-
-/* Old sys identification code.
- * Not to be used for any binaries outside of openrc. */
-const char *
-rc_sys_v1(void)
-{
-#ifdef PREFIX
- return RC_SYS_PREFIX;
-#else
-
-#ifdef __FreeBSD__
- int jailed = 0;
- size_t len = sizeof(jailed);
-
- if (sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0) == 0)
- if (jailed == 1)
- return RC_SYS_JAIL;
-#endif
-
-#ifdef __NetBSD__
- if (exists("/kern/xen/privcmd"))
- return RC_SYS_XEN0;
- if (exists("/kern/xen"))
- return RC_SYS_XENU;
-#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 (exists("/proc/vz/veinfo") && !exists("/proc/vz/version"))
- return RC_SYS_OPENVZ;
- else if (file_regex("/proc/self/status",
- "envID:[[:space:]]*[1-9]"))
- return RC_SYS_OPENVZ; /* old test */
- else if (file_regex("/proc/1/environ", "container=lxc"))
- return RC_SYS_LXC;
-#endif
-
- return NULL;
-#endif /* PREFIX */
-}
-librc_hidden_def(rc_sys_v1)
-
-const char *
-rc_sys(void)
-{
- if (rc_conf_value("rc_sys")) {
- return rc_sys_v2();
- } else {
- return rc_sys_v1();
- }
-}
-librc_hidden_def(rc_sys)
-
-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 NULL;
-}
-
-/* Returns a list of all the chained runlevels used by the
- * specified runlevel in dependency order, including the
- * specified runlevel. */
-static void
-get_runlevel_chain(const char *runlevel, RC_STRINGLIST *level_list)
-{
- char path[PATH_MAX];
- RC_STRINGLIST *dirs;
- RC_STRING *d, *dn;
-
- /*
- * If we haven't been passed a runlevel or a level list, or
- * if the passed runlevel doesn't exist then we're done already!
- */
- if (!runlevel || !level_list || !rc_runlevel_exists(runlevel))
- return;
-
- /*
- * We want to add this runlevel to the list but if
- * it is already in the list it needs to go at the
- * end again.
- */
- if (rc_stringlist_find(level_list, runlevel))
- rc_stringlist_delete(level_list, runlevel);
- rc_stringlist_add(level_list, runlevel);
-
- /*
- * We can now do exactly the above procedure for our chained
- * runlevels.
- */
- snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
- dirs = ls_dir(path, LS_DIR);
- TAILQ_FOREACH_SAFE(d, dirs, entries, dn)
- get_runlevel_chain(d->value, level_list);
-}
-
-bool
-rc_runlevel_starting(void)
-{
- return exists(RC_STARTING);
-}
-librc_hidden_def(rc_runlevel_starting)
-
-bool
-rc_runlevel_stopping(void)
-{
- return exists(RC_STOPPING);
-}
-librc_hidden_def(rc_runlevel_stopping)
-
-RC_STRINGLIST *rc_runlevel_list(void)
-{
- return ls_dir(RC_RUNLEVELDIR, LS_DIR);
-}
-librc_hidden_def(rc_runlevel_list)
-
-char *
-rc_runlevel_get(void)
-{
- FILE *fp;
- char *runlevel = NULL;
- size_t i;
-
- if ((fp = fopen(RC_RUNLEVEL, "r"))) {
- runlevel = xmalloc(sizeof(char) * PATH_MAX);
- if (fgets(runlevel, PATH_MAX, fp)) {
- i = strlen(runlevel) - 1;
- if (runlevel[i] == '\n')
- runlevel[i] = 0;
- } else
- *runlevel = '\0';
- fclose(fp);
- }
-
- if (!runlevel || !*runlevel) {
- free(runlevel);
- runlevel = xstrdup(RC_LEVEL_SYSINIT);
- }
-
- return runlevel;
-}
-librc_hidden_def(rc_runlevel_get)
-
-bool
-rc_runlevel_set(const char *runlevel)
-{
- FILE *fp = fopen(RC_RUNLEVEL, "w");
-
- if (!fp)
- return false;
- fprintf(fp, "%s", runlevel);
- fclose(fp);
- return true;
-}
-librc_hidden_def(rc_runlevel_set)
-
-bool
-rc_runlevel_exists(const char *runlevel)
-{
- char path[PATH_MAX];
- struct stat buf;
-
- if (!runlevel || strcmp(runlevel, ".") == 0 || strcmp(runlevel, "..") == 0)
- return false;
- snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
- if (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode))
- return true;
- return false;
-}
-librc_hidden_def(rc_runlevel_exists)
-
-bool
-rc_runlevel_stack(const char *dst, const char *src)
-{
- char d[PATH_MAX], s[PATH_MAX];
-
- if (!rc_runlevel_exists(dst) || !rc_runlevel_exists(src))
- return false;
- snprintf(s, sizeof(s), "../%s", src);
- snprintf(d, sizeof(s), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
- return (symlink(s, d) == 0 ? true : false);
-}
-librc_hidden_def(rc_runlevel_stack)
-
-bool
-rc_runlevel_unstack(const char *dst, const char *src)
-{
- char path[PATH_MAX];
-
- snprintf(path, sizeof(path), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
- return (unlink(path) == 0 ? true : false);
-}
-librc_hidden_def(rc_runlevel_unstack)
-
-RC_STRINGLIST *
-rc_runlevel_stacks(const char *runlevel)
-{
- RC_STRINGLIST *stack;
- stack = rc_stringlist_new();
- get_runlevel_chain(runlevel, stack);
- return stack;
-}
-librc_hidden_def(rc_runlevel_stacks)
-
-/* Resolve a service name to its full path */
-char *
-rc_service_resolve(const char *service)
-{
- char buffer[PATH_MAX];
- char file[PATH_MAX];
- int r;
- struct stat buf;
-
- if (!service)
- return NULL;
-
- if (service[0] == '/')
- return xstrdup(service);
-
- /* First check started services */
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", "started", service);
- if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode)) {
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- "inactive", service);
- if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode))
- *file = '\0';
- }
-
- if (*file) {
- memset(buffer, 0, sizeof(buffer));
- r = readlink(file, buffer, sizeof(buffer));
- if (r > 0)
- return xstrdup(buffer);
- }
-
-#ifdef RC_LOCAL_INITDIR
- /* Nope, so lets see if the user has written it */
- snprintf(file, sizeof(file), RC_LOCAL_INITDIR "/%s", service);
- if (stat(file, &buf) == 0)
- return xstrdup(file);
-#endif
-
- /* System scripts take precedence over 3rd party ones */
- snprintf(file, sizeof(file), RC_INITDIR "/%s", service);
- if (stat(file, &buf) == 0)
- return xstrdup(file);
-
-#ifdef RC_PKG_INITDIR
- /* Check RC_PKG_INITDIR */
- snprintf(file, sizeof(file), RC_PKG_INITDIR "/%s", service);
- if (stat(file, &buf) == 0)
- return xstrdup(file);
-#endif
-
- return NULL;
-}
-librc_hidden_def(rc_service_resolve)
-
-bool
-rc_service_exists(const char *service)
-{
- char *file;
- bool retval = false;
- size_t len;
- struct stat buf;
-
- if (!service) {
- errno = EINVAL;
- return false;
- }
-
- len = strlen(service);
-
- /* .sh files are not init scripts */
- if (len > 2 && service[len - 3] == '.' &&
- service[len - 2] == 's' &&
- service[len - 1] == 'h') {
- errno = EINVAL;
- return false;
- }
-
- if (!(file = rc_service_resolve(service))) {
- errno = ENOENT;
- return false;
- }
-
- if (stat(file, &buf) == 0) {
- if (buf.st_mode & S_IXUGO)
- retval = true;
- else
- errno = ENOEXEC;
- }
- free(file);
- return retval;
-}
-librc_hidden_def(rc_service_exists)
-
-#define OPTSTR \
-". '%s'; echo $extra_commands $extra_started_commands $extra_stopped_commands"
-
-RC_STRINGLIST *
-rc_service_extra_commands(const char *service)
-{
- char *svc;
- char *cmd = NULL;
- char *buffer = NULL;
- size_t len = 0;
- RC_STRINGLIST *commands = NULL;
- 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"))) {
- rc_getline(&buffer, &len, fp);
- p = buffer;
- commands = rc_stringlist_new();
-
- while ((token = strsep(&p, " ")))
- if (token[0] != '\0')
- 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 *svc;
- char *cmd;
- char *desc = NULL;
- size_t len = 0;
- FILE *fp;
- size_t l;
-
- 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"))) {
- rc_getline(&desc, &len, fp);
- pclose(fp);
- }
- free(cmd);
- return desc;
-}
-librc_hidden_def(rc_service_description)
-
-bool
-rc_service_in_runlevel(const char *service, const char *runlevel)
-{
- char file[PATH_MAX];
-
- snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s",
- runlevel, basename_c(service));
- return exists(file);
-}
-librc_hidden_def(rc_service_in_runlevel)
-
-bool
-rc_service_mark(const char *service, const RC_SERVICE state)
-{
- char file[PATH_MAX];
- int i = 0;
- int skip_state = -1;
- const char *base;
- char *init = rc_service_resolve(service);
- bool skip_wasinactive = false;
- int s;
- char was[PATH_MAX];
- RC_STRINGLIST *dirs;
- RC_STRING *dir;
- int serrno;
-
- if (!init)
- return false;
-
- base = basename_c(service);
- if (state != RC_SERVICE_STOPPED) {
- if (!exists(init)) {
- free(init);
- return false;
- }
-
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- rc_parse_service_state(state), base);
- if (exists(file))
- unlink(file);
- i = symlink(init, file);
- if (i != 0) {
- free(init);
- return false;
- }
- skip_state = state;
- }
-
- if (state == RC_SERVICE_HOTPLUGGED || state == RC_SERVICE_FAILED) {
- free(init);
- return true;
- }
-
- /* Remove any old states now */
- for (i = 0; rc_service_state_names[i].name; i++) {
- s = rc_service_state_names[i].state;
-
- if ((s != skip_state &&
- s != RC_SERVICE_STOPPED &&
- s != RC_SERVICE_HOTPLUGGED &&
- s != RC_SERVICE_SCHEDULED) &&
- (! skip_wasinactive || s != RC_SERVICE_WASINACTIVE))
- {
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- rc_service_state_names[i].name, base);
- if (exists(file)) {
- if ((state == RC_SERVICE_STARTING ||
- state == RC_SERVICE_STOPPING) &&
- s == RC_SERVICE_INACTIVE)
- {
- snprintf(was, sizeof(was),
- RC_SVCDIR "/%s/%s",
- rc_parse_service_state(RC_SERVICE_WASINACTIVE),
- base);
- if (symlink(init, was) == -1)
- return false;
- skip_wasinactive = true;
- }
- if (unlink(file) == -1) {
- free(init);
- return false;
- }
- }
- }
- }
-
- /* Remove the exclusive state if we're inactive */
- if (state == RC_SERVICE_STARTED ||
- state == RC_SERVICE_STOPPED ||
- state == RC_SERVICE_INACTIVE)
- {
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- "exclusive", base);
- unlink(file);
- }
-
- /* Remove any options and daemons the service may have stored */
- if (state == RC_SERVICE_STOPPED) {
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- "options", base);
- rm_dir(file, true);
-
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- "daemons", base);
- rm_dir(file, true);
-
- rc_service_schedule_clear(service);
- }
-
- /* These are final states, so remove us from scheduled */
- if (state == RC_SERVICE_STARTED || state == RC_SERVICE_STOPPED) {
- snprintf(file, sizeof(file), RC_SVCDIR "/%s", "scheduled");
- dirs = ls_dir(file, 0);
- TAILQ_FOREACH(dir, dirs, entries) {
- snprintf(was, sizeof(was), "%s/%s/%s",
- file, dir->value, base);
- unlink(was);
-
- /* Try and remove the dir; we don't care about errors */
- snprintf(was, sizeof(was), "%s/%s", file, dir->value);
- serrno = errno;
- rmdir(was);
- errno = serrno;
- }
- rc_stringlist_free(dirs);
- }
- free(init);
- return true;
-}
-librc_hidden_def(rc_service_mark)
-
-RC_SERVICE
-rc_service_state(const char *service)
-{
- int i;
- int state = RC_SERVICE_STOPPED;
- char file[PATH_MAX];
- RC_STRINGLIST *dirs;
- RC_STRING *dir;
- const char *base = basename_c(service);
-
- for (i = 0; rc_service_state_names[i].name; i++) {
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- rc_service_state_names[i].name, base);
- 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;
- }
- }
-
- if (state & RC_SERVICE_STOPPED) {
- dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
- TAILQ_FOREACH(dir, dirs, entries) {
- snprintf(file, sizeof(file),
- RC_SVCDIR "/scheduled/%s/%s",
- dir->value, service);
- if (exists(file)) {
- state |= RC_SERVICE_SCHEDULED;
- break;
- }
- }
- rc_stringlist_free(dirs);
- }
-
- return state;
-}
-librc_hidden_def(rc_service_state)
-
-char *
-rc_service_value_get(const char *service, const char *option)
-{
- char *buffer = NULL;
- size_t len = 0;
- char file[PATH_MAX];
-
- snprintf(file, sizeof(file), RC_SVCDIR "/options/%s/%s",
- service, option);
- rc_getfile(file, &buffer, &len);
-
- return buffer;
-}
-librc_hidden_def(rc_service_value_get)
-
-bool
-rc_service_value_set(const char *service, const char *option,
- const char *value)
-{
- FILE *fp;
- char file[PATH_MAX];
- char *p = file;
-
- p += snprintf(file, sizeof(file), RC_SVCDIR "/options/%s", service);
- if (mkdir(file, 0755) != 0 && errno != EEXIST)
- return false;
-
- snprintf(p, sizeof(file) - (p - file), "/%s", option);
- if (!(fp = fopen(file, "w")))
- return false;
- if (value)
- fprintf(fp, "%s", value);
- fclose(fp);
- return true;
-}
-librc_hidden_def(rc_service_value_set)
-
-
-bool
-rc_service_schedule_start(const char *service, const char *service_to_start)
-{
- char file[PATH_MAX];
- char *p = file;
- char *init;
- bool retval;
-
- /* service may be a provided service, like net */
- if (! service || ! rc_service_exists(service_to_start))
- return false;
-
- p += snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s",
- basename_c(service));
- if (mkdir(file, 0755) != 0 && errno != EEXIST)
- return false;
-
- init = rc_service_resolve(service_to_start);
- snprintf(p, sizeof(file) - (p - file),
- "/%s", basename_c(service_to_start));
- retval = (exists(file) || symlink(init, file) == 0);
- free(init);
- return retval;
-}
-librc_hidden_def(rc_service_schedule_start)
-
-bool
-rc_service_schedule_clear(const char *service)
-{
- char dir[PATH_MAX];
-
- snprintf(dir, sizeof(dir), RC_SVCDIR "/scheduled/%s",
- basename_c(service));
- if (!rm_dir(dir, true) && errno == ENOENT)
- return true;
- return false;
-}
-librc_hidden_def(rc_service_schedule_clear)
-
-RC_STRINGLIST *
-rc_services_in_runlevel(const char *runlevel)
-{
- char dir[PATH_MAX];
- RC_STRINGLIST *list = NULL;
-
- if (!runlevel) {
-#ifdef RC_PKG_INITDIR
- RC_STRINGLIST *pkg = ls_dir(RC_PKG_INITDIR, LS_INITD);
-#endif
-#ifdef RC_LOCAL_INITDIR
- RC_STRINGLIST *local = ls_dir(RC_LOCAL_INITDIR, LS_INITD);
-#endif
-
- list = ls_dir(RC_INITDIR, LS_INITD);
-
-#ifdef RC_PKG_INITDIR
- TAILQ_CONCAT(list, pkg, entries);
- free(pkg);
-#endif
-#ifdef RC_LOCAL_INITDIR
- TAILQ_CONCAT(list, local, entries);
- free(local);
-#endif
- return list;
- }
-
- /* These special levels never contain any services */
- if (strcmp(runlevel, RC_LEVEL_SINGLE) != 0) {
- snprintf(dir, sizeof(dir), RC_RUNLEVELDIR "/%s", runlevel);
- list = ls_dir(dir, LS_INITD);
- }
- if (!list)
- list = rc_stringlist_new();
- return list;
-}
-librc_hidden_def(rc_services_in_runlevel)
-
-RC_STRINGLIST *
-rc_services_in_runlevel_stacked(const char *runlevel)
-{
- RC_STRINGLIST *list, *stacks, *sl;
- RC_STRING *stack;
-
- list = rc_services_in_runlevel(runlevel);
- stacks = rc_runlevel_stacks(runlevel);
- TAILQ_FOREACH(stack, stacks, entries) {
- sl = rc_services_in_runlevel(stack->value);
- TAILQ_CONCAT(list, sl, entries);
- free(sl);
- }
- return list;
-}
-librc_hidden_def(rc_services_in_runlevel_stacked)
-
-RC_STRINGLIST *
-rc_services_in_state(RC_SERVICE state)
-{
- RC_STRINGLIST *services;
- RC_STRINGLIST *list;
- RC_STRINGLIST *dirs;
- RC_STRING *d;
- char dir[PATH_MAX];
- char *p = dir;
-
- p += snprintf(dir, sizeof(dir), RC_SVCDIR "/%s",
- rc_parse_service_state(state));
-
- if (state != RC_SERVICE_SCHEDULED)
- return ls_dir(dir, LS_INITD);
-
- dirs = ls_dir(dir, 0);
- list = rc_stringlist_new();
- if (! dirs)
- return list;
-
- TAILQ_FOREACH(d, dirs, entries) {
- snprintf(p, sizeof(dir) - (p - dir), "/%s", d->value);
- services = ls_dir(dir, LS_INITD);
- if (services) {
- TAILQ_CONCAT(list, services, entries);
- free(services);
- }
- }
- rc_stringlist_free(dirs);
- return list;
-}
-librc_hidden_def(rc_services_in_state)
-
-bool
-rc_service_add(const char *runlevel, const char *service)
-{
- bool retval;
- char *init;
- char file[PATH_MAX];
- char path[MAXPATHLEN] = { '\0' };
- char *p = NULL;
- char binit[PATH_MAX];
- char *i;
-
- if (!rc_runlevel_exists(runlevel)) {
- errno = ENOENT;
- return false;
- }
-
- if (rc_service_in_runlevel(service, runlevel)) {
- errno = EEXIST;
- return false;
- }
-
- i = init = rc_service_resolve(service);
- snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s",
- runlevel, basename_c(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) {
- p = realpath(dirname(init), path);
- if (!*p) {
- free(init);
- return false;
- }
- if (strcmp(path, RC_INITDIR) != 0) {
- free(init);
- errno = EPERM;
- return false;
- }
- snprintf(binit, sizeof(binit), RC_INITDIR "/%s", service);
- i = binit;
- }
-
- retval = (symlink(i, file) == 0);
- free(init);
- return retval;
-}
-librc_hidden_def(rc_service_add)
-
-bool
-rc_service_delete(const char *runlevel, const char *service)
-{
- char file[PATH_MAX];
-
- snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s",
- runlevel, basename_c(service));
- if (unlink(file) == 0)
- return true;
- return false;
-}
-librc_hidden_def(rc_service_delete)
-
-RC_STRINGLIST *
-rc_services_scheduled_by(const char *service)
-{
- RC_STRINGLIST *dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
- RC_STRINGLIST *list = rc_stringlist_new();
- RC_STRING *dir;
- char file[PATH_MAX];
-
- TAILQ_FOREACH(dir, dirs, entries) {
- snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s/%s",
- dir->value, service);
- if (exists(file))
- rc_stringlist_add(list, file);
- }
- rc_stringlist_free(dirs);
- return list;
-}
-librc_hidden_def(rc_services_scheduled_by)
-
-RC_STRINGLIST *
-rc_services_scheduled(const char *service)
-{
- char dir[PATH_MAX];
-
- snprintf(dir, sizeof(dir), RC_SVCDIR "/scheduled/%s",
- basename_c(service));
- return ls_dir(dir, LS_INITD);
-}
-librc_hidden_def(rc_services_scheduled)
diff --git a/src/librc/librc.h b/src/librc/librc.h
deleted file mode 100644
index 0824eba7..00000000
--- a/src/librc/librc.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * librc.h
- * Internal header file to setup build env for files in librc.so
- */
-
-/*
- * Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
- *
- * 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_H_
-#define _LIBRC_H_
-
-#define _IN_LIBRC
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <limits.h>
-#include <paths.h>
-#include <regex.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <time.h>
-#include <unistd.h>
-
-#if defined(BSD) && !defined(__GNU__)
-#include <sys/param.h>
-#include <sys/user.h>
-#include <sys/sysctl.h>
-#include <kvm.h>
-#else
-#include <sys/param.h>
-#endif
-
-#include "rc.h"
-#include "rc-misc.h"
-
-#include "hidden-visibility.h"
-#define librc_hidden_proto(x) hidden_proto(x)
-#define librc_hidden_def(x) hidden_def(x)
-
-librc_hidden_proto(rc_conf_value)
-librc_hidden_proto(rc_config_list)
-librc_hidden_proto(rc_config_load)
-librc_hidden_proto(rc_config_value)
-librc_hidden_proto(rc_deptree_depend)
-librc_hidden_proto(rc_deptree_depends)
-librc_hidden_proto(rc_deptree_free)
-librc_hidden_proto(rc_deptree_load)
-librc_hidden_proto(rc_deptree_load_file)
-librc_hidden_proto(rc_deptree_order)
-librc_hidden_proto(rc_deptree_update)
-librc_hidden_proto(rc_deptree_update_needed)
-librc_hidden_proto(rc_find_pids)
-librc_hidden_proto(rc_getfile)
-librc_hidden_proto(rc_getline)
-librc_hidden_proto(rc_newer_than)
-librc_hidden_proto(rc_proc_getent)
-librc_hidden_proto(rc_older_than)
-librc_hidden_proto(rc_runlevel_exists)
-librc_hidden_proto(rc_runlevel_get)
-librc_hidden_proto(rc_runlevel_list)
-librc_hidden_proto(rc_runlevel_set)
-librc_hidden_proto(rc_runlevel_stack)
-librc_hidden_proto(rc_runlevel_stacks)
-librc_hidden_proto(rc_runlevel_starting)
-librc_hidden_proto(rc_runlevel_stopping)
-librc_hidden_proto(rc_runlevel_unstack)
-librc_hidden_proto(rc_service_add)
-librc_hidden_proto(rc_service_daemons_crashed)
-librc_hidden_proto(rc_service_daemon_set)
-librc_hidden_proto(rc_service_delete)
-librc_hidden_proto(rc_service_description)
-librc_hidden_proto(rc_service_exists)
-librc_hidden_proto(rc_service_extra_commands)
-librc_hidden_proto(rc_service_in_runlevel)
-librc_hidden_proto(rc_service_mark)
-librc_hidden_proto(rc_service_resolve)
-librc_hidden_proto(rc_service_schedule_clear)
-librc_hidden_proto(rc_service_schedule_start)
-librc_hidden_proto(rc_services_in_runlevel)
-librc_hidden_proto(rc_services_in_runlevel_stacked)
-librc_hidden_proto(rc_services_in_state)
-librc_hidden_proto(rc_services_scheduled)
-librc_hidden_proto(rc_services_scheduled_by)
-librc_hidden_proto(rc_service_started_daemon)
-librc_hidden_proto(rc_service_state)
-librc_hidden_proto(rc_service_value_get)
-librc_hidden_proto(rc_service_value_set)
-librc_hidden_proto(rc_stringlist_add)
-librc_hidden_proto(rc_stringlist_addu)
-librc_hidden_proto(rc_stringlist_delete)
-librc_hidden_proto(rc_stringlist_find)
-librc_hidden_proto(rc_stringlist_free)
-librc_hidden_proto(rc_stringlist_new)
-librc_hidden_proto(rc_stringlist_split)
-librc_hidden_proto(rc_stringlist_sort)
-librc_hidden_proto(rc_sys)
-librc_hidden_proto(rc_sys_v1)
-librc_hidden_proto(rc_sys_v2)
-librc_hidden_proto(rc_yesno)
-
-#endif
diff --git a/src/librc/rc.h.in b/src/librc/rc.h.in
deleted file mode 100644
index 58d8eb57..00000000
--- a/src/librc/rc.h.in
+++ /dev/null
@@ -1,619 +0,0 @@
-/*
- * Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
- *
- * 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 __RC_H__
-#define __RC_H__
-
-#include <sys/types.h>
-#include <stdbool.h>
-#include <stdio.h>
-
-/* __BEGIN_DECLS */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define RC_PREFIX "@PREFIX@"
-#define RC_SYSCONFDIR "@SYSCONFDIR@"
-#define RC_LIBDIR "@PREFIX@/@LIB@/rc"
-#define RC_LIBEXECDIR "@LIBEXECDIR@"
-#if defined(PREFIX)
-#define RC_SVCDIR RC_LIBEXECDIR "/init.d"
-#elif defined(__linux__) || (defined(__FreeBSD_kernel__) && \
- defined(__GLIBC__)) || defined(__GNU__)
-#define RC_SVCDIR "/run/openrc"
-#else
-#define RC_SVCDIR RC_LIBEXECDIR "/init.d"
-#endif
-#define RC_RUNLEVELDIR RC_SYSCONFDIR "/runlevels"
-#define RC_INITDIR RC_SYSCONFDIR "/init.d"
-#define RC_CONFDIR RC_SYSCONFDIR "/conf.d"
-#define RC_PLUGINDIR RC_LIBDIR "/plugins"
-
-#define RC_PROFILE_ENV RC_SYSCONFDIR "/profile.env"
-#define RC_SYS_WHITELIST RC_LIBEXECDIR "/conf.d/env_whitelist"
-#define RC_USR_WHITELIST RC_SYSCONFDIR "/conf.d/env_whitelist"
-#define RC_CONF RC_SYSCONFDIR "/rc.conf"
-#define RC_CONF_OLD RC_SYSCONFDIR "/conf.d/rc"
-
-#define RC_PATH_PREFIX RC_LIBEXECDIR "/bin:/bin:/sbin:/usr/bin:/usr/sbin"
-
-/* PKG_PREFIX is where packages are installed if different from the base OS
- * On Gentoo this is normally unset, on FreeBSD /usr/local and on NetBSD
- * /usr/pkg. */
-#define RC_PKG_PREFIX "@PKG_PREFIX@"
-#ifdef RC_PKG_PREFIX
-# define RC_PKG_INITDIR RC_PKG_PREFIX "/etc/init.d"
-# define RC_PKG_CONFDIR RC_PKG_PREFIX "/etc/conf.d"
-#endif
-
-/* LOCAL_PREFIX is for user written stuff, which the base OS and package
- * manger don't touch. */
-#define RC_LOCAL_PREFIX "@LOCAL_PREFIX@"
-#ifdef RC_LOCAL_PREFIX
-# define RC_LOCAL_INITDIR RC_LOCAL_PREFIX "/etc/init.d"
-# define RC_LOCAL_CONFDIR RC_LOCAL_PREFIX "/etc/conf.d"
-#endif
-
-#ifndef _SYS_QUEUE_H_
-
-/*
- * The following are copied directly from our imported queue.h.
- */
-
-/*
- * List definitions.
- */
-#define LIST_HEAD(name, type) \
-struct name { \
- struct type *lh_first; /* first element */ \
-}
-
-#define LIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define LIST_ENTRY(type) \
-struct { \
- struct type *le_next; /* next element */ \
- struct type **le_prev; /* address of previous next element */ \
-}
-
-/*
- * Tail queue definitions.
- */
-#define _TAILQ_HEAD(name, type, qual) \
-struct name { \
- qual type *tqh_first; /* first element */ \
- qual type *qual *tqh_last; /* addr of last next element */ \
-}
-#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
-
-#define TAILQ_HEAD_INITIALIZER(head) \
- { TAILQ_END(head), &(head).tqh_first }
-
-#define _TAILQ_ENTRY(type, qual) \
-struct { \
- qual type *tqe_next; /* next element */ \
- qual type *qual *tqe_prev; /* address of previous next element */\
-}
-#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
-
-#endif /* _SYS_QUEUE_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"
-#define RC_LEVEL_SHUTDOWN "shutdown"
-
-/*! Return the current runlevel.
- * @return the current runlevel */
-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 *);
-
-/*! Stack a runlevel onto another
- * @param runlevel to stack onto
- * @param runlevel being stacked
- * @return true if successful, otherwise false */
-bool rc_runlevel_stack(const char *, const char *);
-
-/*! Unstack a runlevel from another
- * @param runlevel to unstack from
- * @param runlevel being unstacked
- * @return true if successful, otherwise false */
-bool rc_runlevel_unstack(const char *, const char *);
-
-/*! Return a NULL terminated list of runlevel stacks in the runlevels
- * @return a NULL terminated list of runlevels */
-RC_STRINGLIST *rc_runlevel_stacks(const char *);
-
-/*! Return a NULL terminated list of runlevels
- * @return a NULL terminated list of runlevels */
-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 *);
-
-/*! Is the runlevel starting?
- * @return true if yes, otherwise false */
-bool rc_runlevel_starting(void);
-
-/*! Is the runlevel stopping?
- * @return true if yes, otherwise false */
-bool rc_runlevel_stopping(void);
-
-/*! @name RC
- * A service can be given as a full path or just its name.
- * If it's just a name then we try to resolve the service to a full path.
- * This should allow the use if local init.d directories in the future. */
-
-/*! @brief States a service can be in */
-typedef enum
-{
- /* These are actual states
- * The service has to be in one only at all times */
- RC_SERVICE_STOPPED = 0x0001,
- RC_SERVICE_STARTED = 0x0002,
- RC_SERVICE_STOPPING = 0x0004,
- RC_SERVICE_STARTING = 0x0008,
- RC_SERVICE_INACTIVE = 0x0010,
-
- /* Service may or may not have been hotplugged */
- RC_SERVICE_HOTPLUGGED = 0x0100,
-
- /* Optional states service could also be in */
- RC_SERVICE_FAILED = 0x0200,
- RC_SERVICE_SCHEDULED = 0x0400,
- RC_SERVICE_WASINACTIVE = 0x0800
-} 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 *, 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 *, const char *);
-
-/*! Save the arguments to find a running daemon
- * @param service to save arguments for
- * @param exec that we started
- * @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 *, const char *, const char *const *, 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 *, 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 *);
-
-/*! 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 *, 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 *, RC_SERVICE);
-
-/*! Lists the extra commands a service has
- * @param service to load the commands from
- * @return NULL terminated string list of commands */
-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 *);
-
-/*! 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 *, 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 */
-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 *);
-
-/*! Checks if a service in in a state
- * @param service to check
- * @return state of the service */
-RC_SERVICE rc_service_state(const char *);
-
-/*! Check if the service started the daemon
- * @param service to check
- * @param exec to check
- * @param argv 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 *, 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 *, 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 *, const char *, const char *);
-
-/*! List the services in a runlevel
- * @param runlevel to list
- * @return NULL terminated list of services */
-RC_STRINGLIST *rc_services_in_runlevel(const char *);
-
-/*! List the stacked services in a runlevel
- * @param runlevel to list
- * @return NULL terminated list of services */
-RC_STRINGLIST *rc_services_in_runlevel_stacked(const char *);
-
-/*! List the services in a state
- * @param state to list
- * @return NULL terminated list of services */
-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 */
-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 *);
-
-/*! @name System types
- * OpenRC can support some special sub system types, normally virtualization.
- * Some services cannot work in these systems, or we do something else. */
-#define RC_SYS_JAIL "JAIL"
-#define RC_SYS_OPENVZ "OPENVZ"
-#define RC_SYS_LXC "LXC"
-#define RC_SYS_PREFIX "PREFIX"
-#define RC_SYS_UML "UML"
-#define RC_SYS_VSERVER "VSERVER"
-#define RC_SYS_XEN0 "XEN0"
-#define RC_SYS_XENU "XENU"
-
-/*! Returns the type of subsystem
- * @return string from RC_SYS_* types or NULL if none detected */
-const char *rc_sys(void);
-
-/*! Returns the type of subsystem using old automatic code
- * @return string from RC_SYS_* types or NULL if none detected */
-const char *rc_sys_v1(void);
-
-/*! Returns the type of subsystem using new rc.conf rc_sys value
- * @return string from RC_SYS_* types or NULL if none detected */
-const char *rc_sys_v2(void);
-
-/*! @name Dependency options
- * These options can change the services found by the rc_get_depinfo and
- * rc_get_depends functions. */
-/*! Trace provided services */
-#define RC_DEP_TRACE (1<<0)
-/*! Only use services added to runlevels */
-#define RC_DEP_STRICT (1<<1)
-/*! Runlevel is starting */
-#define RC_DEP_START (1<<2)
-/*! Runlevel is stopping */
-#define RC_DEP_STOP (1<<3)
-
-/*! @name Dependencies
- * We analyse each init script and cache the resultant dependency tree.
- * This tree can be accessed using the below functions. */
-
-#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 */
- TAILQ_ENTRY(rc_deptype) entries;
-} RC_DEPTYPE;
-
-/*! Singly linked list of services and their dependencies */
-typedef struct rc_depinfo
-{
- /*! Name of service */
- char *service;
- /*! Dependencies */
- TAILQ_HEAD(, rc_deptype) depends;
- /*! List of entries */
- TAILQ_ENTRY(rc_depinfo) entries;
-} RC_DEPINFO;
-
-typedef TAILQ_HEAD(,rc_depinfo) RC_DEPTREE;
-#else
-/* Handles to internal structures */
-typedef void *RC_DEPTREE;
-#endif
-
-/*! Check to see if source is newer than target.
- * If target is a directory then we traverse it and its children.
- * @param source
- * @param target
- * @param mtime of newest target
- * @param filename of the newest target (needs mtime param)
- * @return true if source is newer than target, otherwise false */
-bool rc_newer_than(const char *, const char *, time_t *, char *);
-
-/*! Check to see if source is older than target.
- * If target is a directory then we traverse it and its children.
- * @param source
- * @param target
- * @param mtime of oldest target
- * @param filename of the oldest target (needs mtime param)
- * @return true if source is older than target, otherwise false */
-bool rc_older_than(const char *, const char *, time_t *, char *);
-
-/*! Read variables/values from /proc/cmdline
- * @param value
- * @return pointer to the value, otherwise NULL */
-char *rc_proc_getent(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.
- * time_t returns the time of the newest file that the dependency tree
- * will be checked against.
- * @return true if successful, otherwise false */
-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.
- * @param mtime of newest file
- * @param buffer of PATH_MAX to store newest file
- * @return true if it needs updating, otherwise false */
-bool rc_deptree_update_needed(time_t *, char *);
-
-/*! 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_DEPTREE *rc_deptree_load(void);
-
-/*! Load a cached dependency tree from the specified file and return a pointer
- * to it. This pointer should be freed with rc_deptree_free when done.
- * @return pointer to the dependency tree */
-RC_DEPTREE *rc_deptree_load_file(const char *);
-
-/*! 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 */
-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.
- * @param deptree to search
- * @param types to use (ineed, iuse, etc)
- * @param services to check
- * @param options to pass
- * @return NULL terminated list of services in order */
-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
- * approriate.
- * @param deptree to search
- * @param runlevel to change into
- * @param options to pass
- * @return NULL terminated list of services in order */
-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_DEPTREE *);
-
-/*! @name Plugins
- * For each plugin loaded we will call rc_plugin_hook with the below
- * enum and either the runlevel name or service name.
- *
- * Plugins are called when rc does something. This does not indicate an
- * end result and the plugin should use the above functions to query things
- * like service status.
- *
- * The service hooks have extra ones - now and done. This is because after
- * start_in we may start other services before we start the service in
- * question. now shows we really will start the service now and done shows
- * when we have done it as may start scheduled services at this point. */
-/*! Points at which a plugin can hook into RC */
-typedef enum
-{
- RC_HOOK_RUNLEVEL_STOP_IN = 1,
- RC_HOOK_RUNLEVEL_STOP_OUT = 4,
- RC_HOOK_RUNLEVEL_START_IN = 5,
- RC_HOOK_RUNLEVEL_START_OUT = 8,
- /*! We send the abort if an init script requests we abort and drop
- * into single user mode if system not fully booted */
- RC_HOOK_ABORT = 99,
- RC_HOOK_SERVICE_STOP_IN = 101,
- RC_HOOK_SERVICE_STOP_NOW = 102,
- RC_HOOK_SERVICE_STOP_DONE = 103,
- RC_HOOK_SERVICE_STOP_OUT = 104,
- RC_HOOK_SERVICE_START_IN = 105,
- RC_HOOK_SERVICE_START_NOW = 106,
- RC_HOOK_SERVICE_START_DONE = 107,
- RC_HOOK_SERVICE_START_OUT = 108
-} 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, const char *);
-
-/*! Plugins should write FOO=BAR to this fd to set any environment
- * variables they wish. Variables should be separated by NULLs. */
-extern FILE *rc_environ_fd;
-
-
-/*! Return a NULL terminated list of non comment lines from a file. */
-RC_STRINGLIST *rc_config_list(const char *);
-
-/*! Return a NULL terminated list of key=value lines from a file. */
-RC_STRINGLIST *rc_config_load(const char *);
-
-/*! Return the value of the entry from a key=value list. */
-char *rc_config_value(RC_STRINGLIST *, const char *);
-
-/*! Return the value of the entry from rc.conf. */
-char *rc_conf_value(const char *);
-
-/*! Check if a variable is a boolean and return its 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 *);
-
-/*! @name String List functions
- * 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 */
-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 */
-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_stringlist_delete(RC_STRINGLIST *, const char *);
-
-/*! Find the item on the list.
- * @param list to search
- * @param item to find.
- * @return pointer to item */
-RC_STRING *rc_stringlist_find(RC_STRINGLIST *, const char *);
-
-/*! Split a string into a stringlist based on separator.
- * @param string to split
- * @param separator
- * @return new list */
-RC_STRINGLIST *rc_stringlist_split(const char *, const char *);
-
-
-/*! 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_stringlist_free(RC_STRINGLIST *);
-
-typedef struct rc_pid
-{
- pid_t pid;
- LIST_ENTRY(rc_pid) entries;
-} RC_PID;
-typedef LIST_HEAD(rc_pidlist, rc_pid) RC_PIDLIST;
-
-/*! Find processes based on criteria.
- * All of these are optional.
- * pid overrides anything else.
- * If both exec and cmd are given then we ignore exec.
- * @param exec to check for
- * @param argv to check for
- * @param uid to check for
- * @param pid to check for
- * @return NULL terminated list of pids */
-RC_PIDLIST *rc_find_pids(const char *, const char *const *, uid_t, pid_t);
-
-/* Basically the same as rc_getline() below, it just returns multiple lines */
-bool rc_getfile(const char *, char **, size_t *);
-
-/* getline is a handy glibc function that not all libcs have, so
- * we have our own */
-ssize_t rc_getline(char **, size_t *, FILE *);
-
-/* __END_DECLS */
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/librc/rc.map b/src/librc/rc.map
deleted file mode 100644
index 2aa58dea..00000000
--- a/src/librc/rc.map
+++ /dev/null
@@ -1,68 +0,0 @@
-RC_1.0 {
-global:
- rc_conf_value;
- rc_config_list;
- rc_config_load;
- rc_config_value;
- rc_deptree_depend;
- rc_deptree_depends;
- rc_deptree_free;
- rc_deptree_load;
- rc_deptree_load_file;
- rc_deptree_order;
- rc_deptree_update;
- rc_deptree_update_needed;
- rc_environ_fd;
- rc_find_pids;
- rc_getfile;
- rc_getline;
- rc_newer_than;
- rc_older_than;
- rc_proc_getent;
- rc_runlevel_exists;
- rc_runlevel_get;
- rc_runlevel_list;
- rc_runlevel_set;
- rc_runlevel_stack;
- rc_runlevel_stacks;
- rc_runlevel_starting;
- rc_runlevel_stopping;
- rc_runlevel_unstack;
- rc_service_add;
- rc_service_daemons_crashed;
- rc_service_daemon_set;
- rc_service_delete;
- rc_service_description;
- rc_service_exists;
- rc_service_extra_commands;
- rc_service_in_runlevel;
- rc_service_mark;
- rc_service_options;
- rc_service_resolve;
- rc_service_schedule_clear;
- rc_service_schedule_start;
- rc_services_in_runlevel;
- rc_services_in_runlevel_stacked;
- rc_services_in_state;
- rc_services_scheduled;
- rc_services_scheduled_by;
- rc_service_started_daemon;
- rc_service_state;
- rc_service_value_get;
- rc_service_value_set;
- rc_stringlist_add;
- rc_stringlist_addu;
- rc_stringlist_delete;
- rc_stringlist_find;
- rc_stringlist_split;
- rc_stringlist_new;
- rc_stringlist_sort;
- rc_stringlist_free;
- rc_sys;
- rc_sys_v1;
- rc_sys_v2;
- rc_yesno;
-
-local:
- *;
-};