Remove null terminated char ** lists in favour of RC_STRINGLIST, using TAILQ from queue(3). Refactor code style around the BSD KNF.

This commit is contained in:
Roy Marples
2008-03-16 17:00:56 +00:00
parent 40e12f6ba0
commit cb9da6a262
41 changed files with 4675 additions and 5322 deletions

View File

@@ -3,12 +3,12 @@ librc.o
librc-daemon.o
librc-depend.o
librc-misc.o
librc-strlist.o
librc-stringlist.o
librc.So
librc-daemon.So
librc-depend.So
librc-misc.So
librc-strlist.So
librc-stringlist.So
librc.a
librc.so.1
librc.so

View File

@@ -4,7 +4,7 @@ include ${MK}/os.mk
LIB= rc
SHLIB_MAJOR= 1
SRCS= librc.c librc-daemon.c librc-depend.c librc-misc.c \
librc-strlist.c
librc-stringlist.c
INCS= rc.h
VERSION_MAP= rc.map

View File

@@ -32,33 +32,33 @@
#include "librc.h"
#if defined(__linux__)
static bool pid_is_cmd (pid_t pid, const char *cmd)
static bool pid_is_cmd(pid_t pid, const char *cmd)
{
char buffer[32];
FILE *fp;
int c;
snprintf(buffer, sizeof (buffer), "/proc/%d/stat", pid);
if ((fp = fopen (buffer, "r")) == NULL)
return (false);
snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
if ((fp = fopen(buffer, "r")) == NULL)
return false;
while ((c = getc (fp)) != EOF && c != '(')
while ((c = getc(fp)) != EOF && c != '(')
;
if (c != '(') {
fclose(fp);
return (false);
return false;
}
while ((c = getc (fp)) != EOF && c == *cmd)
while ((c = getc(fp)) != EOF && c == *cmd)
cmd++;
fclose (fp);
fclose(fp);
return ((c == ')' && *cmd == '\0') ? true : false);
return (c == ')' && *cmd == '\0') ? true : false;
}
static bool pid_is_exec (pid_t pid, const char *const *argv)
static bool pid_is_exec(pid_t pid, const char *const *argv)
{
char cmdline[32];
char buffer[PATH_MAX];
@@ -66,31 +66,30 @@ static bool pid_is_exec (pid_t pid, const char *const *argv)
int fd = -1;
int r;
/* Check it's the right binary */
snprintf (cmdline, sizeof (cmdline), "/proc/%u/exe", pid);
memset (buffer, 0, sizeof (buffer));
#if 0
if (readlink (cmdline, buffer, sizeof (buffer)) != -1) {
if (strcmp (exec, buffer) == 0)
return (true);
if (readlink(cmdline, buffer, sizeof(buffer)) != -1) {
if (strcmp(*argv, buffer) == 0)
return true;
/* We should cater for deleted binaries too */
if (strlen (buffer) > 10) {
p = buffer + (strlen (buffer) - 10);
if (strcmp (p, " (deleted)") == 0) {
if (strlen(buffer) > 10) {
p = buffer + (strlen(buffer) - 10);
if (strcmp(p, " (deleted)") == 0) {
*p = 0;
if (strcmp (buffer, exec) == 0)
return (true);
if (strcmp(buffer, *argv) == 0)
return true;
}
}
}
#endif
snprintf (cmdline, sizeof (cmdline), "/proc/%u/cmdline", pid);
if ((fd = open (cmdline, O_RDONLY)) < 0)
return (false);
snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
if ((fd = open(cmdline, O_RDONLY)) < 0)
return false;
r = read (fd, buffer, sizeof (buffer));
close (fd);
r = read(fd, buffer, sizeof(buffer));
close(fd);
if (r == -1)
return 0;
@@ -98,18 +97,18 @@ static bool pid_is_exec (pid_t pid, const char *const *argv)
buffer[r] = 0;
p = buffer;
while (*argv) {
if (strcmp (*argv, p) != 0)
return (false);
if (strcmp(*argv, p) != 0)
return false;
argv++;
p += strlen (p) + 1;
p += strlen(p) + 1;
if ((unsigned) (p - buffer) > sizeof (buffer))
return (false);
return false;
}
return (true);
return true;
}
pid_t *rc_find_pids (const char *const *argv, const char *cmd,
uid_t uid, pid_t pid)
pid_t *rc_find_pids(const char *const *argv, const char *cmd,
uid_t uid, pid_t pid)
{
DIR *procdir;
struct dirent *entry;
@@ -122,8 +121,8 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
pid_t runscript_pid = 0;
char *pp;
if ((procdir = opendir ("/proc")) == NULL)
return (NULL);
if ((procdir = opendir("/proc")) == NULL)
return NULL;
/*
We never match RC_RUNSCRIPT_PID if present so we avoid the below
@@ -136,13 +135,13 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
nasty
*/
if ((pp = getenv ("RC_RUNSCRIPT_PID"))) {
if (sscanf (pp, "%d", &runscript_pid) != 1)
if ((pp = getenv("RC_RUNSCRIPT_PID"))) {
if (sscanf(pp, "%d", &runscript_pid) != 1)
runscript_pid = 0;
}
while ((entry = readdir (procdir)) != NULL) {
if (sscanf (entry->d_name, "%d", &p) != 1)
while ((entry = readdir(procdir)) != NULL) {
if (sscanf(entry->d_name, "%d", &p) != 1)
continue;
if (runscript_pid != 0 && runscript_pid == p)
@@ -152,23 +151,23 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
continue;
if (uid) {
snprintf (buffer, sizeof (buffer), "/proc/%d", p);
if (stat (buffer, &sb) != 0 || sb.st_uid != uid)
snprintf(buffer, sizeof(buffer), "/proc/%d", p);
if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
continue;
}
if (cmd && ! pid_is_cmd (p, cmd))
if (cmd && ! pid_is_cmd(p, cmd))
continue;
if (argv && ! cmd && ! pid_is_exec (p, (const char *const *)argv))
if (argv && ! cmd && ! pid_is_exec(p, (const char *const *)argv))
continue;
tmp = realloc (pids, sizeof (pid_t) * (npids + 2));
tmp = realloc(pids, sizeof (pid_t) * (npids + 2));
if (! tmp) {
free (pids);
closedir (procdir);
free(pids);
closedir(procdir);
errno = ENOMEM;
return (NULL);
return NULL;
}
pids = tmp;
@@ -176,9 +175,9 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
pids[npids + 1] = 0;
npids++;
}
closedir (procdir);
closedir(procdir);
return (pids);
return pids;
}
librc_hidden_def(rc_find_pids)
@@ -206,8 +205,8 @@ librc_hidden_def(rc_find_pids)
# define _KVM_FLAGS O_RDONLY
# endif
pid_t *rc_find_pids (const char *const *argv, const char *cmd,
uid_t uid, pid_t pid)
pid_t *rc_find_pids(const char *const *argv, const char *cmd,
uid_t uid, pid_t pid)
{
static kvm_t *kd = NULL;
char errbuf[_POSIX2_LINE_MAX];
@@ -218,44 +217,45 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
char **pargv;
pid_t *pids = NULL;
pid_t *tmp;
pid_t p;
const char *const *arg;
int npids = 0;
int match;
if ((kd = kvm_openfiles (_KVM_PATH, _KVM_PATH,
NULL, _KVM_FLAGS, errbuf)) == NULL)
if ((kd = kvm_openfiles(_KVM_PATH, _KVM_PATH,
NULL, _KVM_FLAGS, errbuf)) == NULL)
{
fprintf (stderr, "kvm_open: %s\n", errbuf);
return (NULL);
fprintf(stderr, "kvm_open: %s\n", errbuf);
return NULL;
}
#ifdef _KVM_GETPROC2
kp = kvm_getproc2 (kd, KERN_PROC_ALL, 0, sizeof(*kp), &processes);
kp = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(*kp), &processes);
#else
kp = kvm_getprocs (kd, KERN_PROC_PROC, 0, &processes);
kp = kvm_getprocs(kd, KERN_PROC_PROC, 0, &processes);
#endif
if ((kp == NULL && processes > 0) || (kp != NULL && processes < 0)) {
fprintf (stderr, "kvm_getprocs: %s\n", kvm_geterr (kd));
kvm_close (kd);
return (NULL);
fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd));
kvm_close(kd);
return NULL;
}
for (i = 0; i < processes; i++) {
pid_t p = _GET_KINFO_PID (kp[i]);
p = _GET_KINFO_PID(kp[i]);
if (pid != 0 && pid != p)
continue;
if (uid != 0 && uid != _GET_KINFO_UID (kp[i]))
if (uid != 0 && uid != _GET_KINFO_UID(kp[i]))
continue;
if (cmd) {
if (! _GET_KINFO_COMM (kp[i]) ||
strcmp (cmd, _GET_KINFO_COMM (kp[i])) != 0)
if (! _GET_KINFO_COMM(kp[i]) ||
strcmp(cmd, _GET_KINFO_COMM(kp[i])) != 0)
continue;
}
if (argv && *argv && ! cmd) {
pargv = _KVM_GETARGV (kd, &kp[i], pargc);
pargv = _KVM_GETARGV(kd, &kp[i], pargc);
if (! pargv || ! *pargv)
continue;
@@ -263,7 +263,7 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
match = 1;
while (*arg && *pargv)
if (strcmp (*arg++, *pargv++) != 0) {
if (strcmp(*arg++, *pargv++) != 0) {
match = 0;
break;
}
@@ -272,12 +272,12 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
continue;
}
tmp = realloc (pids, sizeof (pid_t) * (npids + 2));
tmp = realloc(pids, sizeof(pid_t) * (npids + 2));
if (! tmp) {
free (pids);
kvm_close (kd);
free(pids);
kvm_close(kd);
errno = ENOMEM;
return (NULL);
return NULL;
}
pids = tmp;
@@ -285,9 +285,9 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
pids[npids + 1] = 0;
npids++;
}
kvm_close (kd);
kvm_close(kd);
return (pids);
return pids;
}
librc_hidden_def(rc_find_pids)
@@ -295,67 +295,72 @@ librc_hidden_def(rc_find_pids)
# error "Platform not supported!"
#endif
static bool _match_daemon (const char *path, const char *file, char **match)
static bool _match_daemon(const char *path, const char *file,
RC_STRINGLIST *match)
{
char *line;
char *ffile = rc_strcatpaths (path, file, (char *) NULL);
char *ffile = rc_strcatpaths(path, file, (char *) NULL);
FILE *fp;
RC_STRING *m;
fp = fopen (ffile, "r");
free (ffile);
fp = fopen(ffile, "r");
free(ffile);
if (! fp)
return (false);
return false;
while ((line = rc_getline (fp))) {
rc_strlist_delete (&match, line);
if (! match || !*match)
while ((line = rc_getline(fp))) {
TAILQ_FOREACH(m, match, entries)
if (strcmp(line, m->value) == 0) {
TAILQ_REMOVE(match, m, entries);
break;
}
if (! TAILQ_FIRST(match))
break;
}
fclose (fp);
if (match && *match)
return (false);
return (true);
fclose(fp);
if (TAILQ_FIRST(match))
return false;
return true;
}
static char **_match_list (const char* const* argv,
const char *name, const char *pidfile)
static RC_STRINGLIST *_match_list(const char* const* argv,
const char *name, const char *pidfile)
{
char **match = NULL;
RC_STRINGLIST *match = rc_stringlist_new();
int i = 0;
size_t l;
char *m;
while (argv && argv[i]) {
l = strlen (*argv) + strlen ("argv_=") + 16;
m = xmalloc (sizeof (char) * l);
snprintf (m, l, "argv_0=%s", argv[i++]);
rc_strlist_add (&match, m);
free (m);
l = strlen(*argv) + strlen("argv_=") + 16;
m = xmalloc(sizeof(char) * l);
snprintf(m, l, "argv_0=%s", argv[i++]);
rc_stringlist_add(match, m);
free(m);
}
if (name) {
l = strlen (name) + 6;
m = xmalloc (sizeof (char) * l);
snprintf (m, l, "name=%s", name);
rc_strlist_add (&match, m);
free (m);
l = strlen(name) + 6;
m = xmalloc(sizeof (char) * l);
snprintf(m, l, "name=%s", name);
rc_stringlist_add(match, m);
free(m);
}
if (pidfile) {
l = strlen (pidfile) + 9;
m = xmalloc (sizeof (char) * l);
snprintf (m, l, "pidfile=%s", pidfile);
rc_strlist_add (&match, m);
l = strlen(pidfile) + 9;
m = xmalloc(sizeof (char) * l);
snprintf(m, l, "pidfile=%s", pidfile);
rc_stringlist_add(match, m);
free (m);
}
return (match);
return match;
}
bool rc_service_daemon_set (const char *service, const char *const *argv,
const char *name, const char *pidfile,
bool started)
bool rc_service_daemon_set(const char *service, const char *const *argv,
const char *name, const char *pidfile, bool started)
{
char *dirpath;
char *file = NULL;
@@ -364,123 +369,123 @@ bool rc_service_daemon_set (const char *service, const char *const *argv,
bool retval = false;
DIR *dp;
struct dirent *d;
char **match = NULL;
RC_STRINGLIST *match;
int i = 0;
char buffer[10];
FILE *fp;
if (! (argv && *argv) && ! name && ! pidfile) {
if (!(argv && *argv) && ! name && ! pidfile) {
errno = EINVAL;
return (false);
return false;
}
dirpath = rc_strcatpaths (RC_SVCDIR, "daemons",
basename_c (service), (char *) NULL);
dirpath = rc_strcatpaths(RC_SVCDIR, "daemons",
basename_c(service), (char *) NULL);
match = _match_list (argv, name, pidfile);
match = _match_list(argv, name, pidfile);
/* Regardless, erase any existing daemon info */
if ((dp = opendir (dirpath))) {
while ((d = readdir (dp))) {
if ((dp = opendir(dirpath))) {
while ((d = readdir(dp))) {
if (d->d_name[0] == '.')
continue;
file = rc_strcatpaths (dirpath, d->d_name, (char *) NULL);
file = rc_strcatpaths(dirpath, d->d_name, (char *) NULL);
nfiles++;
if (! oldfile) {
if (_match_daemon (dirpath, d->d_name, match)) {
if (_match_daemon(dirpath, d->d_name, match)) {
unlink (file);
oldfile = file;
nfiles--;
}
} else {
rename (file, oldfile);
free (oldfile);
rename(file, oldfile);
free(oldfile);
oldfile = file;
}
}
free (file);
closedir (dp);
free(file);
closedir(dp);
}
/* Now store our daemon info */
if (started) {
char buffer[10];
FILE *fp;
if (mkdir (dirpath, 0755) == 0 || errno == EEXIST) {
snprintf (buffer, sizeof (buffer), "%03d", nfiles + 1);
file = rc_strcatpaths (dirpath, buffer, (char *) NULL);
if ((fp = fopen (file, "w"))) {
if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
snprintf(buffer, sizeof(buffer), "%03d", nfiles + 1);
file = rc_strcatpaths(dirpath, buffer, (char *) NULL);
if ((fp = fopen(file, "w"))) {
while (argv && argv[i]) {
fprintf (fp, "argv_%d=%s\n", i, argv[i]);
fprintf(fp, "argv_%d=%s\n", i, argv[i]);
i++;
}
fprintf (fp, "name=");
fprintf(fp, "name=");
if (name)
fprintf (fp, "%s", name);
fprintf (fp, "\npidfile=");
fprintf(fp, "%s", name);
fprintf(fp, "\npidfile=");
if (pidfile)
fprintf (fp, "%s", pidfile);
fprintf (fp, "\n");
fclose (fp);
fprintf(fp, "%s", pidfile);
fprintf(fp, "\n");
fclose(fp);
retval = true;
}
free (file);
free(file);
}
} else
retval = true;
rc_strlist_free (match);
free (dirpath);
rc_stringlist_free(match);
free(dirpath);
return (retval);
return retval;
}
librc_hidden_def(rc_service_daemon_set)
bool rc_service_started_daemon (const char *service, const char *const *argv,
int indx)
bool
rc_service_started_daemon (const char *service, const char *const *argv,
int indx)
{
char *dirpath;
char *file;
size_t l;
char **match;
RC_STRINGLIST *match;
bool retval = false;
DIR *dp;
struct dirent *d;
if (! service || ! (argv && *argv))
return (false);
if (!service || !(argv && *argv))
return false;
dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename_c (service),
(char *) NULL);
dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", basename_c(service),
(char *) NULL);
match = _match_list (argv, NULL, NULL);
match = _match_list(argv, NULL, NULL);
if (indx > 0) {
l = sizeof (char) * 10;
file = xmalloc (l);
snprintf (file, l, "%03d", indx);
retval = _match_daemon (dirpath, file, match);
free (file);
file = xmalloc(l);
snprintf(file, l, "%03d", indx);
retval = _match_daemon(dirpath, file, match);
free(file);
} else {
if ((dp = opendir (dirpath))) {
while ((d = readdir (dp))) {
if ((dp = opendir(dirpath))) {
while ((d = readdir(dp))) {
if (d->d_name[0] == '.')
continue;
retval = _match_daemon (dirpath, d->d_name, match);
retval = _match_daemon(dirpath, d->d_name, match);
if (retval)
break;
}
closedir (dp);
closedir(dp);
}
}
free (dirpath);
rc_strlist_free (match);
return (retval);
free(dirpath);
rc_stringlist_free(match);
return retval;
}
librc_hidden_def(rc_service_started_daemon)
bool rc_service_daemons_crashed (const char *service)
bool rc_service_daemons_crashed(const char *service)
{
char *dirpath;
DIR *dp;
@@ -497,116 +502,123 @@ bool rc_service_daemons_crashed (const char *service)
char *p;
char *token;
bool retval = false;
RC_STRINGLIST *list;
RC_STRING *s;
size_t i;
if (! service)
return (false);
dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", basename_c(service),
(char *) NULL);
dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename_c (service),
(char *) NULL);
if (! (dp = opendir (dirpath))) {
free (dirpath);
return (false);
if (! (dp = opendir(dirpath))) {
free(dirpath);
return false;
}
while ((d = readdir (dp))) {
while ((d = readdir(dp))) {
if (d->d_name[0] == '.')
continue;
path = rc_strcatpaths (dirpath, d->d_name, (char *) NULL);
fp = fopen (path, "r");
free (path);
path = rc_strcatpaths(dirpath, d->d_name, (char *) NULL);
fp = fopen(path, "r");
free(path);
if (! fp)
break;
while ((line = rc_getline (fp))) {
list = rc_stringlist_new();
while ((line = rc_getline(fp))) {
p = line;
if ((token = strsep (&p, "=")) == NULL || ! p) {
free (line);
if ((token = strsep(&p, "=")) == NULL || ! p) {
free(line);
continue;
}
if (strlen (p) == 0) {
free (line);
if (! *p) {
free(line);
continue;
}
if (strncmp (token, "argv_", 5) == 0) {
rc_strlist_add (&argv, p);
} else if (strcmp (token, "exec") == 0) {
if (strncmp(token, "argv_", 5) == 0) {
rc_stringlist_add(list, p);
} else if (strcmp(token, "exec") == 0) {
if (exec)
free (exec);
exec = xstrdup (p);
} else if (strcmp (token, "name") == 0) {
free(exec);
exec = xstrdup(p);
} else if (strcmp(token, "name") == 0) {
if (name)
free (name);
name = xstrdup (p);
} else if (strcmp (token, "pidfile") == 0) {
free(name);
name = xstrdup(p);
} else if (strcmp(token, "pidfile") == 0) {
if (pidfile)
free (pidfile);
pidfile = xstrdup (p);
free(pidfile);
pidfile = xstrdup(p);
}
free (line);
free(line);
}
fclose (fp);
fclose(fp);
pid = 0;
if (pidfile) {
if (! exists (pidfile)) {
if (! exists(pidfile)) {
retval = true;
break;
}
if ((fp = fopen (pidfile, "r")) == NULL) {
if ((fp = fopen(pidfile, "r")) == NULL) {
retval = true;
break;
}
if (fscanf (fp, "%d", &pid) != 1) {
if (fscanf(fp, "%d", &pid) != 1) {
fclose (fp);
retval = true;
break;
}
fclose (fp);
free (pidfile);
fclose(fp);
free(pidfile);
pidfile = NULL;
/* We have the pid, so no need to match on name */
rc_strlist_free (argv);
argv = NULL;
rc_stringlist_free(list);
list = NULL;
free (exec);
exec = NULL;
free (name);
name = NULL;
}
if (exec && ! argv) {
rc_strlist_add (&argv, exec);
free (exec);
} else {
if (exec && ! TAILQ_FIRST(list)) {
rc_stringlist_add(list, exec);
}
free(exec);
exec = NULL;
/* 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 ((pids = rc_find_pids ((const char *const *)argv, name, 0, pid)) == NULL) {
if ((pids = rc_find_pids((const char *const *)argv, name, 0, pid)) == NULL)
retval = true;
break;
}
free (pids);
rc_strlist_free (argv);
free(pids);
free(argv);
argv = NULL;
free (exec);
exec = NULL;
free (name);
rc_stringlist_free(list);
free(name);
name = NULL;
if (retval)
break;
}
rc_strlist_free (argv);
free (exec);
free (name);
free (dirpath);
closedir (dp);
free(dirpath);
closedir(dp);
return (retval);
return retval;
}
librc_hidden_def(rc_service_daemons_crashed)

File diff suppressed because it is too large Load Diff

View File

@@ -1,61 +0,0 @@
/*
* librc-depend.h
* Internal header file for dependency structures
*/
/*
* Copyright 2007-2008 Roy Marples
* All rights reserved
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _LIBRC_DEPEND_H
#define _LIBRC_DEPEND_H
/*! @name Dependency structures
* private to librc - rc.h exposes them just a pointers */
/*! Singly linked list of dependency types that list the services the
* type is for */
typedef struct rc_deptype
{
/*! ineed, iuse, iafter, etc */
char *type;
/*! NULL terminated list of services */
char **services;
/*! Next dependency type */
struct rc_deptype *next;
} rc_deptype_t;
/*! Singly linked list of services and their dependencies */
typedef struct rc_depinfo
{
/*! Name of service */
char *service;
/*! Dependencies */
rc_deptype_t *depends;
/*! Next service dependency type */
struct rc_depinfo *next;
} rc_depinfo_t;
#endif

View File

@@ -35,14 +35,14 @@ bool rc_yesno (const char *value)
{
if (! value) {
errno = ENOENT;
return (false);
return false;
}
if (strcasecmp (value, "yes") == 0 ||
strcasecmp (value, "y") == 0 ||
strcasecmp (value, "true") == 0 ||
strcasecmp (value, "1") == 0)
return (true);
return true;
if (strcasecmp (value, "no") != 0 &&
strcasecmp (value, "n") != 0 &&
@@ -50,7 +50,7 @@ bool rc_yesno (const char *value)
strcasecmp (value, "0") != 0)
errno = EINVAL;
return (false);
return false;
}
librc_hidden_def(rc_yesno)
@@ -64,7 +64,7 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...)
char *pathp;
if (! path1 || ! paths)
return (NULL);
return NULL;
length = strlen (path1) + strlen (paths) + 1;
if (*paths != '/')
@@ -101,7 +101,7 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...)
*pathp++ = 0;
return (path);
return path;
}
librc_hidden_def(rc_strcatpaths)
@@ -113,7 +113,7 @@ char *rc_getline (FILE *fp)
size_t last = 0;
if (feof (fp))
return (NULL);
return NULL;
do {
len += BUFSIZ;
@@ -128,74 +128,78 @@ char *rc_getline (FILE *fp)
if (*line && line[--last] == '\n')
line[last] = '\0';
return (line);
return line;
}
librc_hidden_def(rc_getline)
char **rc_config_list (const char *file)
RC_STRINGLIST *rc_config_list(const char *file)
{
FILE *fp;
char *buffer;
char *p;
char *token;
char **list = NULL;
RC_STRINGLIST *list;
if (! (fp = fopen (file, "r")))
return (NULL);
if (!(fp = fopen(file, "r")))
return NULL;
while ((p = buffer = rc_getline (fp))) {
list = rc_stringlist_new();
while ((p = buffer = rc_getline(fp))) {
/* Strip leading spaces/tabs */
while ((*p == ' ') || (*p == '\t'))
p++;
/* Get entry - we do not want comments */
token = strsep (&p, "#");
if (token && (strlen (token) > 1)) {
token = strsep(&p, "#");
if (token && (strlen(token) > 1)) {
/* If not variable assignment then skip */
if (strchr (token, '=')) {
if (strchr(token, '=')) {
/* Stip the newline if present */
if (token[strlen (token) - 1] == '\n')
token[strlen (token) - 1] = 0;
if (token[strlen(token) - 1] == '\n')
token[strlen(token) - 1] = 0;
rc_strlist_add (&list, token);
rc_stringlist_add(list, token);
}
}
free (buffer);
free(buffer);
}
fclose (fp);
fclose(fp);
return (list);
return list;
}
librc_hidden_def(rc_config_list)
char **rc_config_load (const char *file)
RC_STRINGLIST *rc_config_load(const char *file)
{
char **list = NULL;
char **config = NULL;
RC_STRINGLIST *list = NULL;
RC_STRINGLIST *config = NULL;
char *token;
char *line;
char *linep;
char *linetok;
RC_STRING *line;
RC_STRING *cline;
size_t i = 0;
int j;
bool replaced;
char *entry;
char *newline;
char *p;
list = rc_config_list (file);
STRLIST_FOREACH (list, line, j) {
config = rc_stringlist_new();
list = rc_config_list(file);
TAILQ_FOREACH(line, list, entries) {
/* Get entry */
if (! (token = strsep (&line, "=")))
p = line->value;
if (! (token = strsep(&p, "=")))
continue;
entry = xstrdup (token);
/* Preserve shell coloring */
if (*line == '$')
token = line;
if (*p == '$')
token = line->value;
else
do {
/* Bash variables are usually quoted */
token = strsep (&line, "\"\'");
token = strsep(&p, "\"\'");
} while (token && *token == '\0');
/* Drop a newline if that's all we have */
@@ -205,57 +209,54 @@ char **rc_config_load (const char *file)
token[i] = 0;
i = strlen (entry) + strlen (token) + 2;
newline = xmalloc (sizeof (char) * i);
snprintf (newline, i, "%s=%s", entry, token);
newline = xmalloc(sizeof(char) * i);
snprintf(newline, i, "%s=%s", entry, token);
} else {
i = strlen (entry) + 2;
newline = xmalloc (sizeof (char) * i);
snprintf (newline, i, "%s=", entry);
newline = xmalloc(sizeof(char) * i);
snprintf(newline, i, "%s=", entry);
}
replaced = false;
/* In shells the last item takes precedence, so we need to remove
any prior values we may already have */
STRLIST_FOREACH (config, line, i) {
char *tmp = xstrdup (line);
linep = tmp;
linetok = strsep (&linep, "=");
if (strcmp (linetok, entry) == 0) {
TAILQ_FOREACH(cline, config, entries) {
p = strchr(cline->value, '=');
if (p && strncmp(entry, cline->value,
(size_t) (p - cline->value)) == 0)
{
/* We have a match now - to save time we directly replace it */
free (config[i - 1]);
config[i - 1] = newline;
free(cline->value);
cline->value = newline;
replaced = true;
free (tmp);
break;
}
free (tmp);
}
if (! replaced) {
rc_strlist_addsort (&config, newline);
free (newline);
rc_stringlist_add(config, newline);
free(newline);
}
free (entry);
free(entry);
}
rc_strlist_free (list);
rc_stringlist_free(list);
return (config);
return config;
}
librc_hidden_def(rc_config_load)
char *rc_config_value (const char *const *list, const char *entry)
char *rc_config_value(RC_STRINGLIST *list, const char *entry)
{
const char *line;
int i;
RC_STRING *line;
char *p;
STRLIST_FOREACH (list, line, i) {
p = strchr (line, '=');
if (p && strncmp (entry, line, (size_t) (p - line)) == 0)
return (p += 1);
TAILQ_FOREACH(line, list, entries) {
p = strchr(line->value, '=');
if (p &&
strncmp(entry, line->value, (size_t)(p - line->value)) == 0)
return p += 1;
}
return (NULL);
return NULL;
}
librc_hidden_def(rc_config_value)

View File

@@ -1,230 +0,0 @@
/*
librc-strlist.h
String list functions for using char ** arrays
Based on a previous implementation by Martin Schlemmer
*/
/*
* Copyright 2007-2008 Roy Marples
* All rights reserved
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "librc.h"
static char *_rc_strlist_add (char ***list, const char *item, bool uniq)
{
char **newlist;
char **lst = *list;
int i = 0;
if (! item)
return (NULL);
while (lst && lst[i]) {
if (uniq && strcmp (lst[i], item) == 0) {
errno = EEXIST;
return (NULL);
}
i++;
}
newlist = xrealloc (lst, sizeof (char *) * (i + 2));
newlist[i] = xstrdup (item);
newlist[i + 1] = NULL;
*list = newlist;
return (newlist[i]);
}
char *rc_strlist_add (char ***list, const char *item)
{
return (_rc_strlist_add (list, item, false));
}
librc_hidden_def(rc_strlist_add)
char *rc_strlist_addu (char ***list, const char *item)
{
return (_rc_strlist_add (list, item, true));
}
librc_hidden_def(rc_strlist_addu)
static char *_rc_strlist_addsort (char ***list, const char *item,
int (*sortfunc) (const char *s1,
const char *s2),
bool uniq)
{
char **newlist;
char **lst = *list;
int i = 0;
char *tmp1;
char *tmp2;
char *retval;
if (! item)
return (NULL);
while (lst && lst[i]) {
if (uniq && strcmp (lst[i], item) == 0) {
errno = EEXIST;
return (NULL);
}
i++;
}
newlist = xrealloc (lst, sizeof (char *) * (i + 2));
if (! i)
newlist[i] = NULL;
newlist[i + 1] = NULL;
i = 0;
while (newlist[i] && sortfunc (newlist[i], item) < 0)
i++;
tmp1 = newlist[i];
retval = newlist[i] = xstrdup (item);
do {
i++;
tmp2 = newlist[i];
newlist[i] = tmp1;
tmp1 = tmp2;
} while (tmp1);
*list = newlist;
return (retval);
}
char *rc_strlist_addsort (char ***list, const char *item)
{
return (_rc_strlist_addsort (list, item, strcoll, false));
}
librc_hidden_def(rc_strlist_addsort)
char *rc_strlist_addsortc (char ***list, const char *item)
{
return (_rc_strlist_addsort (list, item, strcmp, false));
}
librc_hidden_def(rc_strlist_addsortc)
char *rc_strlist_addsortu (char ***list, const char *item)
{
return (_rc_strlist_addsort (list, item, strcmp, true));
}
librc_hidden_def(rc_strlist_addsortu)
bool rc_strlist_delete (char ***list, const char *item)
{
char **lst = *list;
int i = 0;
if (!lst || ! item)
return (false);
while (lst[i]) {
if (strcmp (lst[i], item) == 0) {
free (lst[i]);
do {
lst[i] = lst[i + 1];
i++;
} while (lst[i]);
return (true);
}
i++;
}
errno = ENOENT;
return (false);
}
librc_hidden_def(rc_strlist_delete)
char *rc_strlist_join (char ***list1, char **list2)
{
char **lst1 = *list1;
char **newlist;
int i = 0;
int j = 0;
if (! list2)
return (NULL);
while (lst1 && lst1[i])
i++;
while (list2[j])
j++;
newlist = xrealloc (lst1, sizeof (char *) * (i + j + 1));
j = 0;
while (list2[j]) {
newlist[i] = list2[j];
/* Take the item off the 2nd list as it's only a shallow copy */
list2[j] = NULL;
i++;
j++;
}
newlist[i] = NULL;
*list1 = newlist;
return (newlist[i == 0 ? 0 : i - 1]);
}
librc_hidden_def(rc_strlist_join)
void rc_strlist_reverse (char **list)
{
char *item;
int i = 0;
int j = 0;
if (! list)
return;
while (list[j])
j++;
j--;
while (i < j && list[i] && list[j]) {
item = list[i];
list[i] = list[j];
list[j] = item;
i++;
j--;
}
}
librc_hidden_def(rc_strlist_reverse)
void rc_strlist_free (char **list)
{
int i = 0;
if (! list)
return;
while (list[i])
free (list[i++]);
free (list);
}
librc_hidden_def(rc_strlist_free)

File diff suppressed because it is too large Load Diff

View File

@@ -64,10 +64,8 @@
#include <kvm.h>
#endif
#include "librc-depend.h"
#include "rc.h"
#include "rc-misc.h"
#include "strlist.h"
#include "hidden-visibility.h"
#define librc_hidden_proto(x) hidden_proto(x)
@@ -115,15 +113,11 @@ librc_hidden_proto(rc_service_state)
librc_hidden_proto(rc_service_value_get)
librc_hidden_proto(rc_service_value_set)
librc_hidden_proto(rc_strcatpaths)
librc_hidden_proto(rc_strlist_add)
librc_hidden_proto(rc_strlist_addu)
librc_hidden_proto(rc_strlist_addsort)
librc_hidden_proto(rc_strlist_addsortc)
librc_hidden_proto(rc_strlist_addsortu)
librc_hidden_proto(rc_strlist_delete)
librc_hidden_proto(rc_strlist_free)
librc_hidden_proto(rc_strlist_join)
librc_hidden_proto(rc_strlist_reverse)
librc_hidden_proto(rc_stringlist_add)
librc_hidden_proto(rc_stringlist_addu)
librc_hidden_proto(rc_stringlist_delete)
librc_hidden_proto(rc_stringlist_free)
librc_hidden_proto(rc_stringlist_sort)
librc_hidden_proto(rc_yesno)
#endif

View File

@@ -32,15 +32,24 @@
# if (GCC_VERSION >= 3005)
# define SENTINEL __attribute__ ((__sentinel__))
# endif
# define DEPRECATED __attribute__ ((deprecated))
#endif
#ifndef SENTINEL
# define SENTINEL
#endif
#include <sys/types.h>
#include <sys/queue.h>
#include <stdbool.h>
#include <stdio.h>
/* A doubly linked list using queue(3) for ease of use */
typedef struct rc_string {
char *value;
TAILQ_ENTRY(rc_string) entries;
} RC_STRING;
typedef TAILQ_HEAD(rc_stringlist, rc_string) RC_STRINGLIST;
/*! @name Reserved runlevel names */
#define RC_LEVEL_SYSINIT "sysinit"
#define RC_LEVEL_SINGLE "single"
@@ -49,30 +58,30 @@
/*! Return the current runlevel.
* @return the current runlevel */
char *rc_runlevel_get (void);
char *rc_runlevel_get(void);
/*! Checks if the runlevel exists or not
* @param runlevel to check
* @return true if the runlevel exists, otherwise false */
bool rc_runlevel_exists (const char *runlevel);
bool rc_runlevel_exists(const char *);
/*! Return a NULL terminated list of runlevels
* @return a NULL terminated list of runlevels */
char **rc_runlevel_list (void);
RC_STRINGLIST *rc_runlevel_list(void);
/*! Set the runlevel.
* This just changes the stored runlevel and does not start or stop any
* services.
* @param runlevel to store */
bool rc_runlevel_set (const char *runlevel);
bool rc_runlevel_set(const char *);
/*! Is the runlevel starting?
* @return true if yes, otherwise false */
bool rc_runlevel_starting (void);
bool rc_runlevel_starting(void);
/*! Is the runlevel stopping?
* @return true if yes, otherwise false */
bool rc_runlevel_stopping (void);
bool rc_runlevel_stopping(void);
/*! @name RC
* A service can be given as a full path or just its name.
@@ -97,19 +106,19 @@ typedef enum
RC_SERVICE_FAILED = 0x0200,
RC_SERVICE_SCHEDULED = 0x0400,
RC_SERVICE_WASINACTIVE = 0x0800
} rc_service_state_t;
} RC_SERVICE;
/*! Add the service to the runlevel
* @param runlevel to add to
* @param service to add
* @return true if successful, otherwise false */
bool rc_service_add (const char *runlevel, const char *service);
bool rc_service_add(const char *, const char *);
/*! Remove the service from the runlevel
* @param runlevel to remove from
* @param service to remove
* @return true if sucessful, otherwise false */
bool rc_service_delete (const char *runlevel, const char *service);
bool rc_service_delete(const char *, const char *);
/*! Save the arguments to find a running daemon
* @param service to save arguments for
@@ -117,116 +126,113 @@ bool rc_service_delete (const char *runlevel, const char *service);
* @param name of the process (optional)
* @param pidfile of the process (optional)
* @param started if true, add the arguments otherwise remove existing matching arguments */
bool rc_service_daemon_set (const char *service, const char *const *argv,
const char *name, const char *pidfile,
bool started);
bool rc_service_daemon_set(const char *, const char *const *, const char *, const char *,
bool);
/*! Returns a description of what the service and/or option does.
* @param service to check
* @param option to check (if NULL, service description)
* @return a newly allocated pointer to the description */
char *rc_service_description (const char *service, const char *option);
char *rc_service_description(const char *, const char *);
/*! Checks if a service exists or not.
* @param service to check
* @return true if service exists, otherwise false */
bool rc_service_exists (const char *service);
bool rc_service_exists(const char *);
/*! Checks if a service is in a runlevel
* @param service to check
* @param runlevel it should be in
* @return true if service is in the runlevel, otherwise false */
bool rc_service_in_runlevel (const char *service, const char *runlevel);
bool rc_service_in_runlevel(const char *, const char *);
/*! Marks the service state
* @param service to mark
* @param state service should be in
* @return true if service state change was successful, otherwise false */
bool rc_service_mark (const char *service, rc_service_state_t state);
bool rc_service_mark(const char *, RC_SERVICE);
/*! Lists the extra commands a service has
* @param service to load the commands from
* @return NULL terminated string list of commands */
char **rc_service_extra_commands (const char *service);
RC_STRINGLIST *rc_service_extra_commands(const char *);
/*! Resolves a service name to its full path.
* @param service to check
* @return pointer to full path of service */
char *rc_service_resolve (const char *service);
char *rc_service_resolve(const char *);
/*! Schedule a service to be started when another service starts
* @param service that starts the scheduled service when started
* @param service_to_start service that will be started */
bool rc_service_schedule_start (const char *service,
const char *service_to_start);
bool rc_service_schedule_start(const char *, const char *);
/*! Return a NULL terminated list of services that are scheduled to start
* when the given service has started
* @param service to check
* @return NULL terminated list of services scheduled to start */
char **rc_services_scheduled_by (const char *service);
RC_STRINGLIST *rc_services_scheduled_by(const char *);
/*! Clear the list of services scheduled to be started by this service
* @param service to clear
* @return true if no errors, otherwise false */
bool rc_service_schedule_clear (const char *service);
bool rc_service_schedule_clear(const char *);
/*! Checks if a service in in a state
* @param service to check
* @return state of the service */
rc_service_state_t rc_service_state (const char *service);
RC_SERVICE rc_service_state(const char *);
/*! Start a service
* @param service to start
* @return pid of the service starting process */
pid_t rc_service_start (const char *service);
pid_t rc_service_start(const char *);
/*! Stop a service
* @param service to stop
* @return pid of service stopping process */
pid_t rc_service_stop (const char *service);
pid_t rc_service_stop(const char *);
/*! Check if the service started the daemon
* @param service to check
* @param exec to check
* @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc)
* @return true if started by this service, otherwise false */
bool rc_service_started_daemon (const char *service, const char *const *argv,
int indx);
bool rc_service_started_daemon(const char *, const char *const *, int);
/*! Return a saved value for a service
* @param service to check
* @param option to load
* @return saved value */
char *rc_service_value_get (const char *service, const char *option);
char *rc_service_value_get(const char *, const char *);
/*! Save a persistent value for a service
* @param service to save for
* @param option to save
* @param value of the option
* @return true if saved, otherwise false */
bool rc_service_value_set (const char *service, const char *option,
const char *value);
bool rc_service_value_set(const char *, const char *, const char *);
/*! List the services in a runlevel
* @param runlevel to list
* @return NULL terminated list of services */
char **rc_services_in_runlevel (const char *runlevel);
RC_STRINGLIST *rc_services_in_runlevel(const char *);
/*! List the services in a state
* @param state to list
* @return NULL terminated list of services */
char **rc_services_in_state (rc_service_state_t state);
RC_STRINGLIST *rc_services_in_state(RC_SERVICE);
/*! List the services shceduled to start when this one does
* @param service to check
* @return NULL terminated list of services */
char **rc_services_scheduled (const char *service);
RC_STRINGLIST *rc_services_scheduled(const char *);
/*! Checks that all daemons started with start-stop-daemon by the service
* are still running.
* @param service to check
* @return true if all daemons started are still running, otherwise false */
bool rc_service_daemons_crashed (const char *service);
bool rc_service_daemons_crashed(const char *);
/*! @name System types
* OpenRC can support some special sub system types, normally virtualization.
@@ -238,7 +244,7 @@ bool rc_service_daemons_crashed (const char *service);
#define RC_SYS_VSERVER "VSERVER"
#define RC_SYS_XEN0 "XEN0"
#define RC_SYS_XENU "XENU"
const char *rc_sys (void);
const char *rc_sys(void);
/*! @name Dependency options
* These options can change the services found by the rc_get_depinfo and
@@ -256,40 +262,67 @@ const char *rc_sys (void);
* We analyse each init script and cache the resultant dependency tree.
* This tree can be accessed using the below functions. */
#ifndef _IN_LIBRC
#ifdef _IN_LIBRC
/*! @name Dependency structures
* private to librc */
/*! Singly linked list of dependency types that list the services the
* type is for */
typedef struct rc_deptype
{
/*! ineed, iuse, iafter, etc */
char *type;
/*! list of services */
RC_STRINGLIST *services;
/*! list of types */
STAILQ_ENTRY(rc_deptype) entries;
} RC_DEPTYPE;
/*! Singly linked list of services and their dependencies */
typedef struct rc_depinfo
{
/*! Name of service */
char *service;
/*! Dependencies */
STAILQ_HEAD(, rc_deptype) depends;
/*! List of entries */
STAILQ_ENTRY(rc_depinfo) entries;
} RC_DEPINFO;
typedef STAILQ_HEAD(,rc_depinfo) RC_DEPTREE;
#else
/* Handles to internal structures */
typedef void *rc_depinfo_t;
typedef void *RC_DEPTREE;
#endif
/*! Check to see if source is newer than target.
* If target is a directory then we traverse it and it's children.
* @return true if source is newer than target, otherwise false */
bool rc_newer_than (const char *source, const char *target);
bool rc_newer_than(const char *, const char *);
/*! Update the cached dependency tree if it's older than any init script,
* its configuration file or an external configuration file the init script
* has specified.
* @return true if successful, otherwise false */
bool rc_deptree_update (void);
bool rc_deptree_update(void);
/*! Check if the cached dependency tree is older than any init script,
* its configuration file or an external configuration file the init script
* has specified.
* @return true if it needs updating, otherwise false */
bool rc_deptree_update_needed (void);
bool rc_deptree_update_needed(void);
/*! Load the cached dependency tree and return a pointer to it.
* This pointer should be freed with rc_deptree_free when done.
* @return pointer to the dependency tree */
rc_depinfo_t *rc_deptree_load (void);
RC_DEPTREE *rc_deptree_load(void);
/*! List the depend for the type of service
* @param deptree to search
* @param type to use (keywords, etc)
* @param service to check
* @return NULL terminated list of services in order */
char **rc_deptree_depend (const rc_depinfo_t *deptree,
const char *type, const char *service);
RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *, const char *, const char *);
/*! List all the services in order that the given services have
* for the given types and options.
@@ -298,10 +331,8 @@ char **rc_deptree_depend (const rc_depinfo_t *deptree,
* @param services to check
* @param options to pass
* @return NULL terminated list of services in order */
char **rc_deptree_depends (const rc_depinfo_t *deptree,
const char *const *types,
const char *const *services, const char *runlevel,
int options);
RC_STRINGLIST *rc_deptree_depends(const RC_DEPTREE *, const RC_STRINGLIST *,
const RC_STRINGLIST *, const char *, int);
/*! List all the services that should be stoppned and then started, in order,
* for the given runlevel, including sysinit and boot services where
@@ -310,12 +341,11 @@ char **rc_deptree_depends (const rc_depinfo_t *deptree,
* @param runlevel to change into
* @param options to pass
* @return NULL terminated list of services in order */
char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel,
int options);
RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *, const char *, int);
/*! Free a deptree and its information
* @param deptree to free */
void rc_deptree_free (rc_depinfo_t *deptree);
void rc_deptree_free(RC_DEPTREE *);
/*! @name Plugins
* For each plugin loaded we will call rc_plugin_hook with the below
@@ -347,13 +377,13 @@ typedef enum
RC_HOOK_SERVICE_START_NOW = 106,
RC_HOOK_SERVICE_START_DONE = 107,
RC_HOOK_SERVICE_START_OUT = 108
} rc_hook_t;
} RC_HOOK;
/*! Plugin entry point
* @param hook point
* @param name of runlevel or service
* @return 0 for success otherwise -1 */
int rc_plugin_hook (rc_hook_t hook, const char *name);
int rc_plugin_hook(RC_HOOK, const char *);
/*! Plugins should write FOO=BAR to this fd to set any environment
* variables they wish. Variables should be separated by NULLs. */
@@ -362,91 +392,64 @@ extern FILE *rc_environ_fd;
/*! @name Configuration
* These functions help to deal with shell based configuration files */
/*! Return a line from a file, stripping the trailing newline. */
char *rc_getline (FILE *fp);
char *rc_getline(FILE *);
/*! Return a NULL terminated list of non comment lines from a file. */
char **rc_config_list (const char *file);
RC_STRINGLIST *rc_config_list(const char *);
/*! Return a NULL terminated list of key=value lines from a file. */
char **rc_config_load (const char *file);
RC_STRINGLIST *rc_config_load(const char *);
/*! Return the value of the entry from a key=value list. */
char *rc_config_value (const char *const *list, const char *entry);
char *rc_config_value(RC_STRINGLIST *, const char *);
/*! Check if a variable is a boolean and return it's value.
* If variable is not a boolean then we set errno to be ENOENT when it does
* not exist or EINVAL if it's not a boolean.
* @param variable to check
* @return true if it matches true, yes or 1, false if otherwise. */
bool rc_yesno (const char *variable);
bool rc_yesno(const char *);
/*! @name String List functions
* Handy functions for dealing with string arrays of char **.
* It's safe to assume that any function here that uses char ** is a string
* list that can be manipulated with the below functions. Every string list
* should be released with a call to rc_strlist_free. */
* Every string list should be released with a call to rc_stringlist_free. */
/*! Create a new stringlinst
* @return pointer to new list */
RC_STRINGLIST *rc_stringlist_new(void);
/*! Duplicate the item, add it to end of the list and return a pointer to it.
* @param list to add the item too
* @param item to add.
* @return pointer to newly added item */
char *rc_strlist_add (char ***list, const char *item);
RC_STRING *rc_stringlist_add(RC_STRINGLIST *, const char *);
/*! If the item does not exist in the list, duplicate it, add it to the
* list and then return a pointer to it.
* @param list to add the item too
* @param item to add.
* @return pointer to newly added item */
char *rc_strlist_addu (char ***list, const char *item);
/*! Duplicate the item, add it to the list at the point based on locale and
* then return a pointer to it.
* @param list to add the item too
* @param item to add.
* @return pointer to newly added item */
char *rc_strlist_addsort (char ***list, const char *item);
/*! Duplicate the item, add it to the list at the point based on C locale and
* then return a pointer to it.
* @param list to add the item too
* @param item to add.
* @return pointer to newly added item */
char *rc_strlist_addsortc (char ***list, const char *item);
/*! If the item does not exist in the list, duplicate it, add it to the
* list based on locale and then return a pointer to it.
* @param list to add the item too
* @param item to add.
* @return pointer to newly added item */
char *rc_strlist_addsortu (char ***list, const char *item);
RC_STRING *rc_stringlist_addu(RC_STRINGLIST *, const char *);
/*! Free the item and remove it from the list. Return 0 on success otherwise -1.
* @param list to add the item too
* @param item to add.
* @return true on success, otherwise false */
bool rc_strlist_delete (char ***list, const char *item);
bool rc_stringlist_delete(RC_STRINGLIST *, const char *);
/*! Moves the contents of list2 onto list1, so list2 is effectively emptied.
* Returns a pointer to the last item on the new list.
* @param list1 to append to
* @param list2 to move from
* @return pointer to the last item on the list */
char *rc_strlist_join (char ***list1, char **list2);
/*! Reverses the contents of the list.
* @param list to reverse */
void rc_strlist_reverse (char **list);
/*! Sort the list according to C locale
* @param list to sort */
void rc_stringlist_sort(RC_STRINGLIST **);
/*! Frees each item on the list and the list itself.
* @param list to free */
void rc_strlist_free (char **list);
void rc_stringlist_free(RC_STRINGLIST *);
/*! Concatenate paths adding '/' if needed. The resultant pointer should be
* freed when finished with.
* @param path1 starting path
* @param paths NULL terminated list of paths to add
* @return pointer to the new path */
char *rc_strcatpaths (const char *path1, const char *paths, ...) SENTINEL;
char *rc_strcatpaths(const char *, const char *, ...) SENTINEL;
/*! Find processes based on criteria.
* All of these are optional.
@@ -457,7 +460,6 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...) SENTINEL;
* @param uid to check for
* @param pid to check for
* @return NULL terminated list of pids */
pid_t *rc_find_pids (const char *const *argv, const char *cmd,
uid_t uid, pid_t pid);
pid_t *rc_find_pids(const char *const *, const char *, uid_t, pid_t);
#endif

View File

@@ -43,15 +43,12 @@ global:
rc_service_value_get;
rc_service_value_set;
rc_strcatpaths;
rc_strlist_add;
rc_strlist_addu;
rc_strlist_addsort;
rc_strlist_addsortc;
rc_strlist_addsortu;
rc_strlist_delete;
rc_strlist_free;
rc_strlist_join;
rc_strlist_reverse;
rc_stringlist_add;
rc_stringlist_addu;
rc_stringlist_delete;
rc_stringlist_new;
rc_stringlist_sort;
rc_stringlist_free;
rc_sys;
rc_yesno;